102 lines
2.9 KiB
Python
102 lines
2.9 KiB
Python
"""
|
|
Un plugin qui permet de jouer des animations de sprites.
|
|
"""
|
|
|
|
from typing import Callable
|
|
|
|
import pygame
|
|
from engine import GlobalPlugin
|
|
from engine.ecs import Entity, World
|
|
from plugins.assets import Assets
|
|
from plugins.render import Sprite
|
|
from plugins.timing import Delta
|
|
|
|
|
|
class Animation:
|
|
"""
|
|
Composant qui contient toutes les informations d'une animation est en cour
|
|
sur l'entité.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
name: str,
|
|
fps: float = 60.0,
|
|
loop: bool = False,
|
|
callback: Callable[[World, Entity], object] = lambda _w, _e: None,
|
|
) -> None:
|
|
self.name = name
|
|
self.fps = fps
|
|
self.loop = loop
|
|
self.callback = callback
|
|
self.timer = 0.0
|
|
self.ended = False
|
|
|
|
def wait(self) -> Callable[[World], bool]:
|
|
"""
|
|
Utilitaire de `Coroutine` permettant d'attendre que l'animation soit finie.
|
|
"""
|
|
return lambda world: self.ended
|
|
|
|
|
|
def __update_sprite(entity: Entity, texture: pygame.Surface, assets: Assets):
|
|
"""
|
|
Change la texture de la `Sprite` d'une entité.
|
|
|
|
Si l'entité n'as pas de `Sprite`, une nouvelle `Sprite` sera ajoutée.
|
|
Si la texture est la texture d'erreur, la texture de la `Sprite` ne
|
|
sera pas changée.
|
|
"""
|
|
if texture is assets.error_texture:
|
|
return
|
|
if Sprite not in entity:
|
|
entity[Sprite] = Sprite(texture)
|
|
else:
|
|
entity[Sprite].texture = texture
|
|
|
|
|
|
def __update_animations(world: World) -> None:
|
|
"""
|
|
Met à jour les sprites des animations.
|
|
"""
|
|
assets = world[Assets]
|
|
delta = world[Delta]
|
|
for entity in world.query(Animation):
|
|
animation = entity[Animation]
|
|
animation.timer += delta
|
|
|
|
# On récupère la texture correspondante a la frame de l'animation
|
|
frame_index = int(animation.timer * animation.fps)
|
|
texture = assets.get_texture(f"{animation.name}/{frame_index:04d}")
|
|
|
|
# Si la texture n'existe pas, l'animation est finie
|
|
if texture is assets.error_texture:
|
|
if animation.loop:
|
|
# Si l'animation est une boucle on met la première image de l'animation
|
|
animation.timer = 0.0
|
|
__update_sprite(
|
|
entity, assets.get_texture(f"{animation.name}/0000"), assets
|
|
)
|
|
|
|
# Et on appelle la fonction de callback
|
|
animation.callback(world, entity)
|
|
else:
|
|
# Sinon on supprime le composant `Animation`
|
|
del entity[Animation]
|
|
animation.ended = True
|
|
|
|
# Et on appelle la fonction de callback
|
|
animation.callback(world, entity)
|
|
else:
|
|
# Si l'animation n'est pas finie, on met à jour la texture
|
|
__update_sprite(entity, texture, assets)
|
|
animation.ended = False
|
|
|
|
|
|
PLUGIN = GlobalPlugin(
|
|
[],
|
|
[],
|
|
[__update_animations],
|
|
[],
|
|
)
|