ecs #58
|
@ -3,6 +3,7 @@ Un plugin permettant d'afficher du texte à l'écran.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
import pygame
|
import pygame
|
||||||
|
|
||||||
from engine import GlobalPlugin
|
from engine import GlobalPlugin
|
||||||
|
@ -22,9 +23,9 @@ class Text:
|
||||||
text: str,
|
text: str,
|
||||||
size: int = 50,
|
size: int = 50,
|
||||||
color: pygame.Color = pygame.Color(255, 255, 255),
|
color: pygame.Color = pygame.Color(255, 255, 255),
|
||||||
position: Vec2 = Vec2(0),
|
position: Optional[Vec2] = None,
|
||||||
order: float = -1.0,
|
order: Optional[float] = None,
|
||||||
origin: Vec2 = Vec2(0),
|
origin: Optional[Vec2] = None,
|
||||||
):
|
):
|
||||||
self.text = text
|
self.text = text
|
||||||
self.size = size
|
self.size = size
|
||||||
|
@ -48,8 +49,11 @@ def __render_texts(world: World):
|
||||||
entity[Sprite].texture = texture
|
entity[Sprite].texture = texture
|
||||||
else:
|
else:
|
||||||
entity[Sprite] = Sprite(texture)
|
entity[Sprite] = Sprite(texture)
|
||||||
|
if text.position is not None:
|
||||||
entity[Sprite].position = text.position
|
entity[Sprite].position = text.position
|
||||||
|
if text.order is not None:
|
||||||
entity[Sprite].order = text.order
|
entity[Sprite].order = text.order
|
||||||
|
if text.origin is not None:
|
||||||
entity[Sprite].origin = text.origin
|
entity[Sprite].origin = text.origin
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,15 +3,92 @@ Scène du jeu dans lequel Windows Defender se cache de Edmond dans les dossiers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from engine import Scene
|
from engine import Scene
|
||||||
from engine.ecs import Entity
|
from engine.ecs import Entity, World
|
||||||
from engine.math import Vec2
|
from engine.math import Vec2
|
||||||
from plugins import assets as plugin_assets, render
|
from plugins import assets as plugin_assets, render, smooth
|
||||||
|
from plugins.click import Clicked
|
||||||
|
from plugins.inputs import Held, MousePosition
|
||||||
|
from plugins.assets import Assets
|
||||||
|
from plugins.render import Sprite
|
||||||
|
from plugins.sound import Sound
|
||||||
|
from plugins.text import Text
|
||||||
|
|
||||||
|
|
||||||
LINES = 3
|
LINES = 3
|
||||||
COLUMNS = 5
|
COLUMNS = 5
|
||||||
SPACING = 200
|
SPACING = 200
|
||||||
|
|
||||||
|
NAMES = [
|
||||||
|
"Classique",
|
||||||
|
"Menteur",
|
||||||
|
"Tricheur",
|
||||||
|
"Histoire",
|
||||||
|
"Je t'aime",
|
||||||
|
"Hello",
|
||||||
|
"Cheval",
|
||||||
|
"Defender",
|
||||||
|
"Dansons",
|
||||||
|
"Secrets",
|
||||||
|
"Edmond",
|
||||||
|
"Mon Amour",
|
||||||
|
"Melatonin",
|
||||||
|
"Films",
|
||||||
|
"Cinéma",
|
||||||
|
]
|
||||||
|
|
||||||
|
POSITIONS = [
|
||||||
|
Vec2(1348, 903),
|
||||||
|
Vec2(988, 903),
|
||||||
|
Vec2(808, 737),
|
||||||
|
Vec2(628, 903),
|
||||||
|
Vec2(268, 903),
|
||||||
|
Vec2(1168, 405),
|
||||||
|
Vec2(988, 571),
|
||||||
|
Vec2(808, 405),
|
||||||
|
Vec2(448, 737),
|
||||||
|
Vec2(268, 405),
|
||||||
|
Vec2(1348, 239),
|
||||||
|
Vec2(988, 239),
|
||||||
|
Vec2(628, 73),
|
||||||
|
Vec2(448, 239),
|
||||||
|
Vec2(88, 239),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class Directory:
|
||||||
|
"""
|
||||||
|
Composant marquand une entité comme étant un dossier.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class DefenderDirectory:
|
||||||
|
"""
|
||||||
|
Composant marquant une entité comme étant le dossier de Windows Defender.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class BlockedDirectory:
|
||||||
|
"""
|
||||||
|
Composant marquant une entité comme etant un dossier bloqué.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class SearchingDirectory:
|
||||||
|
"""
|
||||||
|
Composant marquant une entité comme etant un dossier en train de être fouillé.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class DirectoryName:
|
||||||
|
"""
|
||||||
|
Composant marquant une entité comme étant le nom d'un dossier.
|
||||||
|
|
||||||
|
Ce composant contient l'entité auquel il est lie.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, entity: Entity):
|
||||||
|
self.entity = entity
|
||||||
|
|
||||||
|
|
||||||
class DirectoryPosition(Vec2):
|
class DirectoryPosition(Vec2):
|
||||||
"""
|
"""
|
||||||
|
@ -37,16 +114,140 @@ class SelectedDirectory:
|
||||||
de la souris lors du clic.
|
de la souris lors du clic.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, entity: Entity, position: Vec2):
|
def __init__(self, entity: Entity, mouse_position: Vec2):
|
||||||
self.entity = entity
|
self.entity = entity
|
||||||
self.position = position
|
self.mouse_position = mouse_position
|
||||||
|
|
||||||
|
|
||||||
|
def __initialize(world: World):
|
||||||
|
"""
|
||||||
|
Prépare le monde pour le lancement de la scène.
|
||||||
|
|
||||||
|
Cette fonction fait apparaitre tous les dossiers et lance la boucle de jeu.
|
||||||
|
"""
|
||||||
|
assets = world[Assets]
|
||||||
|
|
||||||
|
# Ajout du fond
|
||||||
|
world.new_entity().set(Sprite(assets.get_texture("background")))
|
||||||
|
|
||||||
|
# Ajout des dossiers et des noms
|
||||||
|
directory_texture = assets.get_texture("directory")
|
||||||
|
for y in range(LINES):
|
||||||
|
for x in range(COLUMNS):
|
||||||
|
# Récupération du nom et de la position
|
||||||
|
position = POSITIONS.pop()
|
||||||
|
name = NAMES.pop()
|
||||||
|
|
||||||
|
# Création de l'entité du dossier
|
||||||
|
entity = world.new_entity()
|
||||||
|
entity.set(
|
||||||
|
Sprite(directory_texture, position, 1, origin=Vec2(0.5)),
|
||||||
|
DirectoryPosition(x, y),
|
||||||
|
Directory(),
|
||||||
|
)
|
||||||
|
if name == "Defender":
|
||||||
|
entity.set(DefenderDirectory())
|
||||||
|
entity[Sprite].texture = assets.get_texture("defender_directory")
|
||||||
|
|
||||||
|
# Création de l'entité du nom
|
||||||
|
world.new_entity().set(
|
||||||
|
Sprite(directory_texture, position + Vec2(0, 75)),
|
||||||
|
Text(name, 40, order=1, origin=Vec2(0.5)),
|
||||||
|
DirectoryName(entity),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def __control_directories(world: World):
|
||||||
|
"""
|
||||||
|
Ce système gère les déplacements de dossiers fais par l'utilisateur.
|
||||||
|
"""
|
||||||
|
# Si aucuns dossier n'est séléctioné, on attend que l'utilisateur clique sur un dossier, si
|
||||||
|
# le dossier cliqué est en train de être fouillé ou que le dossier est bloqué, on ignore
|
||||||
|
if SelectedDirectory not in world:
|
||||||
|
entities = world.query(
|
||||||
|
Clicked, Directory, without=(SearchingDirectory, BlockedDirectory)
|
||||||
|
)
|
||||||
|
if len(entities) > 0:
|
||||||
|
world.set(SelectedDirectory(entities.pop(), Vec2(world[MousePosition])))
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
selected = world[SelectedDirectory]
|
||||||
|
|
||||||
|
# Si le boutton de la souris a été relaché entre temps, on supprime le dossier selectionné.
|
||||||
|
if "button_1" not in world[Held]:
|
||||||
|
del world[SelectedDirectory]
|
||||||
|
return
|
||||||
|
|
||||||
|
# Ensuite on vérifie de combien la souris a été déplacé depuis la selection du dossier,
|
||||||
|
# si cette valeur est en dessous d'un certain seuil, on ne fais rien
|
||||||
|
mouse_delta = world[MousePosition] - selected.mouse_position
|
||||||
|
if mouse_delta.length < 40:
|
||||||
|
return
|
||||||
|
|
||||||
|
# On récupère le mouvement voulu, pour cela on compare la valeur absolue du déplacement
|
||||||
|
# de la souris sur l'axe des x et de la souris sur l'axe des y pour savoir lequel
|
||||||
|
# est le plus grand, puis on en deduit le mouvement voulu.
|
||||||
|
if abs(mouse_delta.x) >= abs(mouse_delta.y):
|
||||||
|
movement = Vec2(mouse_delta.x / abs(mouse_delta.x), 0)
|
||||||
|
else:
|
||||||
|
movement = Vec2(0, mouse_delta.y / abs(mouse_delta.y))
|
||||||
|
|
||||||
|
# On vérifie que le mouvement ne fait pas sortir le dossier de la grille.
|
||||||
|
new_position = selected.entity[DirectoryPosition] + movement
|
||||||
|
if (
|
||||||
|
new_position.x < 0
|
||||||
|
or new_position.x >= COLUMNS
|
||||||
|
or new_position.y < 0
|
||||||
|
or new_position.y >= LINES
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
# On trouve le dossier vers lequel on souhaite se diriger, si le dossier
|
||||||
|
# est en train de être fouillé ou que le dossier est bloqué, on ne fait rien
|
||||||
|
for entity in world.query(
|
||||||
|
Directory, without=(SearchingDirectory, BlockedDirectory)
|
||||||
|
):
|
||||||
|
if entity[DirectoryPosition] == new_position:
|
||||||
|
other_directory = entity
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
# On inverse la position des deux dossiers
|
||||||
|
selected_directory = selected.entity
|
||||||
|
other_directory[DirectoryPosition], selected_directory[DirectoryPosition] = (
|
||||||
|
selected_directory[DirectoryPosition],
|
||||||
|
other_directory[DirectoryPosition],
|
||||||
|
)
|
||||||
|
|
||||||
|
# On joue un son de déplacement
|
||||||
|
world.new_entity().set(Sound(world[Assets].get_sound("move_directory")))
|
||||||
|
|
||||||
|
# On supprime le dossier selectionné
|
||||||
|
del world[SelectedDirectory]
|
||||||
|
|
||||||
|
|
||||||
|
def __update_graphics(world: World):
|
||||||
|
"""
|
||||||
|
Met à jour tous ce qui est relatif au graphismes de la scène.
|
||||||
|
"""
|
||||||
|
# On met à jour la position des dossiers
|
||||||
|
for entity in world.query(Directory, DirectoryPosition):
|
||||||
|
entity.set(smooth.Target(entity[DirectoryPosition].screen_position()))
|
||||||
|
|
||||||
|
# On met à jour la position des noms des dossiers
|
||||||
|
for entity in world.query(DirectoryName):
|
||||||
|
entity[smooth.Target] = entity[DirectoryName].entity[smooth.Target] + Vec2(
|
||||||
|
0, 75
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
SCENE = plugin_assets.loading_scene(
|
SCENE = plugin_assets.loading_scene(
|
||||||
Scene(
|
Scene(
|
||||||
|
[__initialize],
|
||||||
|
[__control_directories, __update_graphics],
|
||||||
[],
|
[],
|
||||||
[],
|
)
|
||||||
[],
|
+ smooth.PLUGIN,
|
||||||
),
|
|
||||||
"story/directory_search",
|
"story/directory_search",
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue