From 522126e325aa44b58da4e3f7c2f2ab6087032635 Mon Sep 17 00:00:00 2001 From: Tipragot Date: Wed, 1 Nov 2023 03:05:33 +0100 Subject: [PATCH] Ajout d'un chargement --- assets/loaded.png | Bin 0 -> 37953 bytes assets/unloaded.png | Bin 0 -> 3388 bytes src/engine/__init__.py | 30 +++++--- src/main.py | 10 +-- src/plugins/animation.py | 23 ++++++ src/plugins/assets.py | 161 +++++++++++++++++++++++++++++++++++++++ src/plugins/defaults.py | 4 +- src/plugins/render.py | 22 +++++- 8 files changed, 229 insertions(+), 21 deletions(-) create mode 100644 assets/loaded.png create mode 100644 assets/unloaded.png create mode 100644 src/plugins/animation.py create mode 100644 src/plugins/assets.py diff --git a/assets/loaded.png b/assets/loaded.png new file mode 100644 index 0000000000000000000000000000000000000000..f12e82f75a63fbc77b7b4dbc0d9788501c853cbe GIT binary patch literal 37953 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� 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 None: self.init_systems = init_systems self.update_systems = update_systems self.stop_systems = stop_systems @@ -68,13 +68,21 @@ class KeepAlive: """ -class CurrentScene(KeepAlive, str): +class CurrentScene(KeepAlive): """ Resource qui permet de savoir et de changer la scène actuelle. """ + def __init__(self, scene: Scene): + self.scene = scene -def start_game(global_scene: GlobalScene, scenes: dict[str, Scene], scene_name: str): + def __eq__(self, value: object) -> bool: + if isinstance(value, CurrentScene): + return self.scene == value.scene + return False + + +def start_game(global_scene: GlobalScene, scene: Optional[Scene]): """ Lance un jeu. @@ -84,14 +92,14 @@ def start_game(global_scene: GlobalScene, scenes: dict[str, Scene], scene_name: """ # On création du monde world = World() - world[CurrentScene] = CurrentScene(scene_name) + if scene is not None: + world[CurrentScene] = CurrentScene(scene) # On initialise la scène globale for system in global_scene.init_systems: system(world) # Boucle principale - scene = scenes.get(scene_name) while scene is not None: # On retire les ressources de l'ancienne scène for resource in world: @@ -107,7 +115,7 @@ def start_game(global_scene: GlobalScene, scenes: dict[str, Scene], scene_name: system(world) # Tant que la scène n'est pas terminé on la met à jour - while world.get(CurrentScene, "") == scene_name: + while world.get(CurrentScene, ()) == CurrentScene(scene): # On met à jour la scène globale for system in global_scene.pre_update_systems: system(world) @@ -124,8 +132,12 @@ def start_game(global_scene: GlobalScene, scenes: dict[str, Scene], scene_name: for system in scene.stop_systems: system(world) - # Récupération de la scène suivante - scene = scenes.get(world.get(CurrentScene, "")) + # On met à jour la scène + current_scene = world.get(CurrentScene, ()) + if isinstance(current_scene, tuple): + scene = None + else: + scene = current_scene.scene # On arrête la scène globale for system in global_scene.stop_systems: diff --git a/src/main.py b/src/main.py index 464773a..b1a7b68 100644 --- a/src/main.py +++ b/src/main.py @@ -3,13 +3,7 @@ Module d'exemple de l'utilisation du moteur de jeu. """ from engine import Scene, start_game -from plugins import defaults +from plugins import assets, defaults -start_game( - defaults.PLUGIN, - { - "menu": Scene([], [], []), - }, - "menu", -) +start_game(defaults.PLUGIN, assets.loading_scene(Scene([], [], []), "textures")) diff --git a/src/plugins/animation.py b/src/plugins/animation.py new file mode 100644 index 0000000..6738980 --- /dev/null +++ b/src/plugins/animation.py @@ -0,0 +1,23 @@ +""" +Un plugin qui permet de jouer des animations de sprites. +""" + +from engine import GlobalScene + + +class Animation: + """ + Composant qui contient toutes les informations d'une animation est en cour + sur l'entité. + """ + + def __init__(self) -> None: + pass + + +PLUGIN = GlobalScene( + [], + [], + [], + [], +) diff --git a/src/plugins/assets.py b/src/plugins/assets.py new file mode 100644 index 0000000..dc9f202 --- /dev/null +++ b/src/plugins/assets.py @@ -0,0 +1,161 @@ +""" +Un plugin qui gère les ressources du jeu. +""" + +import glob +import pygame +from engine import CurrentScene, GlobalScene, KeepAlive, Scene +from engine.ecs import World +from plugins import render + + +class Assets(KeepAlive): + """ + Ressource qui gère les assets du jeu. + """ + + def __init__(self): + # Création de la texture d'erreur + error_texture = pygame.Surface((256, 256)) + error_texture.fill((0, 0, 0)) + pygame.draw.rect(error_texture, (255, 0, 255), (0, 0, 128, 128)) + pygame.draw.rect(error_texture, (255, 0, 255), (128, 128, 128, 128)) + self.__error_texture = error_texture.convert() + + # Chargement des textures de chargement + self.__unloaded_texture = pygame.image.load("assets/unloaded.png").convert() + self.__loaded_texture = pygame.image.load("assets/loaded.png").convert() + + # Cache des ressources + self.__textures: dict[str, pygame.Surface] = {} + + @property + def unloaded_texture(self) -> pygame.Surface: + return self.__unloaded_texture + + @property + def loaded_texture(self) -> pygame.Surface: + return self.__loaded_texture + + def load_texture(self, name: str, path: str) -> pygame.Surface: + """ + Charge une texture et la renvoi. Si une texture existe déja dans le cache, + elle sera remplacée par la nouvelle. + """ + surface = pygame.image.load(path).convert_alpha() + self.__textures[name] = surface + return surface + + def get_texture(self, name: str) -> pygame.Surface: + """ + Renvoie la texture demandée. + """ + return self.__textures.get(name, self.__error_texture) + + def clear_cache(self): + """ + Vide le cache des assets. + """ + self.__textures.clear() + + +def __initialize(world: World): + """ + Ajoute la ressource `Assets` au monde. + """ + world.set(Assets()) + + +PLUGIN = GlobalScene( + [__initialize], + [], + [], + [], +) + + +def loading_scene(target: Scene, name: str): + """ + Retourne une scène de chargement des assets qui passe à la scène donné + en paramètres lorsque tous les assets de la scène sont chargées. + + Paramètres: + - `target`: la scène qui sera lancé après le chargement des assets. + - `name`: le nom de la scène, ce nom est utilisé pour savoir dans quel + dossier sont les assets de la scène. Les assets de la scène + seront récupéré dans le dossier `assets/`. + """ + + class AssetIterator: + """ + Une ressource qui contient un itérateur sur les fichiers des assets + de la scène à charger. + """ + + def __init__(self): + self.files = glob.glob(f"assets/{name}/**/*", recursive=True) + self.total = len(self.files) + + @staticmethod + def prepare_world(world: World): + """ + Retire toutes les ressource précédentes du monde puis + ajoute `ResourceIterator` et la barre de progression dans le monde. + """ + assets = world[Assets] + assets.clear_cache() + world.set(AssetIterator()) + world.new_entity().set( + render.Sprite(assets.unloaded_texture, order=100000000000) + ) + world.new_entity().set( + ProgessBar(), + render.Sprite( + assets.loaded_texture, + order=100000000001, + area=(0, 0, 0, render.HEIGHT), + ), + ) + + @staticmethod + def load_next(world: World): + """ + Charge le fichier suivant de l'itérateur. + """ + asset_iterator = world[AssetIterator] + if len(asset_iterator.files) == 0: + world[CurrentScene] = target + else: + file = asset_iterator.files.pop().replace("\\", "/") + ressource_extension = file.split(".")[-1] + ressource_name = "/".join(file.split("/")[2:])[ + : -len(ressource_extension) - 1 + ] + if ressource_extension in ("png", "jpg"): + world[Assets].load_texture(ressource_name, file) + + class ProgessBar: + """ + Composant marquant une entité comme étant une barre de progression. + """ + + @staticmethod + def render(world: World): + """ + Affiche une barre de progression du chargement des assets. + """ + # Calcul du pourcentage de chargement + asset_iterator = world[AssetIterator] + file_loaded = asset_iterator.total - len(asset_iterator.files) + progress = file_loaded / asset_iterator.total + pixels = int(render.WIDTH * progress) + + # Affichage de la barre de progression + progress_bar = world.query(ProgessBar).pop() + progress_bar[render.Sprite].area = (0, 0, pixels, render.HEIGHT) + + return Scene( + [AssetIterator.prepare_world], + [AssetIterator.load_next, ProgessBar.render], + [], + ) diff --git a/src/plugins/defaults.py b/src/plugins/defaults.py index e2c086f..d262dc1 100644 --- a/src/plugins/defaults.py +++ b/src/plugins/defaults.py @@ -2,7 +2,7 @@ Plugin qui rassemple tous les plugins globaux. """ -from plugins import display, inputs, render +from plugins import assets, display, inputs, render -PLUGIN = display.PLUGIN + inputs.PLUGIN + render.PLUGIN +PLUGIN = display.PLUGIN + assets.PLUGIN + inputs.PLUGIN + render.PLUGIN diff --git a/src/plugins/render.py b/src/plugins/render.py index 6237df2..dfa118e 100644 --- a/src/plugins/render.py +++ b/src/plugins/render.py @@ -2,6 +2,7 @@ Un plugin qui s'occupe de rendre des choses dans la fenetre. """ +from typing import Optional import pygame from engine import GlobalScene, KeepAlive from engine.ecs import World @@ -40,11 +41,24 @@ class Sprite: """ def __init__( - self, surface: pygame.Surface, position: Vec2 = Vec2(0), order: float = -1.0 + self, + surface: pygame.Surface, + position: Vec2 = Vec2(0), + order: float = -1.0, + area: Optional[tuple[float, float, float, float]] = None, ): self.surface = surface self.position = position self.order = order + if area is None: + self.area = ( + 0.0, + 0.0, + float(surface.get_width()), + float(surface.get_height()), + ) + else: + self.area = area def __initialize(world: World): @@ -62,7 +76,11 @@ def __render(world: World): surface = world[Surface] sprites = [entity[Sprite] for entity in world.query(Sprite)] for sprite in sorted(sprites, key=lambda sprite: sprite.order): - surface.blit(sprite.surface, (sprite.position.x, sprite.position.y)) + surface.blit( + sprite.surface, + (sprite.position.x, sprite.position.y), + sprite.area, + ) # On affiche la surface sur la fenetre rect = calculate_surface_rect()