Ajout d'un système de coroutines

This commit is contained in:
Tipragot 2023-11-01 22:04:33 +01:00
parent ce232071c1
commit cb11a10a13
3 changed files with 112 additions and 11 deletions

View file

@ -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)),
)
],
[],

85
src/plugins/coroutine.py Normal file
View file

@ -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],
[],
[],
)

View file

@ -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