diff --git a/src/button.py b/src/button.py new file mode 100644 index 0000000..e254574 --- /dev/null +++ b/src/button.py @@ -0,0 +1,67 @@ +import pygame + +class Button: + def __init__(self, text, width, height, pos_x, pos_y, color, hover): + """ + + :param text: Text inside the button. + :param width: Width of the button. + :param height: Height of the button. + :param pos_x: X position of the button on the screen. + :param pos_y: Y position of the button on the screen. + :param color: Color of the button on the screen. + :param hover: Color of the button on the screen when mouse is hover. + """ + self.text = text + self.width = width + self.height = height + self.pos_x = pos_x + self.pos_y = pos_y + self.color = color + self.hover = hover + + # create rectangle for button + self.rect = pygame.Rect(self.pos_x, self.pos_y, self.width, self.height) + + # set font for button text + self.font = pygame.font.SysFont("Arial", 30) + + # temp var to stor click event - so it will be executed just once + self.clicked = False + + def draw(self, screen): + """ + Draw the button on the screen. + :param screen: Screen object where button will be drawn. + :return: Return True when button was clicked. + """ + action = False + + # get current mous position + mouse_pos = pygame.mouse.get_pos() + + # check if mouse is over button + if self.rect.collidepoint(mouse_pos): + current_color = self.hover + + # check if left mouse button is pressed + if pygame.mouse.get_pressed()[0] == 1: + self.clicked = True + if pygame.mouse.get_pressed()[0] == 0 and self.clicked: + self.clicked = False + action = True + else: + current_color = self.color + self.clicked = False + + # draw buttton + pygame.draw.rect(screen, current_color, self.rect, border_radius = 12) + + # render button text + text_surface = self.font.render(self.text, True, (255, 255, 255)) + + # place text in the middle of the button + text_rect = text_surface.get_rect(center=self.rect.center) + screen.blit(text_surface, text_rect) + + return action \ No newline at end of file diff --git a/src/ects.py b/src/ects.py new file mode 100644 index 0000000..e746c12 --- /dev/null +++ b/src/ects.py @@ -0,0 +1,26 @@ +import pygame + +from src.settings import START_ECTS_VALUE, ECTS_UPDATE_INTERVAL + +class ECTS: + def __init__(self): + # total amount of ECTS the player has at the beginning + self.ects_balance = 0 + # start amount of ECTS player gains ber interval at the beginning + self.ects_per_second = START_ECTS_VALUE + # timer when last ECTS was given to player + self.last_update_time = pygame.time.get_ticks() + + # check if ECTS should be added + def update(self, is_at_desk): + current_time = pygame.time.get_ticks() + + # if player is at desk and interval passed + if is_at_desk and ((current_time - self.last_update_time) >= ECTS_UPDATE_INTERVAL): + self.ects_balance += self.ects_per_second + # reset timer + self.last_update_time = current_time + + # beer increases amount of how much ECTS are earned per second + def upgrade_rate(self, extra_ects): + self.ects_per_second += extra_ects diff --git a/src/hud.py b/src/hud.py new file mode 100644 index 0000000..e69de29 diff --git a/src/settings.py b/src/settings.py index fa3fabf..e19f541 100644 --- a/src/settings.py +++ b/src/settings.py @@ -4,7 +4,6 @@ from typing import Mapping, Literal, Tuple DESK_WIDTH = 70 DESK_HEIGHT = 40 - # --- DOOR --- DOOR_WIDTH = 20 DOOR_HEIGHT = 100 @@ -31,3 +30,64 @@ DIRECTION_FRAMES: Mapping[Direction, Tuple[int, int, int]] = { # Default drawing size and animation speed. DEFAULT_SPRITE_HEIGHT: int = 138 DEFAULT_FRAME_TIME: float = 0.16 +======= + +# --- ECTS --- +START_ECTS_VALUE = 1 # how many ECTS are generated at the beginning +ECTS_UPDATE_INTERVAL = 1000 # time in ms = 1 sec + +BEER_BOTTLE_ECTS_VALUE = 2 +BEER_COST = 50 + +# --- BUTTONS --- +COLOR_BUTTON = (0, 255, 0) +COLOR_BUTTON_HOVER = (200, 255, 0) + +# --- STARTSCREEN --- +COLOR_STARTSCREEN_BACKGROUND = ((0, 0, 0)) +COLOR_STARTSCREEN_FONT_TITLE = (0, 255, 0) +COLOR_STARTSCREEN_FONT_LABEL = (0, 255, 255) + + +# --- COFFEE --- +COFFEE_COST = 30 +COFFEE_HEAL_VALUE = 30 + +# --- TOWER --- +TOWER_COST = 150 +PROJECTILE_DMG = 15 +PROJECTILE_SPEED = 7 +COLOR_PROJECTILE = (200, 200, 0) +TOWER_TIMER = 30000 # how long the tower stays and attack before it disappears + + +# --- SHOPPING TIMER --- +ITEM_SHOPPING_TIMER = 10000 # for items like coffee, beer, tower - how long u have time to buy it + + +# -- ZOMBIE --- +ZOMBIE_EASY_HP = 30 +ZOMBIE_EASY_DMG = 3 + +ZOMBIE_MEDIUM_HP = 60 +ZOMBIE_MEDIUM_DMG = 7 + +ZOMBIE_HARD_HP = 120 +ZOMBIE_HARD_DMG = 12 + + +# --- HUD --- +HUD_FONT = "Arial" +HUD_FONT_SIZE = 22 +HUD_FONT_BOLD = True + +COLOR_HUD_TEXT = (255, 255, 255) +COLOR_HUD_SHOP_TEXT = (200, 200, 200) + +COLOR_HP_BAR_GREEN = (0, 255, 0) +COLOR_HP_BAR_BG = (50, 50, 50) +COLOR_HP_BAR_RED = (200, 0, 0) +COLOR_HP_BAR_YELLOW = (255, 255, 0) + +HUD_BAR_WIDTH = 100 +HUD_BAR_HEIGHT = 15 diff --git a/src/startscreen.py b/src/startscreen.py new file mode 100644 index 0000000..1e9c34a --- /dev/null +++ b/src/startscreen.py @@ -0,0 +1,156 @@ +import pygame +from button import Button +from settings import (COLOR_BUTTON, + COLOR_BUTTON_HOVER, + COLOR_STARTSCREEN_BACKGROUND, + COLOR_STARTSCREEN_FONT_TITLE, + COLOR_STARTSCREEN_FONT_LABEL) +from text_input import TextInput + +class Startscreen: + def __init__(self, screen): + self.screen = screen + self.font_title = pygame.font.SysFont("Arial", 36) + self.font_label = pygame.font.SysFont("Arial", 20) + + self.button_color = COLOR_BUTTON + self.button_hover_color = COLOR_BUTTON_HOVER + + self.player_name = "" + self.wrong_name = False + + self.button_start = Button("[ENTER] Matriculate", + 500, + 70, + 20, + 100, + self.button_color, + self.button_hover_color) + + self.button_quit = Button("[ESC] Exmatriculate", + 500, + 70, + 20, + 190, + self.button_color, + self.button_hover_color) + + self.text_input_name = TextInput(400, + 40, + 20, + 310) + + def run(self): + # set background color + self.screen.fill(COLOR_STARTSCREEN_BACKGROUND) + + # set title and intro/welcome message + title = self.font_title.render("SILENT FH", True, COLOR_STARTSCREEN_FONT_TITLE) + self.screen.blit(title, (10, 10)) + message_1 = self.font_label.render("Welcome to Silent FH", True, COLOR_STARTSCREEN_FONT_LABEL) + message_2 = self.font_label.render("Study with purpose. Survive with Coffee.", True, + COLOR_STARTSCREEN_FONT_LABEL) + + self.screen.blit(message_1, (10, 50)) + self.screen.blit(message_2, (10, 70)) + + # draw buttons and get click state + button_start_pressed = self.button_start.draw(self.screen) + button_quit_pressed = self.button_quit.draw(self.screen) + + # draw text input box + label_input = self.font_label.render("Enter your student name or ID:", True, + COLOR_STARTSCREEN_FONT_LABEL) + self.screen.blit(label_input, (10, 280)) + self.text_input_name.draw(self.screen) + + # prepare error message when no input was submitted + label_input_error = self.font_label.render("Student not found. Please enter valid name/id.", True, + (255, 0, 0)) + + # get all events + events = pygame.event.get() + + # react on button clicks + if button_start_pressed: + self.player_name = self.text_input_name.get_text() + + if self.player_name.strip() != "": + print("Spielername:", self.player_name) + return "game" + else: + self.wrong_name = True + if button_quit_pressed: + return "quit" + + # check events + for event in events: + if event.type == pygame.QUIT: + return "quit" + + # forward event to text input box + self.text_input_name.handle_event(event) + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + return "quit" + + if event.key == pygame.K_RETURN: + self.player_name = self.text_input_name.get_text() + + if self.player_name.strip() != "": + print("Spielername:", self.player_name) + return "game" + else: + self.wrong_name = True + + if self.wrong_name: + self.screen.blit(label_input_error, (10, 350)) + + return "startscreen" + + +# test function fro temporary testing +if __name__ == "__main__": + pygame.init() + + screen = pygame.display.set_mode((960, 640)) + pygame.display.set_caption("Silent FH - Startscreen Test") + + clock = pygame.time.Clock() + + startscreen = Startscreen(screen) + state = "startscreen" + + running = True + + while running: + clock.tick(60) + + if state == "startscreen": + state = startscreen.run() + + elif state == "game": + screen.fill((30, 30, 30)) + + font = pygame.font.SysFont("Arial", 36) + text = font.render("GAME STARTED", True, (255, 255, 255)) + screen.blit(text, (300, 280)) + + info = font.render("Press ESC to quit", True, (150, 150, 150)) + screen.blit(info, (300, 330)) + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + state = "quit" + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + state = "quit" + + elif state == "quit": + running = False + + pygame.display.flip() + + pygame.quit() \ No newline at end of file diff --git a/src/text_input.py b/src/text_input.py new file mode 100644 index 0000000..64acc25 --- /dev/null +++ b/src/text_input.py @@ -0,0 +1,61 @@ +import pygame + +class TextInput: + def __init__(self, width, height, pos_x, pos_y): + self.rect = pygame.Rect(pos_x, pos_y, width, height) + + self.font = pygame.font.SysFont("Arial", 22) + + # input text + self.text = "" + + self.active = False + + # colors + self.text_color = (255, 255, 255) + self.border_color = (255, 255, 255) + self.active_border_color = (0, 255, 0) + self.background_color = (30, 30, 30) + + def handle_event(self, event): + # check if mouse click event on text input box + if event.type == pygame.MOUSEBUTTONDOWN: + if self.rect.collidepoint(event.pos): + self.active = True + else: + self.active = False + + # check for keyboard input + if event.type == pygame.KEYDOWN and self.active: + # enter will submit and exit input box + if event.key == pygame.K_RETURN: + self.active = False + + # backspace will delete last character + elif event.key == pygame.K_BACKSPACE: + self.text = self.text[:-1] + # other characters will be added to the string + else: + self.text += event.unicode + + def draw(self, screen): + # draw background of input box + pygame.draw.rect(screen, self.background_color, self.rect) + + # change border color depending if input box is active or not + if self.active: + border_color = self.active_border_color + else: + border_color = self.border_color + + # draw border + pygame.draw.rect(screen, border_color, self.rect, 2) + + # draw text + text_surface = self.font.render(self.text, True, self.text_color) + + # show text with indentation + screen.blit(text_surface, (self.rect.x + 10, self.rect.y + 10)) + + def get_text(self): + return self.text