Gameplay de la recherche dans les dossiers #44
BIN
assets/krita/classique_arrow.kra
Normal file
BIN
assets/krita/classique_background.kra
Normal file
BIN
assets/krita/classique_button.kra
Normal file
BIN
assets/krita/search_bar.kra
Normal file
BIN
assets/krita/valider.kra
Normal file
BIN
assets/sounds/click/click0.wav
Normal file
BIN
assets/sounds/click/click1.wav
Normal file
BIN
assets/sounds/click/click2.wav
Normal file
BIN
assets/sounds/lose_sound.wav
Normal file
BIN
assets/sounds/menu_click.wav
Normal file
BIN
assets/sounds/win_sound.wav
Normal file
BIN
assets/textures/classique/arrow.png
Normal file
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 6 KiB |
BIN
assets/textures/classique/arrow_hover.png
Normal file
Before Width: | Height: | Size: 7 KiB After Width: | Height: | Size: 7 KiB |
BIN
assets/textures/classique/background.png
Normal file
Before Width: | Height: | Size: 191 KiB After Width: | Height: | Size: 191 KiB |
BIN
assets/textures/classique/play_again.png
Normal file
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
BIN
assets/textures/classique/play_again_hover.png
Normal file
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
BIN
assets/textures/classique/valider.png
Normal file
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
BIN
assets/textures/classique/valider_hover.png
Normal file
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
@ -6,6 +6,7 @@ Un moteur de jeu inspiré de bevy.
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
|
import random
|
||||||
from typing import Callable, Optional, Sequence, SupportsFloat, TypeVar, Union
|
from typing import Callable, Optional, Sequence, SupportsFloat, TypeVar, Union
|
||||||
from time import time
|
from time import time
|
||||||
import pygame
|
import pygame
|
||||||
|
@ -593,6 +594,12 @@ class Sound:
|
||||||
stop_on_remove: bool = False,
|
stop_on_remove: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
|
if os.path.isdir(f"assets/sounds/{name}"):
|
||||||
|
list_files = os.listdir(f"assets/sounds/{name}")
|
||||||
|
random_file = random.choice(list_files)
|
||||||
|
self.name = f"{name}/{random_file}"
|
||||||
|
|
||||||
self.volume = volume
|
self.volume = volume
|
||||||
self.loop = loop
|
self.loop = loop
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
|
@ -763,7 +770,7 @@ def start_game(
|
||||||
del channels[entity]
|
del channels[entity]
|
||||||
|
|
||||||
# Ajout des sons non gérés
|
# Ajout des sons non gérés
|
||||||
for entity in sound_entities:
|
for entity in world.query(Sound):
|
||||||
if entity not in channels:
|
if entity not in channels:
|
||||||
entity_sound = entity[Sound]
|
entity_sound = entity[Sound]
|
||||||
sound = assets.get_sound(entity_sound.name)
|
sound = assets.get_sound(entity_sound.name)
|
||||||
|
|
|
@ -4,13 +4,14 @@ Example de l'utilisation du moteur de jeu.
|
||||||
|
|
||||||
|
|
||||||
from engine import start_game
|
from engine import start_game
|
||||||
from scenes import directory_search, menu
|
from scenes import directory_search, menu, classique
|
||||||
|
|
||||||
|
|
||||||
start_game(
|
start_game(
|
||||||
{
|
{
|
||||||
"menu": menu.SCENE,
|
"menu": menu.SCENE,
|
||||||
"directory_search": directory_search.SCENE,
|
"directory_search": directory_search.SCENE,
|
||||||
|
"classique": classique.SCENE,
|
||||||
},
|
},
|
||||||
"directory_search",
|
"directory_search",
|
||||||
title="Guess The Number",
|
title="Guess The Number",
|
||||||
|
|
37
src/plugins/typing.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
"""
|
||||||
|
Definit un plugin qui crée un texte avec les touches frappées
|
||||||
|
"""
|
||||||
|
|
||||||
|
from engine import Keyboard, Scene, Sound, Text, World
|
||||||
|
|
||||||
|
|
||||||
|
class Typing(str):
|
||||||
|
"""
|
||||||
|
Marque une entité comme un texte qui s'ecrit en fonction du clavier
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def __update(world: World):
|
||||||
|
"""
|
||||||
|
Met a jour les entitées contenant le composant Typing
|
||||||
|
"""
|
||||||
|
keyboard = world[Keyboard]
|
||||||
|
for entity in world.query(Typing, Text):
|
||||||
|
text = entity[Text]
|
||||||
|
for key in keyboard.pressed:
|
||||||
|
if key == "backspace":
|
||||||
|
world.create_entity(Sound("click"))
|
||||||
|
text = text[:-1]
|
||||||
|
if key.startswith("["): # pavé numerique
|
||||||
|
key = key[1]
|
||||||
|
if key in entity[Typing]:
|
||||||
|
world.create_entity(Sound("click"))
|
||||||
|
text += key
|
||||||
|
entity[Text] = Text(text)
|
||||||
|
|
||||||
|
|
||||||
|
PLUGIN = Scene(
|
||||||
|
[],
|
||||||
|
[__update],
|
||||||
|
[],
|
||||||
|
)
|
227
src/scenes/classique.py
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
"""
|
||||||
|
Définis la scène du jeu classique, sans variante.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import random
|
||||||
|
from plugins import typing
|
||||||
|
from engine import (
|
||||||
|
Centered,
|
||||||
|
Clickable,
|
||||||
|
Color,
|
||||||
|
Display,
|
||||||
|
Entity,
|
||||||
|
Game,
|
||||||
|
HoveredTexture,
|
||||||
|
Keyboard,
|
||||||
|
Order,
|
||||||
|
Position,
|
||||||
|
Scene,
|
||||||
|
Sound,
|
||||||
|
Text,
|
||||||
|
TextSize,
|
||||||
|
Texture,
|
||||||
|
World,
|
||||||
|
)
|
||||||
|
|
||||||
|
COLOR_TEXT = Color(66, 39, 148)
|
||||||
|
|
||||||
|
|
||||||
|
class RandomNumber(int):
|
||||||
|
"""
|
||||||
|
La ressource qui est le nombre a deviner.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class TextDialogue:
|
||||||
|
"""
|
||||||
|
Le component qui declare l'entitee Text qui affiche le plus petit ou le plus grand
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class NombreEssai(int):
|
||||||
|
"""
|
||||||
|
Le component qui declare le nombre d'essai
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class NombreEssaiText:
|
||||||
|
"""
|
||||||
|
Le component qui affiche le nombre d'essai
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class IsRunning:
|
||||||
|
"""
|
||||||
|
Le component qui indique si le jeu est en cours
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def __initialize_world(world: World):
|
||||||
|
"""
|
||||||
|
Initialise le monde du menu.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Fond d'ecran
|
||||||
|
world.create_entity(
|
||||||
|
Position(),
|
||||||
|
Order(0),
|
||||||
|
Texture("classique/background.png"),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Bouton valider/rejouer
|
||||||
|
world.create_entity(
|
||||||
|
Position(Display.WIDTH / 2, 875),
|
||||||
|
Order(1),
|
||||||
|
Centered(),
|
||||||
|
Texture("classique/valider.png"),
|
||||||
|
HoveredTexture("classique/valider_hover.png"),
|
||||||
|
Clickable(lambda world, _: _update(world)),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Zone de saisie
|
||||||
|
world.create_entity(
|
||||||
|
Position(Display.WIDTH / 2, 750),
|
||||||
|
Order(2),
|
||||||
|
Centered(),
|
||||||
|
typing.Typing("1234567890"),
|
||||||
|
Text(""),
|
||||||
|
COLOR_TEXT,
|
||||||
|
TextSize(150),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Text qui dit si ton nombre et trop grand ou trop petit
|
||||||
|
world.create_entity(
|
||||||
|
Position(Display.WIDTH / 2, 500),
|
||||||
|
Order(3),
|
||||||
|
Centered(),
|
||||||
|
TextDialogue(),
|
||||||
|
TextSize(150),
|
||||||
|
COLOR_TEXT,
|
||||||
|
Text("Devine le nombre..."),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Text qui affiche le nombre d'essai
|
||||||
|
world.create_entity(
|
||||||
|
Position(Display.WIDTH / 2 - 100, 150),
|
||||||
|
Order(4),
|
||||||
|
TextSize(100),
|
||||||
|
NombreEssaiText(),
|
||||||
|
COLOR_TEXT,
|
||||||
|
Text("il reste : 7 essais"),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Bouton pour revenir au menu
|
||||||
|
world.create_entity(
|
||||||
|
Order(11),
|
||||||
|
Position(150, 150),
|
||||||
|
Texture("classique/arrow.png"),
|
||||||
|
Clickable(on_menu_button),
|
||||||
|
HoveredTexture("classique/arrow_hover.png"),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Les ressources.
|
||||||
|
world[NombreEssai] = NombreEssai(7)
|
||||||
|
world[RandomNumber] = RandomNumber(random.randint(0, 99))
|
||||||
|
world[IsRunning] = IsRunning()
|
||||||
|
|
||||||
|
|
||||||
|
def on_menu_button(world: World, entity: Entity):
|
||||||
|
"""
|
||||||
|
Fonction qui s'execute quand on clique sur un bouton.
|
||||||
|
"""
|
||||||
|
world[Game].change_scene("menu")
|
||||||
|
entity[Sound] = Sound("click")
|
||||||
|
|
||||||
|
|
||||||
|
def _update(world: World):
|
||||||
|
"""
|
||||||
|
Verifie si le nombre donné est le meme que celui que l'on a choisi.
|
||||||
|
Boucle du jeu.
|
||||||
|
"""
|
||||||
|
|
||||||
|
world.create_entity(Sound("menu_click.wav"))
|
||||||
|
|
||||||
|
# si le jeu s'est arrete.
|
||||||
|
if IsRunning not in world:
|
||||||
|
# on relance le jeu.
|
||||||
|
world[Game].change_scene("classique")
|
||||||
|
|
||||||
|
for entity in world.query(typing.Typing, Text):
|
||||||
|
# One efface le nombre.
|
||||||
|
number: str = entity[Text]
|
||||||
|
entity[Text] = Text("")
|
||||||
|
|
||||||
|
# On gere le l'input de l'utilisateur.
|
||||||
|
for entity_text in world.query(TextDialogue):
|
||||||
|
if number == "": # si il a rien evoyé.
|
||||||
|
entity_text[Text] = Text("tu doit entrer un nombre !")
|
||||||
|
return
|
||||||
|
if world[RandomNumber] == int(number): # si il a trouve le nombre.
|
||||||
|
end_game(world, "Gagné")
|
||||||
|
return
|
||||||
|
elif world[NombreEssai] <= 1: # si il n'a plus d'essai.
|
||||||
|
end_game(world, "Perdu")
|
||||||
|
return
|
||||||
|
elif world[RandomNumber] > int(number): # si le nombre est trop petit.
|
||||||
|
entity_text[Text] = Text("Plus grand...")
|
||||||
|
else: # si le nombre est trop grand.
|
||||||
|
entity_text[Text] = Text("Plus petit...")
|
||||||
|
|
||||||
|
# on update l'affichage du nombre d'essai.
|
||||||
|
world[NombreEssai] = NombreEssai(world[NombreEssai] - 1)
|
||||||
|
for entity in world.query(NombreEssaiText):
|
||||||
|
entity[Text] = Text(
|
||||||
|
f"il reste : {world[NombreEssai]} essai{'s' if world[NombreEssai] != 1 else ''}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def end_game(world: World, state: str):
|
||||||
|
"""
|
||||||
|
fonction applé quand le jeu est fini.
|
||||||
|
"""
|
||||||
|
del world[IsRunning] # le jeu est fini.
|
||||||
|
|
||||||
|
# On joue le son
|
||||||
|
if state == "Gagné":
|
||||||
|
world.create_entity(Sound("win_sound.wav"))
|
||||||
|
else:
|
||||||
|
world.create_entity(Sound("lose_sound.wav"))
|
||||||
|
|
||||||
|
# On affiche le message de fin.
|
||||||
|
for entity_text in world.query(TextDialogue):
|
||||||
|
entity_text[Text] = Text(f"{state} !")
|
||||||
|
|
||||||
|
# On empeche de pourvoir continuer le jeu.
|
||||||
|
for entity in world.query(typing.Typing, Text):
|
||||||
|
del entity[typing.Typing]
|
||||||
|
|
||||||
|
if state == "Gagné":
|
||||||
|
for entity in world.query(NombreEssaiText):
|
||||||
|
entity[Text] = Text("")
|
||||||
|
else:
|
||||||
|
for entity in world.query(NombreEssaiText):
|
||||||
|
entity[Text] = Text(" plus d'essais")
|
||||||
|
|
||||||
|
# on change la texture du button submit.
|
||||||
|
for entity in world.query(Clickable, Centered):
|
||||||
|
entity[Texture] = Texture("classique/play_again.png")
|
||||||
|
entity[HoveredTexture] = HoveredTexture("classique/play_again_hover.png")
|
||||||
|
|
||||||
|
|
||||||
|
def _check_return(world: World):
|
||||||
|
"""
|
||||||
|
Verifie si la touche entrée est appuyée.
|
||||||
|
"""
|
||||||
|
keyboard = world[Keyboard]
|
||||||
|
if keyboard.is_key_pressed("return") or keyboard.is_key_pressed("enter"):
|
||||||
|
_update(world)
|
||||||
|
|
||||||
|
|
||||||
|
SCENE = (
|
||||||
|
Scene(
|
||||||
|
[__initialize_world],
|
||||||
|
[_check_return],
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
+ typing.PLUGIN
|
||||||
|
)
|
|
@ -36,7 +36,7 @@ def on_click_butons(world: World, entity: Entity, name: str):
|
||||||
"""
|
"""
|
||||||
Fonction qui s'execute quand on clique sur un bouton.
|
Fonction qui s'execute quand on clique sur un bouton.
|
||||||
"""
|
"""
|
||||||
entity[Sound] = Sound("click.wav")
|
entity[Sound] = Sound("click")
|
||||||
world[Game].change_scene(name)
|
world[Game].change_scene(name)
|
||||||
|
|
||||||
|
|
||||||
|
|