From e50d280afa54497be184d7f6fa4bfacf41b7f802 Mon Sep 17 00:00:00 2001 From: Skyball2000 Date: Wed, 29 Mar 2023 10:45:48 +0200 Subject: [PATCH] Introduced screen layouts and game states --- project/data/levels/level-01.csv | 4 +- project/data/levels/levels.json | 2 +- project/data/sprites/sprites.json | 21 ++ project/level/LevelManager.py | 10 + .../selection}/LevelMenu.py | 24 +- project/level/selection/LevelScreenManager.py | 16 + .../selection/LevelSelectionScreenManager.py | 79 +++++ .../level/selection/MainMenuScreenManager.py | 16 + project/level/selection/ScreenManager.py | 26 ++ project/main.py | 295 +++++++----------- project/sprite/BoundingBox.py | 5 + ...ground.py => ColoredRectangleUiElement.py} | 20 +- 12 files changed, 311 insertions(+), 207 deletions(-) rename project/{ui_elements => level/selection}/LevelMenu.py (60%) create mode 100644 project/level/selection/LevelScreenManager.py create mode 100644 project/level/selection/LevelSelectionScreenManager.py create mode 100644 project/level/selection/MainMenuScreenManager.py create mode 100644 project/level/selection/ScreenManager.py rename project/ui_elements/{Background.py => ColoredRectangleUiElement.py} (64%) diff --git a/project/data/levels/level-01.csv b/project/data/levels/level-01.csv index eb4a382..f87f64e 100644 --- a/project/data/levels/level-01.csv +++ b/project/data/levels/level-01.csv @@ -5,13 +5,13 @@ #,#,S,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# #,#,S,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# #,#,S,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# -#,#,S,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,L,,,,,,,,,,,,,,,,,,,,,,,,C,,,# +#,#,S,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,L,,,,,M,M,,,,,,,,,,,,,,,,,,C,,,# #,#,S,,,,,,,,,,,,,,,,,,,+,+,+,+,S,S,S,S,S,+,+,+,+,+,S,S,S,S,S,+,+,+,+,+,S,S,S,S,S,+,+,+,+,+,+,+,+,+,# #,#,S,,,,,,,,,,,,,,,,,,,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,# #,#,S,,,,,,,,,,,,,,,,,,,,,#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# #,#,S,,,,,,,,,,,,,,,,,,,,,#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# #,#,,,,,,,,,,,,,,,,,,,,,,G,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# -#,,,,,,,,,,,,,,,M,,,M,M,,M,,,,,,,,,,,,,,,,,M,,,,,,M,,,,,,,,,,,,,,,# +#,,,,,,,,,,,,,,,M,,,,,,M,,,,,,,,,,,,,,,,,M,,,,,,M,,,,,,,,,,,,,,,# #,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# #,,,,,,,,,,,+,+,+,+,+,+,+,+,+,+,+,+,+,+,+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# #,L,,,,,,,,,,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# diff --git a/project/data/levels/levels.json b/project/data/levels/levels.json index 4da65a4..186d256 100644 --- a/project/data/levels/levels.json +++ b/project/data/levels/levels.json @@ -15,7 +15,7 @@ }, { "name": "level-02", - "theme": "castle", + "theme": "cave", "abilities": [ ], "file": "level-02.csv" diff --git a/project/data/sprites/sprites.json b/project/data/sprites/sprites.json index fa8c061..fc2a709 100644 --- a/project/data/sprites/sprites.json +++ b/project/data/sprites/sprites.json @@ -834,5 +834,26 @@ "height": 36 } ] + }, + { + "id": "ui_arrow", + "subsheets": [ + { + "id": "left", + "delays": [ + 1 + ], + "width": 12, + "height": 12 + }, + { + "id": "right", + "delays": [ + 1 + ], + "width": 12, + "height": 12 + } + ] } ] \ No newline at end of file diff --git a/project/level/LevelManager.py b/project/level/LevelManager.py index 0c1b878..9069e29 100644 --- a/project/level/LevelManager.py +++ b/project/level/LevelManager.py @@ -25,3 +25,13 @@ class LevelManager: filtered_row = list(map(lambda x: x.replace('\n', ''), split_row)) csv_array.append(filtered_row) return csv_array + + def get_levels_by_theme(self) -> dict[str, list[Level]]: + levels_by_theme = {} + for level in self.levels: + if level.theme not in levels_by_theme: + levels_by_theme[level.theme] = [] + levels_by_theme[level.theme].append(level) + return levels_by_theme + + diff --git a/project/ui_elements/LevelMenu.py b/project/level/selection/LevelMenu.py similarity index 60% rename from project/ui_elements/LevelMenu.py rename to project/level/selection/LevelMenu.py index b1de9f8..599dbed 100644 --- a/project/ui_elements/LevelMenu.py +++ b/project/level/selection/LevelMenu.py @@ -1,7 +1,7 @@ import pygame from level.Level import Level -from ui_elements.Background import Background +from ui_elements.ColoredRectangleUiElement import ColoredRectangleUiElement from ui_elements.ClickEvent import ClickEvent from ui_elements.TextLabel import TextLabel @@ -11,23 +11,27 @@ class LevelMenu: def __init__(self, levels: [Level], x_pos: float, y_pos: float, width: float, height: float, column_count: int): super().__init__() self.levels = levels - self.x_pos = x_pos - self.y_pos = y_pos self.level_select_listener = lambda selected_level: None self.level_text_labels = [] self.width = width self.height = height self.column_count = column_count + self.position = (x_pos, y_pos) + self.create_level_text_labels() - self.background = Background(self.x_pos, self.y_pos, self.width, self.height, (100, 100, 100, 180)) + self.background = ColoredRectangleUiElement(self.width, self.height, (100, 100, 100, 180)) + self.background.position_scale.position = self.position def create_level_text_labels(self): - current_text_label_x = self.x_pos - current_text_label_y = self.y_pos + current_text_label_position = [self.position[0], self.position[1]] for index, level in enumerate(self.levels): - text_label = TextLabel(level.name, current_text_label_x, current_text_label_y, 60) + text_label = TextLabel(level.name, + current_text_label_position[0], + current_text_label_position[1], + 60) + text_label.position_scale.scale = (0.5, 0.5) text_label.add_click_listener( lambda click_event, selected_level=level: @@ -36,10 +40,10 @@ class LevelMenu: self.level_text_labels.append(text_label) if (index + 1) % self.column_count == 0: - current_text_label_y += self.height / (len(self.levels) / self.column_count) - current_text_label_x = self.x_pos + current_text_label_position[0] = self.position[0] + current_text_label_position[1] += self.height / (len(self.levels) / self.column_count) else: - current_text_label_x += self.width / self.column_count + current_text_label_position[0] += self.width / self.column_count def handle_level_text_label_click(self, click_event: ClickEvent, level: Level): if click_event.event.type == pygame.MOUSEBUTTONUP: diff --git a/project/level/selection/LevelScreenManager.py b/project/level/selection/LevelScreenManager.py new file mode 100644 index 0000000..f86d1ae --- /dev/null +++ b/project/level/selection/LevelScreenManager.py @@ -0,0 +1,16 @@ +from abc import abstractmethod + +from level.selection.ScreenManager import ScreenManager +from physics.SpriteManager import SpriteManager +from sprite.SpritesheetManager import SpritesheetManager + + +class LevelScreenManager(ScreenManager): + def __init__(self, sprite_manager: SpriteManager, spritesheet_manager: SpritesheetManager, main_loop): + super().__init__(sprite_manager, spritesheet_manager, main_loop) + + def initialize(self): + pass + + def destroy(self): + super().destroy() diff --git a/project/level/selection/LevelSelectionScreenManager.py b/project/level/selection/LevelSelectionScreenManager.py new file mode 100644 index 0000000..b789be6 --- /dev/null +++ b/project/level/selection/LevelSelectionScreenManager.py @@ -0,0 +1,79 @@ +from abc import abstractmethod + +from level.Level import Level +from level.LevelManager import LevelManager +from level.selection.ScreenManager import ScreenManager +from physics.SpriteManager import SpriteManager, DrawLayers +from sprite.PositionScale import PositionScale +from sprite.SpritesheetManager import SpritesheetManager +from sprite.StaticSprite import StaticSprite +from ui_elements.ClickEvent import ClickEvent +from ui_elements.TextLabel import TextLabel + +LABEL_COUNT = 10 +OFFSET = (50, 20) + + +class LevelSelectionScreenManager(ScreenManager): + def __init__(self, sprite_manager: SpriteManager, spritesheet_manager: SpritesheetManager, main_loop, + level_manager: LevelManager): + super().__init__(sprite_manager, spritesheet_manager, main_loop) + + self.level_manager = level_manager + self.levels_by_theme = self.level_manager.get_levels_by_theme() + self.themes = ['tutorial', 'cave', 'castle'] + + self.level_labels: list[TextLabel] = [] + + self.selected_theme = self.themes[0] + + def select_next_theme(self, click: ClickEvent): + if click.is_click_down(ClickEvent.CLICK_LEFT): + index = (self.themes.index(self.selected_theme) + 1) % len(self.themes) + self.select_theme(self.themes[index]) + + def select_prev_theme(self, click): + if click.is_click_down(ClickEvent.CLICK_LEFT): + index = self.themes.index(self.selected_theme) - 1 + if index < 0: + index = len(self.themes) - 1 + self.select_theme(self.themes[index]) + + def select_level(self, click: ClickEvent, level: Level): + if click.is_click_down(ClickEvent.CLICK_LEFT): + self.main_loop.select_level(level) + + def initialize(self): + arrow_left = StaticSprite(self.spritesheet_manager.get_sheet('ui_arrow')) + arrow_left.set_animation_state('left') + arrow_left.position_scale = PositionScale((OFFSET[0], OFFSET[1]), (3, 3)) + arrow_left.add_click_listener(self.select_prev_theme) + self.add_element(DrawLayers.UI, arrow_left) + + arrow_right = StaticSprite(self.spritesheet_manager.get_sheet('ui_arrow')) + arrow_right.set_animation_state('right') + arrow_right.position_scale = PositionScale((OFFSET[0] + 50, OFFSET[1]), (3, 3)) + arrow_right.add_click_listener(self.select_next_theme) + self.add_element(DrawLayers.UI, arrow_right) + + for i in range(0, LABEL_COUNT): + label = TextLabel(str(i), OFFSET[0] + 30, OFFSET[1] + 60 + i * 50, font_size=65) + label.position_scale.scale = (0.5, 0.5) + self.level_labels.append(label) + self.add_element(DrawLayers.UI, label) + + self.select_theme(self.selected_theme) + + def select_theme(self, theme: str): + self.selected_theme = theme + + for label in self.level_labels: + label.set_text('') + label.click_listeners = [] + + for id, level in enumerate(self.levels_by_theme[self.selected_theme]): + self.level_labels[id].set_text(level.name) + self.level_labels[id].add_click_listener(lambda click: self.select_level(click, level)) + + def destroy(self): + super().destroy() diff --git a/project/level/selection/MainMenuScreenManager.py b/project/level/selection/MainMenuScreenManager.py new file mode 100644 index 0000000..726e599 --- /dev/null +++ b/project/level/selection/MainMenuScreenManager.py @@ -0,0 +1,16 @@ +from abc import abstractmethod + +from level.selection.ScreenManager import ScreenManager +from physics.SpriteManager import SpriteManager +from sprite.SpritesheetManager import SpritesheetManager + + +class MainMenuScreenManager(ScreenManager): + def __init__(self, sprite_manager: SpriteManager, spritesheet_manager: SpritesheetManager,main_loop): + super().__init__(sprite_manager, spritesheet_manager, main_loop) + + def initialize(self): + pass + + def destroy(self): + super().destroy() diff --git a/project/level/selection/ScreenManager.py b/project/level/selection/ScreenManager.py new file mode 100644 index 0000000..29c9322 --- /dev/null +++ b/project/level/selection/ScreenManager.py @@ -0,0 +1,26 @@ +from abc import abstractmethod + +from physics.SpriteManager import SpriteManager +from sprite.SpritesheetManager import SpritesheetManager +from ui_elements.UiElement import UiElement + + +class ScreenManager: + def __init__(self, sprite_manager: SpriteManager, spritesheet_manager: SpritesheetManager, main_loop): + self.sprite_manager = sprite_manager + self.spritesheet_manager = spritesheet_manager + self.main_loop = main_loop + + self.elements: list[UiElement] = [] + + def add_element(self, layer: str, ui_element: UiElement): + self.elements.append(ui_element) + self.sprite_manager.add_ui_element(layer, ui_element) + + @abstractmethod + def initialize(self): + pass + + def destroy(self): + for element in self.elements: + self.sprite_manager.remove_ui_element(element) diff --git a/project/main.py b/project/main.py index 8e3f3d8..404ebf2 100644 --- a/project/main.py +++ b/project/main.py @@ -1,221 +1,146 @@ -import random +from typing import Optional import pygame +from level.Level import Level from level.LevelManager import LevelManager from level.elements.LoadedLevel import LoadedLevel +from level.selection.LevelScreenManager import LevelScreenManager +from level.selection.LevelSelectionScreenManager import LevelSelectionScreenManager +from level.selection.MainMenuScreenManager import MainMenuScreenManager +from level.selection.ScreenManager import ScreenManager from physics import ConstantsParser -from physics.SpriteManager import SpriteManager, DrawLayers +from physics.SpriteManager import SpriteManager from physics.TickData import TickData -from physics.sprites.PlayerSprite import PlayerSprite from sprite.PositionScale import PositionScale -from sprite.Sprite import Sprite from sprite.SpritesheetManager import SpritesheetManager -from sprite.StaticSprite import StaticSprite from ui_elements.ClickEvent import ClickEvent from ui_elements.KeyManager import KeyManager -from ui_elements.LevelMenu import LevelMenu -from ui_elements.TextLabel import TextLabel what_to_run = 'level' -WIDTH = 12 * 71 * 1.5 -HEIGHT = 12 * 40 * 1.5 +DEPRECATED_WIDTH = 12 * 71 * 1.5 +DEPRECATED_HEIGHT = 12 * 40 * 1.5 # Background to test for level design -test_background_castle = pygame.transform.scale(pygame.image.load('data/sprites/castle_bg.png'), (WIDTH, HEIGHT)) -# test_background_cave = pygame.transform.scale(pygame.image.load('data/sprites/cave_bg.png'), (WIDTH, HEIGHT)) -# test_background_tutorial = pygame.transform.scale(pygame.image.load('data/sprites/tutorial_bg.png'), (WIDTH, HEIGHT)) +test_background_castle = pygame.transform.scale(pygame.image.load('data/sprites/castle_bg.png'), + (DEPRECATED_WIDTH, DEPRECATED_HEIGHT)) +# test_background_castle = pygame.transform.scale(pygame.image.load('data/sprites/cave_bg.png'), (DEPRECATED_WIDTH, DEPRECATED_WIDTH)) +# test_background_tutorial = pygame.transform.scale(pygame.image.load('data/sprites/tutorial_bg.png'), (DEPRECATED_WIDTH, DEPRECATED_WIDTH)) -def apply_frame_rate(number: float): + +def apply_frame_rate(number: float, frame_rate: float = 30): """ this function calculates a factor that will be multiplied with the physics of the game to provide a constant speed + :param frame_rate: the frame rate of the game :param number: The number to scale by the factor :return: The scaled number """ return number / (frame_rate / 30) -if what_to_run == 'menu': - screen_transform = PositionScale((0, 0), (1.5, 1.5)) +class MainLoop: + def __init__(self): + self.GAME_STATE_MENU = 'main_menu' + self.GAME_STATE_LEVEL_SELECTION = 'level_selection' + self.GAME_STATE_LEVEL = 'level' - screen_height = 12 * 40 * 1.5 - screen_width = 12 * 71 * 1.5 + self.screen_transform: PositionScale = PositionScale((0, 0), (1.5, 1.5)) + self.window_size: tuple[float, float] = (1, 1) - pygame.init() - screen = pygame.display.set_mode((screen_width, screen_height)) - pygame.display.set_caption("PM GAME") - clock = pygame.time.Clock() - frame_rate = 30 + pygame.init() + pygame.display.set_caption("PM GAME") - spritesheet_manager = SpritesheetManager("data/sprites", "data/sprites/sprites.json") - sprite_manager = SpriteManager() - key_manager = KeyManager() + self.update_position_scale(self.screen_transform) - parsed_levels_manager = LevelManager('data/levels') - parsed_levels_manager.load_from_config('data/levels/levels.json') + self.screen = self.screen + self.clock = pygame.time.Clock() + self.frame_rate = 30 - generated_level = LoadedLevel(sprite_manager, spritesheet_manager) + self.spritesheet_manager = SpritesheetManager("data/sprites", "data/sprites/sprites.json") + self.sprite_manager = SpriteManager() + self.key_manager = KeyManager() - level_menu_width = screen_width / 2 - level_menu_height = screen_height / 2 - level_menu = LevelMenu(parsed_levels_manager.levels, 0, 0, level_menu_width, level_menu_height, 3) - show_menu = False + self.parsed_levels_manager = LevelManager('data/levels') + self.parsed_levels_manager.load_from_config('data/levels/levels.json') + + self.screen_manager: Optional[ScreenManager] = None + self.game_state = self.GAME_STATE_MENU + self.set_game_state(self.GAME_STATE_LEVEL_SELECTION) + + def update_position_scale(self, position_scale: PositionScale): + self.screen_transform = position_scale + self.window_size = ( + self.screen_transform.scale[0] * ConstantsParser.CONFIG.block_size[0] * + ConstantsParser.CONFIG.level_size[0], + self.screen_transform.scale[1] * ConstantsParser.CONFIG.block_size[1] * + ConstantsParser.CONFIG.level_size[1] + ) + + self.screen = pygame.display.set_mode((self.window_size[0], self.window_size[1])) + + def select_level(self, level: Level): + print(level.name) + self.set_game_state(self.GAME_STATE_LEVEL) + + def set_game_state(self, game_state: str): + self.game_state = game_state + + if self.screen_manager is not None: + self.screen_manager.destroy() + + if self.game_state == self.GAME_STATE_MENU: + self.screen_manager = MainMenuScreenManager( + self.sprite_manager, self.spritesheet_manager, self + ) + elif self.game_state == self.GAME_STATE_LEVEL: + self.screen_manager = LevelScreenManager( + self.sprite_manager, self.spritesheet_manager, self + ) + elif self.game_state == self.GAME_STATE_LEVEL_SELECTION: + self.screen_manager = LevelSelectionScreenManager( + self.sprite_manager, self.spritesheet_manager, self, self.parsed_levels_manager + ) + else: + print('Invalid game state', self.game_state) + + if self.screen_manager is not None: + self.screen_manager.initialize() + + def main_loop(self): + while True: + self.clock.tick(self.frame_rate) + + pygame_events: list[pygame.event.Event] = pygame.event.get() + self.key_manager.update_key_events(pygame_events) + click_events: list[ClickEvent] = ClickEvent.create_events(pygame_events, self.screen_transform) + + for event in click_events: + for layer in self.sprite_manager.layers: + for sprite in self.sprite_manager.layers[layer]: + if sprite.get_bounding_box().contains_point(event.world_position): + sprite.click(event) + + for event in pygame_events: + if event.type == pygame.QUIT: + pygame.quit() + quit() + + self.screen.fill((0, 0, 0)) + self.sprite_manager.tick( + TickData(apply_frame_rate(1, self.frame_rate), + pygame_events, + self.key_manager, + click_events, + self.screen_transform) + ) + self.sprite_manager.draw(self.screen, self.screen_transform) + + pygame.display.update() - def load_next_level(selected_level): - global show_menu - generated_level.destroy_level() - generated_level.load_level(selected_level) - destroy_menu() - show_menu = False - - - def destroy_menu(): - global level_text_label - for level_text_label in level_menu.level_text_labels: - sprite_manager.remove_ui_element(level_text_label) - sprite_manager.remove_ui_element(level_menu.background) - - - level_menu.level_select_listener = lambda selected_level: load_next_level(selected_level) - - while True: - clock.tick(frame_rate) - - pygame_events: list[pygame.event.Event] = pygame.event.get() - key_manager.update_key_events(pygame_events) - click_events: list[ClickEvent] = ClickEvent.create_events(pygame_events, screen_transform) - - for event in click_events: - for layer in sprite_manager.layers: - for sprite in sprite_manager.layers[layer]: - if sprite.get_bounding_box().contains_point(event.world_position): - sprite.click(event) - - for event in pygame_events: - if event.type == pygame.QUIT: - pygame.quit() - quit() - if key_manager.is_keymap_down(KeyManager.KEY_ESCAPE): - if show_menu: - show_menu = False - destroy_menu() - else: - show_menu = True - sprite_manager.add_ui_element(DrawLayers.UI, level_menu.background) - for level_text_label in level_menu.level_text_labels: - sprite_manager.add_ui_element(DrawLayers.UI, level_text_label) - - screen.fill((0, 0, 0)) - sprite_manager.tick(TickData(apply_frame_rate(1), pygame_events, key_manager, click_events, screen_transform)) - sprite_manager.draw(screen, screen_transform) - - pygame.display.update() - -elif what_to_run == 'level': - screen_transform = PositionScale((0, 0), (1.5, 1.5)) - - pygame.init() - screen = pygame.display.set_mode((12 * ConstantsParser.CONFIG.level_size[0] * screen_transform.scale[0], - 12 * ConstantsParser.CONFIG.level_size[1] * screen_transform.scale[1]), - flags=pygame.HWSURFACE | pygame.DOUBLEBUF, - vsync=1, - depth=1) - - pygame.display.set_caption("PM GAME") - clock = pygame.time.Clock() - frame_rate = 30 - - spritesheet_manager = SpritesheetManager("data/sprites", "data/sprites/sprites.json") - sprite_manager = SpriteManager() - key_manager = KeyManager() - - parsed_levels_manager = LevelManager('data/levels') - parsed_levels_manager.load_from_config('data/levels/levels.json') - - generated_level = LoadedLevel(sprite_manager, spritesheet_manager) - generated_level.load_level(parsed_levels_manager.levels[1]) - ghost_character = PlayerSprite(spritesheet_manager.get_sheet("ghost_character")) - ghost_character.position_scale = PositionScale((90, 50), (1, 1)) - sprite_manager.add_ui_element(DrawLayers.OBJECTS, ghost_character) - - calculated_frame_rate_text = TextLabel("0 FPS", 2, 2, 70, alignment="left") - calculated_frame_rate_text.position_scale.scale = (0.3, 0.3) - sprite_manager.add_ui_element(DrawLayers.UI, calculated_frame_rate_text) - - left_sprite = None - right_sprite = None - - while True: - clock.tick(frame_rate) - - calculated_frame_rate_text.text = f"{round(clock.get_fps())} FPS" - - pygame_events: list[pygame.event.Event] = pygame.event.get() - key_manager.update_key_events(pygame_events) - click_events: list[ClickEvent] = ClickEvent.create_events(pygame_events, screen_transform) - - for event in pygame_events: - if event.type == pygame.QUIT: - pygame.quit() - quit() - - for event in click_events: - for layer in sprite_manager.layers: - for sprite in sprite_manager.layers[layer]: - if sprite.get_bounding_box().contains_point(event.world_position): - if event.is_click_down(ClickEvent.CLICK_LEFT): - left_sprite = sprite - if event.is_click_down(ClickEvent.CLICK_RIGHT): - right_sprite = sprite - - if left_sprite is not None and right_sprite is not None: - print(left_sprite.get_bounding_box().distance(right_sprite.get_bounding_box())) - left_sprite = None - right_sprite = None - - screen.fill((0, 0, 0)) - # Playground to test background on any level - screen.blit(test_background_castle, (0, 0)) - - sprite_manager.tick(TickData(apply_frame_rate(1), pygame_events, key_manager, click_events, screen_transform)) - sprite_manager.draw(screen, screen_transform) - pygame.display.update() - - -elif what_to_run == 'textlabel': - screen_transform = PositionScale((0, 0), (4, 4)) - - pygame.init() - screen = pygame.display.set_mode((800, 800)) - pygame.display.set_caption("PM GAME") - clock = pygame.time.Clock() - - test1 = TextLabel("Das ist ein Test", 100, 0, 50, alignment="left") - test2 = TextLabel("Das ist ein Test", 100, 50, 50, alignment="left") - test3 = TextLabel("Das ist ein Test", 100, 20, 50, alignment="left") - - test1.position_scale.scale = (0.2, 0.2) - test2.position_scale.scale = (0.4, 0.4) - test3.position_scale.scale = (0.2, 0.2) - - test3.visible = False - - while True: - clock.tick(5) - - for event in pygame.event.get(): - if event.type == pygame.QUIT: - pygame.quit() - - screen.fill((0, 0, 110)) - - test1.draw(screen, screen_transform) - test2.draw(screen, screen_transform) - test3.draw(screen, screen_transform) - - pygame.display.update() +main_loop: MainLoop = MainLoop() +main_loop.main_loop() diff --git a/project/sprite/BoundingBox.py b/project/sprite/BoundingBox.py index 8ff3ccb..e5236f1 100644 --- a/project/sprite/BoundingBox.py +++ b/project/sprite/BoundingBox.py @@ -1,5 +1,7 @@ import math +import pygame + class BoundingBox: def __init__(self, x, y, width, height): @@ -46,3 +48,6 @@ class BoundingBox: """ return self.x < bounding_box.x + bounding_box.width and self.x + self.width > bounding_box.x and \ self.y < bounding_box.y + bounding_box.height and self.y + self.height > bounding_box.y + + def get_rect(self) -> pygame.Rect: + return pygame.Rect(self.x, self.y, self.width, self.height) diff --git a/project/ui_elements/Background.py b/project/ui_elements/ColoredRectangleUiElement.py similarity index 64% rename from project/ui_elements/Background.py rename to project/ui_elements/ColoredRectangleUiElement.py index 17deaaf..3be76dd 100644 --- a/project/ui_elements/Background.py +++ b/project/ui_elements/ColoredRectangleUiElement.py @@ -8,24 +8,26 @@ from sprite.BoundingBox import BoundingBox from ui_elements.UiElement import UiElement -class Background(UiElement): +class ColoredRectangleUiElement(UiElement): - def __init__(self, x_pos: float, y_pos: float, width: float, height: float, color: tuple): + def __init__(self, width: float, height: float, color: tuple): super().__init__() - self.x_pos = x_pos - self.y_pos = y_pos + self.width = width self.height = height self.color = color - def tick(self, tick_data: TickData): - pass - def render_sprite_image(self) -> Optional[Surface]: + bounding_box = self.get_bounding_box() + background_rect = bounding_box.get_rect() + surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA) - background_rect = pygame.Rect(self.x_pos, self.y_pos, self.width, self.height) pygame.draw.rect(surface, self.color, background_rect) return surface def get_bounding_box(self) -> BoundingBox: - return BoundingBox(-1, -1, 0, 0) + return BoundingBox(self.position_scale.position[0], self.position_scale.position[1], + self.width, self.height) + + def tick(self, tick_data: TickData): + pass