diff --git a/src/main.py b/src/main.py index 950163e..fade011 100644 --- a/src/main.py +++ b/src/main.py @@ -3,10 +3,21 @@ Module d'exemple de l'utilisation du moteur de jeu. """ from engine import Scene, start_game +from engine.ecs import World from plugins import assets, defaults -from plugins.animation import Animation -from plugins.render import Sprite -from plugins.sound import Sound +from plugins.coroutine import Coroutine, condition, wait +from plugins.inputs import MousePosition + + +def super_fonction_du_turfu(world: World): + """ + Fonction du turfu qui s'execute sur plusieurs frames. + """ + print("LOL") + yield wait(10.0) + print("LOL 10 secondes après") + yield condition(lambda world: world.get(MousePosition).x > 500) + print("La souris est a droite !") start_game( @@ -15,13 +26,7 @@ start_game( Scene( [ lambda world: world.new_entity().set( - Animation( - "animations/intro", - callback=lambda world, entity: entity.set( - Sound(world[assets.Assets].get_sound("edqsd")) - ), - ), - Sprite(world[assets.Assets].get_texture("intro")), + Coroutine(super_fonction_du_turfu(world)), ) ], [], diff --git a/src/plugins/coroutine.py b/src/plugins/coroutine.py new file mode 100644 index 0000000..6b30659 --- /dev/null +++ b/src/plugins/coroutine.py @@ -0,0 +1,85 @@ +""" +Plugin permettant d'executer des coroutine. + +Une coroutine est une fonction qui est executée sur plusieurs frames, +cela permet d'executer du code comme si il s'agissait d'une fonction +classique tout en laissant tourner la boucle du jeu. Il est a noter que +cette fonction n'est pas lancé dans une autre thread, la fonction est +executé dans le thread principal, mais lorsqu'un `yield` est utilisé, +l'execution de la fonction est arrêté jusqu'a ce que la condition donné +par le `yield` soit remplie, ce qui permet au thread principal de pouvoir +continuer de faire le rendu et la logique du jeu. Faire un traivail bloquant +dans une coroutine auras donc un impacte sur le nombre d'images par secondes +du jeu. +""" + + +from time import time +from typing import Callable, Generator, Optional +from engine import GlobalPlugin +from engine.ecs import Entity, World +from plugins.timing import GlobalTime + + +def wait(seconds: float) -> Callable[[World], bool]: + """ + Utilitaire de `Coroutine` permettant d'attendre un certain temps. + """ + stop_time = time() + seconds + return lambda world: world[GlobalTime] >= stop_time + + +def condition(condition_function: Callable[[World], bool]) -> Callable[[World], bool]: + """ + Utilitaire de `Coroutine` permettant d'attendre que la condition soit réalisé avant + de continuer l'execution. + """ + return condition_function + + +class Coroutine: + """ + Composant permettant d'executer une coroutine. + """ + + def __init__(self, generator: Generator[Callable[[World], bool], None, None]): + self.generator = generator + self.__condition: Optional[ # pylint: disable=unused-private-member + Callable[[World], bool] + ] = None + + @staticmethod + def update(entity: Entity): + """ + Met à jour la coroutine d'une entité. + + Si l'entité n'as pas de `Coroutine` la fonction ne fait rien. + """ + if Coroutine not in entity: + return + coroutine = entity[Coroutine] + if coroutine.__condition is None: + coroutine.__condition = next( # pylint: disable=unused-private-member + coroutine.generator, None + ) + if coroutine.__condition is None: + del entity[Coroutine] + return + if coroutine.__condition(entity.world): + coroutine.__condition = None # pylint: disable=unused-private-member + + +def __update_coroutines(world: World): + """ + Met à jour les coroutine du jeu. + """ + for entity in world.query(Coroutine): + Coroutine.update(entity) + + +PLUGIN = GlobalPlugin( + [], + [__update_coroutines], + [], + [], +) diff --git a/src/plugins/defaults.py b/src/plugins/defaults.py index e963ca1..7235082 100644 --- a/src/plugins/defaults.py +++ b/src/plugins/defaults.py @@ -2,7 +2,17 @@ Plugin qui rassemple tous les plugins globaux. """ -from plugins import animation, assets, display, inputs, render, sound, text, timing +from plugins import ( + animation, + assets, + coroutine, + display, + inputs, + render, + sound, + text, + timing, +) PLUGIN = ( @@ -10,6 +20,7 @@ PLUGIN = ( + timing.PLUGIN + assets.PLUGIN + inputs.PLUGIN + + coroutine.PLUGIN + sound.PLUGIN + text.PLUGIN + animation.PLUGIN