Amélioration des systèmes de base

This commit is contained in:
Tipragot 2023-10-25 15:36:29 +02:00
parent b07814c440
commit f56fe137fa
4 changed files with 182 additions and 33 deletions

View file

@ -264,15 +264,29 @@ class Game:
*plugins: Les plugins a ajouter au jeu. *plugins: Les plugins a ajouter au jeu.
""" """
self._running = False self._running = False
self._pre_startup_tasks: list[Callable[[World], None]] = []
self._startup_tasks: list[Callable[[World], None]] = [] self._startup_tasks: list[Callable[[World], None]] = []
self._post_startup_tasks: list[Callable[[World], None]] = []
self._pre_update_tasks: list[Callable[[World], None]] = [] self._pre_update_tasks: list[Callable[[World], None]] = []
self._update_tasks: list[Callable[[World], None]] = [] self._update_tasks: list[Callable[[World], None]] = []
self._post_update_tasks: list[Callable[[World], None]] = [] self._post_update_tasks: list[Callable[[World], None]] = []
self._pre_render_tasks: list[Callable[[World], None]] = []
self._render_tasks: list[Callable[[World], None]] = [] self._render_tasks: list[Callable[[World], None]] = []
self._post_render_tasks: list[Callable[[World], None]] = []
self._pre_shutdown_tasks: list[Callable[[World], None]] = []
self._shutdown_tasks: list[Callable[[World], None]] = [] self._shutdown_tasks: list[Callable[[World], None]] = []
self._post_shutdown_tasks: list[Callable[[World], None]] = []
for plugin in plugins: for plugin in plugins:
plugin.apply(self) plugin.apply(self)
def add_pre_startup_tasks(self, *tasks: Callable[[World], None]) -> None:
"""
Ajoute des taches qui s'executeront en premier avant le démarrage du jeu.
"""
if self._running:
raise RuntimeError("Cannot add a task while the loop is running")
self._pre_startup_tasks.extend(tasks)
def add_startup_tasks(self, *tasks: Callable[[World], None]) -> None: def add_startup_tasks(self, *tasks: Callable[[World], None]) -> None:
""" """
Ajoute des taches qui s'executeront au démarrage du jeu. Ajoute des taches qui s'executeront au démarrage du jeu.
@ -284,6 +298,14 @@ class Game:
raise RuntimeError("Cannot add a task while the loop is running") raise RuntimeError("Cannot add a task while the loop is running")
self._startup_tasks.extend(tasks) self._startup_tasks.extend(tasks)
def add_post_startup_tasks(self, *tasks: Callable[[World], None]) -> None:
"""
Ajoute des taches qui s'executeront en dernier après le démarrage du jeu.
"""
if self._running:
raise RuntimeError("Cannot add a task while the loop is running")
self._post_startup_tasks.extend(tasks)
def add_pre_update_tasks(self, *tasks: Callable[[World], None]) -> None: def add_pre_update_tasks(self, *tasks: Callable[[World], None]) -> None:
""" """
Ajoute des taches qui s'executeront au debut de chaque mise à jour du jeu. Ajoute des taches qui s'executeront au debut de chaque mise à jour du jeu.
@ -317,6 +339,17 @@ class Game:
raise RuntimeError("Cannot add a task while the loop is running") raise RuntimeError("Cannot add a task while the loop is running")
self._post_update_tasks.extend(tasks) self._post_update_tasks.extend(tasks)
def add_pre_render_tasks(self, *tasks: Callable[[World], None]) -> None:
"""
Ajoute des taches qui s'executeront au début de chaque mise à jour du jeu pour le rendu.
Paramètres:
*tasks: Les taches à ajouter.
"""
if self._running:
raise RuntimeError("Cannot add a task while the loop is running")
self._pre_render_tasks.extend(tasks)
def add_render_tasks(self, *tasks: Callable[[World], None]) -> None: def add_render_tasks(self, *tasks: Callable[[World], None]) -> None:
""" """
Ajoute des taches qui s'executeront après chaque mise à jour du jeu pour le rendu. Ajoute des taches qui s'executeront après chaque mise à jour du jeu pour le rendu.
@ -328,6 +361,25 @@ class Game:
raise RuntimeError("Cannot add a task while the loop is running") raise RuntimeError("Cannot add a task while the loop is running")
self._render_tasks.extend(tasks) self._render_tasks.extend(tasks)
def add_post_render_tasks(self, *tasks: Callable[[World], None]) -> None:
"""
Ajoute des taches qui s'executeront après chaque mise à jour du jeu pour le rendu.
Paramètres:
*tasks: Les taches à ajouter.
"""
if self._running:
raise RuntimeError("Cannot add a task while the loop is running")
self._post_render_tasks.extend(tasks)
def add_pre_shutdown_tasks(self, *tasks: Callable[[World], None]) -> None:
"""
Ajoute des taches qui s'executeront au début de la fin de la boucle de jeu.
"""
if self._running:
raise RuntimeError("Cannot add a task while the loop is running")
self._pre_shutdown_tasks.extend(tasks)
def add_shutdown_tasks(self, *tasks: Callable[[World], None]) -> None: def add_shutdown_tasks(self, *tasks: Callable[[World], None]) -> None:
""" """
Ajoute des taches qui s'executeront à la fin de la boucle de jeu. Ajoute des taches qui s'executeront à la fin de la boucle de jeu.
@ -339,6 +391,14 @@ class Game:
raise RuntimeError("Cannot add a task while the loop is running") raise RuntimeError("Cannot add a task while the loop is running")
self._shutdown_tasks.extend(tasks) self._shutdown_tasks.extend(tasks)
def add_post_shutdown_tasks(self, *tasks: Callable[[World], None]) -> None:
"""
Ajoute des taches qui s'executeront à la fin de la fin de la boucle de jeu.
"""
if self._running:
raise RuntimeError("Cannot add a task while the loop is running")
self._post_shutdown_tasks.extend(tasks)
def run(self, world: World = World()) -> World: def run(self, world: World = World()) -> World:
""" """
Lance la boucle de jeu. Lance la boucle de jeu.
@ -351,6 +411,14 @@ class Game:
world.set(self) world.set(self)
world.apply() world.apply()
# On execute les taches de pré initialisation du monde
for task in self._pre_startup_tasks:
try:
task(world)
except Exception as e:
error(f"Error during pre-startup task: {e}")
world.apply()
# On execute les taches d'initialisation du monde # On execute les taches d'initialisation du monde
for task in self._startup_tasks: for task in self._startup_tasks:
try: try:
@ -359,6 +427,14 @@ class Game:
error(f"Error during startup task: {e}") error(f"Error during startup task: {e}")
world.apply() world.apply()
# On execute les taches de post initialisation du monde
for task in self._post_startup_tasks:
try:
task(world)
except Exception as e:
error(f"Error during post-startup task: {e}")
world.apply()
while self._running: while self._running:
# On execute les taches de pré mise à jour du monde # On execute les taches de pré mise à jour du monde
for task in self._pre_update_tasks: for task in self._pre_update_tasks:
@ -392,6 +468,22 @@ class Game:
error(f"Error during render task: {e}") error(f"Error during render task: {e}")
world.apply() world.apply()
# On execute les taches de fin de rendu du jeu
for task in self._post_render_tasks:
try:
task(world)
except Exception as e:
error(f"Error during post-render task: {e}")
world.apply()
# On execute les taches de pré fin de boucle
for task in self._pre_shutdown_tasks:
try:
task(world)
except Exception as e:
error(f"Error during pre-shutdown task: {e}")
world.apply()
# On exécute les taches de fin du monde # On exécute les taches de fin du monde
for task in self._shutdown_tasks: for task in self._shutdown_tasks:
try: try:
@ -400,6 +492,14 @@ class Game:
error(f"Error during shutdown task: {e}") error(f"Error during shutdown task: {e}")
world.apply() world.apply()
# On execute les taches de post fin de boucle
for task in self._post_shutdown_tasks:
try:
task(world)
except Exception as e:
error(f"Error during post-shutdown task: {e}")
world.apply()
# On retourne le monde # On retourne le monde
return world return world

View file

@ -3,31 +3,71 @@ Définis des classes utiles.
""" """
import math
class Vec2: class Vec2:
""" """
Un vecteur 2D Un vecteur 2D
""" """
def __init__(self, x: float, y: float) -> None: def __init__(self, x: float = 0, y: float = 0) -> None:
self.x = x self.x = float(x)
self.y = y self.y = float(y)
def __add__(self, other: "Vec2") -> "Vec2": def __add__(self, other: object) -> "Vec2":
if isinstance(other, Vec2):
return Vec2(self.x + other.x, self.y + other.y) return Vec2(self.x + other.x, self.y + other.y)
elif isinstance(other, float):
return Vec2(self.x + other, self.y + other)
return Vec2(float("nan"), float("nan"))
def __sub__(self, other: "Vec2") -> "Vec2": def __sub__(self, other: object) -> "Vec2":
if isinstance(other, Vec2):
return Vec2(self.x - other.x, self.y - other.y) return Vec2(self.x - other.x, self.y - other.y)
elif isinstance(other, float):
return Vec2(self.x - other, self.y - other)
return Vec2(float("nan"), float("nan"))
def __mul__(self, other: "Vec2") -> "Vec2": def __mul__(self, other: object) -> "Vec2":
if isinstance(other, Vec2):
return Vec2(self.x * other.x, self.y * other.y) return Vec2(self.x * other.x, self.y * other.y)
elif isinstance(other, float):
return Vec2(self.x * other, self.y * other)
return Vec2(float("nan"), float("nan"))
def __div__(self, other: "Vec2") -> "Vec2": def __truediv__(self, other: object) -> "Vec2":
if isinstance(other, Vec2):
return Vec2(self.x / other.x, self.y / other.y) return Vec2(self.x / other.x, self.y / other.y)
elif isinstance(other, float):
return Vec2(self.x / other, self.y / other)
return Vec2(float("nan"), float("nan"))
def __eq__(self, other: object) -> bool: def __eq__(self, other: object) -> bool:
if isinstance(other, Vec2): if isinstance(other, Vec2):
return self.x == other.x and self.y == other.y return self.x == other.x and self.y == other.y
return False return False
def __hash__(self) -> int:
return hash((self.x, self.y))
def __neg__(self) -> "Vec2":
return Vec2(-self.x, -self.y)
@property
def length(self) -> float:
"""
Retourne la longueur du vecteur.
"""
return math.sqrt(self.x**2 + self.y**2)
@property
def normalized(self) -> "Vec2":
"""
Retourne une version normalisé du vecteur.
"""
length = self.length
return Vec2(self.x / length, self.y / length)
def __repr__(self) -> str: def __repr__(self) -> str:
return f"Vec2({self.x}, {self.y})" return f"Vec2({self.x}, {self.y})"

View file

@ -3,9 +3,8 @@ Définit un plugin qui gère les évenements pygame.
""" """
from engine import * from engine import *
import pygame
from engine.math import Vec2 from engine.math import Vec2
import pygame
class PygamePlugin(Plugin): class PygamePlugin(Plugin):
@ -14,14 +13,20 @@ class PygamePlugin(Plugin):
""" """
@staticmethod @staticmethod
def _initialize_pygame(world: World) -> None: def _initialize(world: World) -> None:
pygame.init() pygame.init()
# Initialisation des ressources # Initialisation des ressources
world.set(Display(pygame.display.set_mode((640, 480))), Keyboard(), Mouse()) world.set(
Display(pygame.display.set_mode((800, 600), pygame.RESIZABLE)),
Keyboard(),
Mouse(),
)
@staticmethod @staticmethod
def _check_events(world: World) -> None: def _check_events(world: World) -> None:
world[Display].size = Vec2(*pygame.display.get_surface().get_size())
keyboard = world[Keyboard] keyboard = world[Keyboard]
keyboard.pressed.clear() keyboard.pressed.clear()
keyboard.released.clear() keyboard.released.clear()
@ -51,7 +56,16 @@ class PygamePlugin(Plugin):
mouse.position = Vec2(float(event.pos[0]), float(event.pos[1])) mouse.position = Vec2(float(event.pos[0]), float(event.pos[1]))
@staticmethod @staticmethod
def _terminate_pygame(world: World) -> None: def _flip_display(world: World) -> None:
"""
Met a jour le rendu de l'écran.
"""
display = world[Display]
pygame.display.flip()
pygame.display.get_surface().fill((0, 0, 0))
@staticmethod
def _terminate(world: World) -> None:
pygame.quit() pygame.quit()
def apply(self, game: Game) -> None: def apply(self, game: Game) -> None:
@ -61,9 +75,10 @@ class PygamePlugin(Plugin):
Paramètres: Paramètres:
game: Le jeu auquel appliquer le plugin. game: Le jeu auquel appliquer le plugin.
""" """
game.add_startup_tasks(self._initialize_pygame) game.add_pre_startup_tasks(self._initialize)
game.add_pre_update_tasks(self._check_events) game.add_pre_update_tasks(self._check_events)
game.add_shutdown_tasks(self._terminate_pygame) game.add_post_render_tasks(self._flip_display)
game.add_post_shutdown_tasks(self._terminate)
class Display: class Display:
@ -71,28 +86,22 @@ class Display:
Ressource qui represente la fenetre du jeu. Ressource qui represente la fenetre du jeu.
""" """
def __init__(self, surface: pygame.Surface) -> None: def __init__(self, display: pygame.Surface) -> None:
self.surface = surface self.size: Vec2 = Vec2(*display.get_size())
@property @property
def width(self) -> int: def width(self) -> float:
""" """
Renvoie la largeur de la fenetre Retourne la largeur de la fenetre.
Retourne:
La largeur de la fenetre
""" """
return self.surface.get_width() return self.size.x
@property @property
def height(self) -> int: def height(self) -> float:
""" """
Renvoie la hauteur de la fenetre Retourne la hauteur de la fenetre.
Retourne:
La hauteur de la fenetre
""" """
return self.surface.get_height() return self.size.y
class Keyboard: class Keyboard:

View file

@ -24,7 +24,7 @@ class TimePlugin(Plugin):
""" """
Applique le plugin a un jeu. Applique le plugin a un jeu.
""" """
game.add_startup_tasks(self._initialize_time) game.add_pre_startup_tasks(self._initialize_time)
game.add_pre_update_tasks(self._update_time) game.add_pre_update_tasks(self._update_time)