diff --git a/assets/global/background.png b/assets/textures/background.png similarity index 100% rename from assets/global/background.png rename to assets/textures/background.png diff --git a/src/engine/ecs.py b/src/engine/ecs.py index 8e58b65..a94a1f0 100644 --- a/src/engine/ecs.py +++ b/src/engine/ecs.py @@ -6,7 +6,7 @@ Pour moddifier le monde, on n'agis que sur les composants. """ -from typing import Iterator, Optional, Sequence, TypeVar +from typing import Iterator, Optional, Sequence class Entity: @@ -17,15 +17,6 @@ class Entity: utilitaire pour acceder au monde plus facilement. """ - __T = TypeVar("__T") - """ - Ce type est utilisé pour permettre la gestion des types - pour certaines fonctions. Par exemple, la fonction `__getitem__` - utilise cette variable pour retourner un object du type demandé. - Cela permet d'avoir des vérifications de types et de l'autocomplétion - en utilisant notre IDE. - """ - def __init__(self, world: "World", identifier: int) -> None: self.__world = world self.__identifier = identifier @@ -55,13 +46,13 @@ class Entity: def __repr__(self) -> str: return f"Entity({self.__identifier})" - def __getitem__(self, component_type: type[__T]) -> __T: + def __getitem__[T](self, component_type: type[T]) -> T: return self.__world.get_component(self, component_type) def __delitem__(self, component_type: type[object]): self.__world.remove_component(self, component_type) - def __setitem__(self, component_type: type[__T], component: __T): + def __setitem__[T](self, component_type: type[T], component: T): if component_type != type(component): component = component_type(component) self.__world.set_component(self, component) @@ -75,7 +66,7 @@ class Entity: def __iter__(self) -> Iterator[object]: return iter(self.__world.all_components(self)) - def get(self, component_type: type[__T], default: Optional[__T] = None) -> __T: + def get[T](self, component_type: type[T], default: Optional[T] = None) -> T: """ Renvoie le composant de type `component_type` de l'entité. Si aucun composant de type `component_type` n'est dans l'entité: @@ -126,15 +117,6 @@ class World(Entity): globaux, relatif au monde. """ - __T = TypeVar("__T") - """ - Ce type est utilisé pour permettre la gestion des types - pour certaines fonctions. Par exemple, la fonction `get_component` - utilise cette variable pour retourner un object du type demandé. - Cela permet d'avoir des vérifications de types et de l'autocomplétion - en utilisant notre IDE. - """ - def __init__(self): super().__init__(self, 0) self.__components: dict[int, dict[type[object], object]] = {} @@ -167,9 +149,9 @@ class World(Entity): self.__components.setdefault(entity.identifier, {})[type(component)] = component self.__entities.setdefault(type(component), set()).add(entity.identifier) - def get_component( - self, entity: "Entity", component_type: type[__T], default: Optional[__T] = None - ) -> __T: + def get_component[T]( + self, entity: "Entity", component_type: type[T], default: Optional[T] = None + ) -> T: """ Renvoie le composant de type `component_type` de l'entité `entity`. Si aucun composant de type `component_type` n'est dans l'entité: diff --git a/src/main.py b/src/main.py index 58ac896..06f1d8f 100644 --- a/src/main.py +++ b/src/main.py @@ -2,9 +2,29 @@ Module d'exemple de l'utilisation du moteur de jeu. """ -from engine import start_game +from engine import Scene, start_game +from engine.ecs import World from plugins import defaults -from scenes import menu +from plugins.render import Origin, Position, Scale, Texture -start_game(defaults.PLUGIN, menu.SCENE) +def __initialize(world: World): + """ + Initialise les ressources pour le moteur de jeu. + """ + world.new_entity().set( + Texture("background.png", 0), + # Scale(1000, 1000), + # Origin(0.5, 0.5), + # Position(600, 600), + ) + + +MENU = Scene( + [__initialize], + [], + [], +) + + +start_game(defaults.PLUGIN, MENU) diff --git a/src/plugins save/__init__.py b/src/plugins save/__init__.py new file mode 100644 index 0000000..63ddc3a --- /dev/null +++ b/src/plugins save/__init__.py @@ -0,0 +1,10 @@ +""" +Module contenant tous les plugins du jeu. + +Un plugin est une scène pouvant être ajouté a d'autres scènes +afin d'ajouter des fonctionnalités au jeu. + +Le but est de faire en sorte que les plugins soient génériques +afin de pouvoir les utilisers dans plusieurs scènes et donc +éviter de répéter plusieurs fois le même code. +""" diff --git a/src/plugins/animation.py b/src/plugins save/animation.py similarity index 100% rename from src/plugins/animation.py rename to src/plugins save/animation.py diff --git a/src/plugins/assets.py b/src/plugins save/assets.py similarity index 100% rename from src/plugins/assets.py rename to src/plugins save/assets.py diff --git a/src/plugins save/click.py b/src/plugins save/click.py new file mode 100644 index 0000000..d4548fa --- /dev/null +++ b/src/plugins save/click.py @@ -0,0 +1,48 @@ +""" +Un plugin permettant de savoir si l'on a cliqué sur une entité. +""" + +from typing import Callable +from engine import GlobalPlugin +from engine.ecs import Entity, World +from plugins.hover import Hovered +from plugins.inputs import Pressed +from plugins.render import Sprite + + +class Clicked: + """ + Component ajouté a toutes les entitées qui viennent d'être cliqué. + """ + + +class Clickable: + """ + Composant qui permet d'executer une fonction lorsqu'une entité est cliquee. + """ + + def __init__(self, callback: Callable[[World, Entity], object]): + self.callback = callback + + +def __update_clicked(world: World): + """ + Met à jour les composants `Clicked`. + """ + mouse_click = "button_1" in world[Pressed] + sprite_entities = world.query(Sprite) + for entity in sprite_entities: + if Hovered in entity and mouse_click: + entity[Clicked] = Clicked() + if Clickable in entity: + entity[Clickable].callback(world, entity) + else: + del entity[Clicked] + + +PLUGIN = GlobalPlugin( + [], + [__update_clicked], + [], + [], +) diff --git a/src/plugins/coroutine.py b/src/plugins save/coroutine.py similarity index 100% rename from src/plugins/coroutine.py rename to src/plugins save/coroutine.py diff --git a/src/plugins save/defaults.py b/src/plugins save/defaults.py new file mode 100644 index 0000000..8545e55 --- /dev/null +++ b/src/plugins save/defaults.py @@ -0,0 +1,34 @@ +""" +Plugin qui rassemple tous les plugins globaux. +""" + +from plugins import ( + animation, + assets, + click, + coroutine, + display, + hover, + inputs, + multisound, + render, + sound, + text, + timing, +) + + +PLUGIN = ( + display.PLUGIN + + timing.PLUGIN + + assets.PLUGIN + + inputs.PLUGIN + + hover.PLUGIN + + click.PLUGIN + + coroutine.PLUGIN + + multisound.PLUGIN + + sound.PLUGIN + + text.PLUGIN + + animation.PLUGIN + + render.PLUGIN +) diff --git a/src/plugins save/display.py b/src/plugins save/display.py new file mode 100644 index 0000000..cc0c1c2 --- /dev/null +++ b/src/plugins save/display.py @@ -0,0 +1,32 @@ +""" +Un plugin pour la gestion de la fenetre du jeu. +""" + + +import pygame +from engine.ecs import World +from engine import GlobalPlugin + + +def __initialize(_world: World): + """ + Initialise pygame et les ressources pour la gestion de la fenetre. + """ + pygame.init() + pygame.display.set_caption("Guess The Number") + pygame.display.set_mode((800, 600), pygame.RESIZABLE) + + +def __terminate(_world: World): + """ + Arrête pygame. + """ + pygame.quit() + + +PLUGIN = GlobalPlugin( + [__initialize], + [], + [], + [__terminate], +) diff --git a/src/plugins save/hover.py b/src/plugins save/hover.py new file mode 100644 index 0000000..c73ea65 --- /dev/null +++ b/src/plugins save/hover.py @@ -0,0 +1,92 @@ +""" +Un plugin permettant de savoir si la souris est par dessus une entité. +""" + + +import pygame + +from engine import GlobalPlugin +from engine.ecs import World +from engine.math import Vec2 +from plugins.inputs import MousePosition +from plugins.render import Sprite + + +class HoverEnter: + """ + Composant indicant que l'entité vient de commencer a être survolée par la souris. + """ + + +class Hovered: + """ + Composant indicant que l'entité est survolée par la souris. + """ + + +class HoverExit: + """ + Composant indicant que la souris viens d'arreter de survoler l'entité. + """ + + +class HoveredTexture: + """ + Composant permettant de changer la texture d'une entité lorsque + celle-ci est survolée par la souris. + """ + + def __init__(self, normal: pygame.Surface, hovered: pygame.Surface): + self.normal = normal + self.hovered = hovered + + +def __update_hovered(world: World): + """ + Vérifie le survol de la souris sur les entitées. + """ + # On met à jour les composants + mouse_position = world[MousePosition] + for entity in world.query(Sprite): + # Récupération de la position et taille de l'entité + sprite = entity[Sprite] + size = Vec2(*sprite.texture.get_size()) * Vec2(*sprite.area[2:]) + position = sprite.position - (sprite.origin * size) + + # On détermine si la souris est sur l'entité + if ( + mouse_position.x >= position.x + and mouse_position.x <= position.x + size.x + and mouse_position.y >= position.y + and mouse_position.y <= position.y + size.y + ): + if Hovered not in entity: + entity[HoverEnter] = HoverEnter() + else: + del entity[HoverEnter] + entity[Hovered] = Hovered() + else: + if Hovered in entity: + entity[HoverExit] = HoverExit() + else: + del entity[HoverExit] + del entity[Hovered] + + # On affiche la bonne texture + for entity in world.query(HoveredTexture): + if Hovered in entity: + texture = entity[HoveredTexture].hovered + else: + texture = entity[HoveredTexture].normal + if Sprite in entity: + entity[Sprite].texture = texture + else: + entity[Sprite] = Sprite(texture) + + +PLUGIN = GlobalPlugin( + [], + [__update_hovered], + [], + [], +) diff --git a/src/plugins save/inputs.py b/src/plugins save/inputs.py new file mode 100644 index 0000000..7c7f59b --- /dev/null +++ b/src/plugins save/inputs.py @@ -0,0 +1,90 @@ +""" +Un plugin permettant de gérer les entrées utilisateur du jeu. +""" + +import pygame +from engine import CurrentScene, GlobalPlugin, KeepAlive +from engine.ecs import World +from engine.math import Vec2 +from plugins import render + + +class Pressed(KeepAlive, set[str]): + """ + Ressource qui correspond aux touches qui viennent d'être préssées par l'utilisateur. + + Pour les boutons de la souris la touche sera nommée `button_x` avec `x` le numéro du bouton. + """ + + +class Held(KeepAlive, set[str]): + """ + Ressource qui correspond aux touches qui sont actuellement préssées par l'utilisateur. + """ + + +class Released(KeepAlive, set[str]): + """ + Ressource qui correspond aux touches qui viennent d'être relachées par l'utilisateur. + """ + + +class MousePosition(KeepAlive, Vec2): + """ + Ressource qui correspond à la position de la souris. + """ + + +def __initialize(world: World): + """ + Initialise des ressources pour la gestion des entrées utilisateur. + """ + world.set(Pressed(), Held(), Released(), MousePosition()) + + +def __update_input(world: World): + """ + Met à jour les ressources qui permettent de savoir quels sont les + entrées utilisateur. + """ + # On récupère les ressources + pressed = world[Pressed] + held = world[Held] + released = world[Released] + + # On clear les touches pressées et relachées + pressed.clear() + released.clear() + + # On récupère les évenements de pygame + for event in pygame.event.get(): + if event.type == pygame.QUIT: + del world[CurrentScene] + elif event.type == pygame.KEYDOWN: + key_name = pygame.key.name(event.key) + held.add(key_name) + pressed.add(key_name) + elif event.type == pygame.KEYUP: + key_name = pygame.key.name(event.key) + held.remove(key_name) + released.add(key_name) + elif event.type == pygame.MOUSEBUTTONDOWN: + held.add(f"button_{event.button}") + pressed.add(f"button_{event.button}") + elif event.type == pygame.MOUSEBUTTONUP: + held.remove(f"button_{event.button}") + released.add(f"button_{event.button}") + elif event.type == pygame.MOUSEMOTION: + x, y, w, h = render.calculate_surface_rect() + world[MousePosition] = Vec2( + ((event.pos[0] - x) / w) * render.WIDTH, + ((event.pos[1] - y) / h) * render.HEIGHT, + ) + + +PLUGIN = GlobalPlugin( + [__initialize], + [__update_input], + [], + [], +) diff --git a/src/plugins/multisound.py b/src/plugins save/multisound.py similarity index 100% rename from src/plugins/multisound.py rename to src/plugins save/multisound.py diff --git a/src/plugins save/render.py b/src/plugins save/render.py new file mode 100644 index 0000000..f8aec72 --- /dev/null +++ b/src/plugins save/render.py @@ -0,0 +1,106 @@ +""" +Un plugin qui s'occupe de rendre des choses dans la fenetre. +""" + +from typing import Optional +import pygame +from engine import GlobalPlugin, KeepAlive +from engine.ecs import World +from engine.math import Vec2 + + +WIDTH = 1440 +HEIGHT = 1080 +RATIO = WIDTH / HEIGHT +INVERT_RATIO = HEIGHT / WIDTH + + +def calculate_surface_rect() -> tuple[float, float, float, float]: + """ + Calcule et renvoie un rectangle qui corresponed a la zone dans laquelle le jeu est rendu. + """ + width, height = pygame.display.get_surface().get_size() + if width / height < RATIO: + target_height = width * INVERT_RATIO + offset = (height - target_height) / 2 + return 0.0, offset, float(width), target_height + target_width = height * RATIO + offset = (width - target_width) / 2 + return offset, 0.0, target_width, float(height) + + +class Surface(KeepAlive, pygame.Surface): + """ + Ressource qui stocke la surface de rendu du jeu. + """ + + +class Sprite: + """ + Composant donnant la texture d'une entité, sa position et son ordre de rendu. + """ + + def __init__( + self, + texture: pygame.Surface, + position: Vec2 = Vec2(0), + order: float = -1.0, + area: Optional[tuple[float, float, float, float]] = None, + origin: Vec2 = Vec2(0), + ): + self.texture = texture + self.position = position + self.order = order + if area is None: + self.area = (0.0, 0.0, 1.0, 1.0) + else: + self.area = area + self.origin = origin + + +def __initialize(world: World): + """ + Prépare le monde pour la gestion du rendu. + """ + world.set(Surface((WIDTH, HEIGHT))) + + +def __render(world: World): + """ + Rend le monde du jeu sur la surface puis l'affiche sur la fenetre. + """ + # On rend le monde sur la surface + surface = world[Surface] + sprites = [entity[Sprite] for entity in world.query(Sprite)] + for sprite in sorted(sprites, key=lambda sprite: sprite.order): + original_size = Vec2(*sprite.texture.get_size()) + size = original_size * Vec2(*sprite.area[2:]) + position = sprite.position - (sprite.origin * size) + surface.blit( + sprite.texture, + (position.x, position.y), + ( + sprite.area[0] * original_size.x, + sprite.area[1] * original_size.y, + sprite.area[2] * original_size.x, + sprite.area[3] * original_size.y, + ), + ) + + # On affiche la surface sur la fenetre + rect = calculate_surface_rect() + pygame.transform.set_smoothscale_backend("MMX") + pygame.transform.smoothscale( + surface, + (rect[2], rect[3]), + pygame.display.get_surface().subsurface(rect), + ) + pygame.display.flip() + + +PLUGIN = GlobalPlugin( + [__initialize], + [], + [__render], + [], +) diff --git a/src/plugins/smooth.py b/src/plugins save/smooth.py similarity index 100% rename from src/plugins/smooth.py rename to src/plugins save/smooth.py diff --git a/src/plugins/text.py b/src/plugins save/text.py similarity index 100% rename from src/plugins/text.py rename to src/plugins save/text.py diff --git a/src/plugins save/timing.py b/src/plugins save/timing.py new file mode 100644 index 0000000..cfdbdcf --- /dev/null +++ b/src/plugins save/timing.py @@ -0,0 +1,52 @@ +""" +Un plugin permettant de connaitre le temps depuis le +lancement du jeu et le temps depuis la dernière frame. +""" + + +from time import time +from engine import GlobalPlugin, KeepAlive +from engine.ecs import World + + +class GlobalTime(KeepAlive, float): + """ + Ressource qui représente le temps global de l'ordinateur sur lequel tourne le jeu. + """ + + +class Time(KeepAlive, float): + """ + Ressource qui représente le temps depuis le lancement du jeu. + """ + + +class Delta(KeepAlive, float): + """ + Ressource qui détermine le temps depuis la première frame. + """ + + +def __initialize(world: World): + """ + Initialise les ressources pour la gestion du temps. + """ + world.set(GlobalTime(time()), Time(0.0)) + + +def __update(world: World): + """ + Met à jour les ressources de temps. + """ + now = time() + world[Delta] = delta = now - world[GlobalTime] + world[GlobalTime] = now + world[Time] += delta + + +PLUGIN = GlobalPlugin( + [__initialize], + [__update], + [], + [], +) diff --git a/src/plugins/click.py b/src/plugins/click.py index d4548fa..eb58691 100644 --- a/src/plugins/click.py +++ b/src/plugins/click.py @@ -2,12 +2,13 @@ Un plugin permettant de savoir si l'on a cliqué sur une entité. """ +from tkinter import Scale from typing import Callable from engine import GlobalPlugin from engine.ecs import Entity, World from plugins.hover import Hovered from plugins.inputs import Pressed -from plugins.render import Sprite +from plugins.render import Position class Clicked: @@ -30,7 +31,7 @@ def __update_clicked(world: World): Met à jour les composants `Clicked`. """ mouse_click = "button_1" in world[Pressed] - sprite_entities = world.query(Sprite) + sprite_entities = world.query(Position, Scale) for entity in sprite_entities: if Hovered in entity and mouse_click: entity[Clicked] = Clicked() diff --git a/src/plugins/defaults.py b/src/plugins/defaults.py index 8545e55..fe5b434 100644 --- a/src/plugins/defaults.py +++ b/src/plugins/defaults.py @@ -2,33 +2,14 @@ Plugin qui rassemple tous les plugins globaux. """ -from plugins import ( - animation, - assets, - click, - coroutine, - display, - hover, - inputs, - multisound, - render, - sound, - text, - timing, -) +from plugins import display, inputs, sound, render, timing, hover PLUGIN = ( display.PLUGIN + timing.PLUGIN - + assets.PLUGIN + inputs.PLUGIN + hover.PLUGIN - + click.PLUGIN - + coroutine.PLUGIN - + multisound.PLUGIN + sound.PLUGIN - + text.PLUGIN - + animation.PLUGIN + render.PLUGIN ) diff --git a/src/plugins/hover.py b/src/plugins/hover.py index c73ea65..d5c32e3 100644 --- a/src/plugins/hover.py +++ b/src/plugins/hover.py @@ -3,13 +3,10 @@ Un plugin permettant de savoir si la souris est par dessus une entité. """ -import pygame - from engine import GlobalPlugin from engine.ecs import World -from engine.math import Vec2 from plugins.inputs import MousePosition -from plugins.render import Sprite +from plugins.render import Origin, Position, Scale, Texture class HoverEnter: @@ -36,7 +33,7 @@ class HoveredTexture: celle-ci est survolée par la souris. """ - def __init__(self, normal: pygame.Surface, hovered: pygame.Surface): + def __init__(self, normal: str, hovered: str): self.normal = normal self.hovered = hovered @@ -47,11 +44,10 @@ def __update_hovered(world: World): """ # On met à jour les composants mouse_position = world[MousePosition] - for entity in world.query(Sprite): + for entity in world.query(Position, Scale): # Récupération de la position et taille de l'entité - sprite = entity[Sprite] - size = Vec2(*sprite.texture.get_size()) * Vec2(*sprite.area[2:]) - position = sprite.position - (sprite.origin * size) + size = entity[Scale] + position = entity[Position] - (entity.get(Origin, Origin(0)) * size) # On détermine si la souris est sur l'entité if ( @@ -75,13 +71,9 @@ def __update_hovered(world: World): # On affiche la bonne texture for entity in world.query(HoveredTexture): if Hovered in entity: - texture = entity[HoveredTexture].hovered + entity[Texture] = entity[HoveredTexture].hovered else: - texture = entity[HoveredTexture].normal - if Sprite in entity: - entity[Sprite].texture = texture - else: - entity[Sprite] = Sprite(texture) + entity[Texture] = entity[HoveredTexture].normal PLUGIN = GlobalPlugin( diff --git a/src/plugins/render.py b/src/plugins/render.py index f8aec72..9bf659b 100644 --- a/src/plugins/render.py +++ b/src/plugins/render.py @@ -2,7 +2,6 @@ Un plugin qui s'occupe de rendre des choses dans la fenetre. """ -from typing import Optional import pygame from engine import GlobalPlugin, KeepAlive from engine.ecs import World @@ -29,35 +28,42 @@ def calculate_surface_rect() -> tuple[float, float, float, float]: return offset, 0.0, target_width, float(height) +class Texture(str): + """ + Composant donnant le nom de la texture d'une entité. + """ + + +class Order(float): + """ + Composant donnant l'ordre d'affichage d'une entité. + """ + + +class Position(Vec2): + """ + Composant donnant la position de l'origine d'un objet. + """ + + +class Scale(Vec2): + """ + Composant donnant la taille de la texture d'une entité. + """ + + +class Origin(Vec2): + """ + Composant définissant l'emplacement de l'origine d'un objet sur sa texture. + """ + + class Surface(KeepAlive, pygame.Surface): """ Ressource qui stocke la surface de rendu du jeu. """ -class Sprite: - """ - Composant donnant la texture d'une entité, sa position et son ordre de rendu. - """ - - def __init__( - self, - texture: pygame.Surface, - position: Vec2 = Vec2(0), - order: float = -1.0, - area: Optional[tuple[float, float, float, float]] = None, - origin: Vec2 = Vec2(0), - ): - self.texture = texture - self.position = position - self.order = order - if area is None: - self.area = (0.0, 0.0, 1.0, 1.0) - else: - self.area = area - self.origin = origin - - def __initialize(world: World): """ Prépare le monde pour la gestion du rendu. @@ -65,27 +71,25 @@ def __initialize(world: World): world.set(Surface((WIDTH, HEIGHT))) -def __render(world: World): +def __render(world: World, cache: dict[str, pygame.Surface] = {}): """ Rend le monde du jeu sur la surface puis l'affiche sur la fenetre. """ # On rend le monde sur la surface - surface = world[Surface] - sprites = [entity[Sprite] for entity in world.query(Sprite)] - for sprite in sorted(sprites, key=lambda sprite: sprite.order): - original_size = Vec2(*sprite.texture.get_size()) - size = original_size * Vec2(*sprite.area[2:]) - position = sprite.position - (sprite.origin * size) - surface.blit( - sprite.texture, - (position.x, position.y), - ( - sprite.area[0] * original_size.x, - sprite.area[1] * original_size.y, - sprite.area[2] * original_size.x, - sprite.area[3] * original_size.y, - ), + surface: Surface = world[Surface] + entities = sorted(world.query(Texture), key=lambda entity: entity.get(Order, -1)) + for entity in entities: + texture_name = entity[Texture] + texture = cache.get(texture_name) + if texture is None: + texture = pygame.image.load(f"assets/textures/{texture_name}") + cache[texture_name] = texture + scale = entity.get(Scale, Scale(128)) + texture = pygame.transform.scale(texture, (scale.x, scale.y)) + position = ( + entity.get(Position, Position(0)) - (entity.get(Origin, Origin(0))) * scale ) + surface.blit(texture, (position.x, position.y)) # On affiche la surface sur la fenetre rect = calculate_surface_rect() diff --git a/src/plugins/sound.py b/src/plugins/sound.py index 06597d7..5b358f3 100644 --- a/src/plugins/sound.py +++ b/src/plugins/sound.py @@ -22,7 +22,7 @@ class Sound: def __init__( self, - sound: pygame.mixer.Sound, + sound: str, loop: bool = False, volume: float = 1.0, fade_ms: int = 0, @@ -42,7 +42,11 @@ def __initialize(world: World): world.set(Channels()) -def __update_sounds(world: World): +def __update_sounds( + world: World, + channels: dict[Entity, pygame.mixer.Channel] = {}, + cache: dict[str, pygame.mixer.Sound] = {}, +): """ Met à jour les sons du jeu. """ diff --git a/src/plugins/timing.py b/src/plugins/timing.py index 4d5d3d0..cfdbdcf 100644 --- a/src/plugins/timing.py +++ b/src/plugins/timing.py @@ -5,9 +5,8 @@ lancement du jeu et le temps depuis la dernière frame. from time import time -from typing import Callable from engine import GlobalPlugin, KeepAlive -from engine.ecs import Entity, World +from engine.ecs import World class GlobalTime(KeepAlive, float): @@ -28,16 +27,6 @@ class Delta(KeepAlive, float): """ -class TimedEvent: - """ - Composant permettant d'executer un callback après un certain temps. - """ - - def __init__(self, timer: float, callback: Callable[[World, Entity], object]): - self.timer = timer - self.callback = callback - - def __initialize(world: World): """ Initialise les ressources pour la gestion du temps. @@ -47,22 +36,13 @@ def __initialize(world: World): def __update(world: World): """ - Met à jour les ressources de temps et execute les `TimedEvent`. + Met à jour les ressources de temps. """ - # On met à jour le temps now = time() world[Delta] = delta = now - world[GlobalTime] world[GlobalTime] = now world[Time] += delta - # On met à jour les `TimedEvent` - for entity in world.query(TimedEvent): - event = entity[TimedEvent] - event.timer -= delta - if event.timer <= 0: - del entity[TimedEvent] - event.callback(world, entity) - PLUGIN = GlobalPlugin( [__initialize], diff --git a/src/plugins/writing.py b/src/plugins/writing.py deleted file mode 100644 index d3c1926..0000000 --- a/src/plugins/writing.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Definit un plugin qui crée un texte avec les touches frappées -""" - -from engine import Scene, World -from plugins.inputs import Pressed -from plugins.text import Text -from scenes import CLICK_SOUND - - -class Writing: - """ - Marque une entité comme un texte qui s'ecrit en fonction du clavier - """ - - def __init__( - self, accepted_chars: str, max_chars: int = 10, base_text: str = "" - ) -> None: - self.accepted_chars = accepted_chars - self.max_chars = max_chars - self.base_text = base_text - - -def __update(world: World): - """ - Met a jour les entitées contenant le composant Typing - """ - pressed = world[Pressed] - for entity in world.query(Writing, Text): - writing = entity[Writing] - text = entity[Text] - for key in pressed: - if key == "backspace" and text.text != writing.base_text: - text.text = text.text[:-1] - world.new_entity().set(CLICK_SOUND) - if text.text == "": - text.text = writing.base_text - if key.startswith("["): # pavé numerique - key = key[1] - if key in writing.accepted_chars and ( - text.text == writing.base_text or len(text.text) < writing.max_chars - ): - if text.text == writing.base_text: - text.text = key - else: - text.text += key - world.new_entity().set(CLICK_SOUND) - if text.text == "": - text.text = writing.base_text - - -PLUGIN = Scene( - [], - [__update], - [], -) diff --git a/src/scenes/__init__.py b/src/scenes/__init__.py index e3b14b0..44fb452 100644 --- a/src/scenes/__init__.py +++ b/src/scenes/__init__.py @@ -1,8 +1,3 @@ """ Module contenant toutes les scènes du jeu. """ - -from plugins.multisound import MultiSound - - -CLICK_SOUND = MultiSound("click/0", "click/1", "click/2")