This commit is contained in:
Timéo Cézard 2024-01-03 03:14:53 +01:00
parent 6fa1b5c70f
commit bac035f00d
25 changed files with 557 additions and 190 deletions

View file

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View file

@ -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: class Entity:
@ -17,15 +17,6 @@ class Entity:
utilitaire pour acceder au monde plus facilement. 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: def __init__(self, world: "World", identifier: int) -> None:
self.__world = world self.__world = world
self.__identifier = identifier self.__identifier = identifier
@ -55,13 +46,13 @@ class Entity:
def __repr__(self) -> str: def __repr__(self) -> str:
return f"Entity({self.__identifier})" 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) return self.__world.get_component(self, component_type)
def __delitem__(self, component_type: type[object]): def __delitem__(self, component_type: type[object]):
self.__world.remove_component(self, component_type) 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): if component_type != type(component):
component = component_type(component) component = component_type(component)
self.__world.set_component(self, component) self.__world.set_component(self, component)
@ -75,7 +66,7 @@ class Entity:
def __iter__(self) -> Iterator[object]: def __iter__(self) -> Iterator[object]:
return iter(self.__world.all_components(self)) 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é. Renvoie le composant de type `component_type` de l'entité.
Si aucun composant de type `component_type` n'est dans 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. 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): def __init__(self):
super().__init__(self, 0) super().__init__(self, 0)
self.__components: dict[int, dict[type[object], object]] = {} self.__components: dict[int, dict[type[object], object]] = {}
@ -167,9 +149,9 @@ class World(Entity):
self.__components.setdefault(entity.identifier, {})[type(component)] = component self.__components.setdefault(entity.identifier, {})[type(component)] = component
self.__entities.setdefault(type(component), set()).add(entity.identifier) self.__entities.setdefault(type(component), set()).add(entity.identifier)
def get_component( def get_component[T](
self, entity: "Entity", component_type: type[__T], default: Optional[__T] = None self, entity: "Entity", component_type: type[T], default: Optional[T] = None
) -> __T: ) -> T:
""" """
Renvoie le composant de type `component_type` de l'entité `entity`. Renvoie le composant de type `component_type` de l'entité `entity`.
Si aucun composant de type `component_type` n'est dans l'entité: Si aucun composant de type `component_type` n'est dans l'entité:

View file

@ -2,9 +2,29 @@
Module d'exemple de l'utilisation du moteur de jeu. 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 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)

View file

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

48
src/plugins save/click.py Normal file
View file

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

View file

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

View file

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

92
src/plugins save/hover.py Normal file
View file

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

View file

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

106
src/plugins save/render.py Normal file
View file

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

View file

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

View file

@ -2,12 +2,13 @@
Un plugin permettant de savoir si l'on a cliqué sur une entité. Un plugin permettant de savoir si l'on a cliqué sur une entité.
""" """
from tkinter import Scale
from typing import Callable from typing import Callable
from engine import GlobalPlugin from engine import GlobalPlugin
from engine.ecs import Entity, World from engine.ecs import Entity, World
from plugins.hover import Hovered from plugins.hover import Hovered
from plugins.inputs import Pressed from plugins.inputs import Pressed
from plugins.render import Sprite from plugins.render import Position
class Clicked: class Clicked:
@ -30,7 +31,7 @@ def __update_clicked(world: World):
Met à jour les composants `Clicked`. Met à jour les composants `Clicked`.
""" """
mouse_click = "button_1" in world[Pressed] mouse_click = "button_1" in world[Pressed]
sprite_entities = world.query(Sprite) sprite_entities = world.query(Position, Scale)
for entity in sprite_entities: for entity in sprite_entities:
if Hovered in entity and mouse_click: if Hovered in entity and mouse_click:
entity[Clicked] = Clicked() entity[Clicked] = Clicked()

View file

@ -2,33 +2,14 @@
Plugin qui rassemple tous les plugins globaux. Plugin qui rassemple tous les plugins globaux.
""" """
from plugins import ( from plugins import display, inputs, sound, render, timing, hover
animation,
assets,
click,
coroutine,
display,
hover,
inputs,
multisound,
render,
sound,
text,
timing,
)
PLUGIN = ( PLUGIN = (
display.PLUGIN display.PLUGIN
+ timing.PLUGIN + timing.PLUGIN
+ assets.PLUGIN
+ inputs.PLUGIN + inputs.PLUGIN
+ hover.PLUGIN + hover.PLUGIN
+ click.PLUGIN
+ coroutine.PLUGIN
+ multisound.PLUGIN
+ sound.PLUGIN + sound.PLUGIN
+ text.PLUGIN
+ animation.PLUGIN
+ render.PLUGIN + render.PLUGIN
) )

View file

@ -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 import GlobalPlugin
from engine.ecs import World from engine.ecs import World
from engine.math import Vec2
from plugins.inputs import MousePosition from plugins.inputs import MousePosition
from plugins.render import Sprite from plugins.render import Origin, Position, Scale, Texture
class HoverEnter: class HoverEnter:
@ -36,7 +33,7 @@ class HoveredTexture:
celle-ci est survolée par la souris. 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.normal = normal
self.hovered = hovered self.hovered = hovered
@ -47,11 +44,10 @@ def __update_hovered(world: World):
""" """
# On met à jour les composants # On met à jour les composants
mouse_position = world[MousePosition] 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é # Récupération de la position et taille de l'entité
sprite = entity[Sprite] size = entity[Scale]
size = Vec2(*sprite.texture.get_size()) * Vec2(*sprite.area[2:]) position = entity[Position] - (entity.get(Origin, Origin(0)) * size)
position = sprite.position - (sprite.origin * size)
# On détermine si la souris est sur l'entité # On détermine si la souris est sur l'entité
if ( if (
@ -75,13 +71,9 @@ def __update_hovered(world: World):
# On affiche la bonne texture # On affiche la bonne texture
for entity in world.query(HoveredTexture): for entity in world.query(HoveredTexture):
if Hovered in entity: if Hovered in entity:
texture = entity[HoveredTexture].hovered entity[Texture] = entity[HoveredTexture].hovered
else: else:
texture = entity[HoveredTexture].normal entity[Texture] = entity[HoveredTexture].normal
if Sprite in entity:
entity[Sprite].texture = texture
else:
entity[Sprite] = Sprite(texture)
PLUGIN = GlobalPlugin( PLUGIN = GlobalPlugin(

View file

@ -2,7 +2,6 @@
Un plugin qui s'occupe de rendre des choses dans la fenetre. Un plugin qui s'occupe de rendre des choses dans la fenetre.
""" """
from typing import Optional
import pygame import pygame
from engine import GlobalPlugin, KeepAlive from engine import GlobalPlugin, KeepAlive
from engine.ecs import World 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) 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): class Surface(KeepAlive, pygame.Surface):
""" """
Ressource qui stocke la surface de rendu du jeu. 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): def __initialize(world: World):
""" """
Prépare le monde pour la gestion du rendu. Prépare le monde pour la gestion du rendu.
@ -65,27 +71,25 @@ def __initialize(world: World):
world.set(Surface((WIDTH, HEIGHT))) 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. Rend le monde du jeu sur la surface puis l'affiche sur la fenetre.
""" """
# On rend le monde sur la surface # On rend le monde sur la surface
surface = world[Surface] surface: Surface = world[Surface]
sprites = [entity[Sprite] for entity in world.query(Sprite)] entities = sorted(world.query(Texture), key=lambda entity: entity.get(Order, -1))
for sprite in sorted(sprites, key=lambda sprite: sprite.order): for entity in entities:
original_size = Vec2(*sprite.texture.get_size()) texture_name = entity[Texture]
size = original_size * Vec2(*sprite.area[2:]) texture = cache.get(texture_name)
position = sprite.position - (sprite.origin * size) if texture is None:
surface.blit( texture = pygame.image.load(f"assets/textures/{texture_name}")
sprite.texture, cache[texture_name] = texture
(position.x, position.y), scale = entity.get(Scale, Scale(128))
( texture = pygame.transform.scale(texture, (scale.x, scale.y))
sprite.area[0] * original_size.x, position = (
sprite.area[1] * original_size.y, entity.get(Position, Position(0)) - (entity.get(Origin, Origin(0))) * scale
sprite.area[2] * original_size.x,
sprite.area[3] * original_size.y,
),
) )
surface.blit(texture, (position.x, position.y))
# On affiche la surface sur la fenetre # On affiche la surface sur la fenetre
rect = calculate_surface_rect() rect = calculate_surface_rect()

View file

@ -22,7 +22,7 @@ class Sound:
def __init__( def __init__(
self, self,
sound: pygame.mixer.Sound, sound: str,
loop: bool = False, loop: bool = False,
volume: float = 1.0, volume: float = 1.0,
fade_ms: int = 0, fade_ms: int = 0,
@ -42,7 +42,11 @@ def __initialize(world: World):
world.set(Channels()) 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. Met à jour les sons du jeu.
""" """

View file

@ -5,9 +5,8 @@ lancement du jeu et le temps depuis la dernière frame.
from time import time from time import time
from typing import Callable
from engine import GlobalPlugin, KeepAlive from engine import GlobalPlugin, KeepAlive
from engine.ecs import Entity, World from engine.ecs import World
class GlobalTime(KeepAlive, float): 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): def __initialize(world: World):
""" """
Initialise les ressources pour la gestion du temps. Initialise les ressources pour la gestion du temps.
@ -47,22 +36,13 @@ def __initialize(world: World):
def __update(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() now = time()
world[Delta] = delta = now - world[GlobalTime] world[Delta] = delta = now - world[GlobalTime]
world[GlobalTime] = now world[GlobalTime] = now
world[Time] += delta 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( PLUGIN = GlobalPlugin(
[__initialize], [__initialize],

View file

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

View file

@ -1,8 +1,3 @@
""" """
Module contenant toutes les scènes du jeu. Module contenant toutes les scènes du jeu.
""" """
from plugins.multisound import MultiSound
CLICK_SOUND = MultiSound("click/0", "click/1", "click/2")