Skip to content

Commit

Permalink
Début d'implémentation d'un mini-jeu
Browse files Browse the repository at this point in the history
+ Petites finitions graphiques pour la L101
+ Ajout d'un mini-jeu de sélection avec une multitude de questions (3) liées au programme de Sup et de Spé

Important : des bugs imprévus peuvent (et vont) apparaître.
  • Loading branch information
fmkr-project committed Mar 30, 2022
1 parent f4b5379 commit 6baaa47
Show file tree
Hide file tree
Showing 18 changed files with 320 additions and 31 deletions.
File renamed without changes.
33 changes: 33 additions & 0 deletions res/locale/fr/select.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
1 :
qu: "Citer les hypothèses du CSSA pour la convergence de la série Σun."
keys: "mathsern"
a : "(|un|) est bornée"
b : "(un) décroît"
c : "(|un|) décroît"
d : "(|un|) tend vers 0"
e : "(|un|) est équivalente à 1/n"
correct: !!set
? 'c'
? 'd'

2 :
qu: "Sélectionner la bonne valeur de h/2π."
keys: "physquan"
a : "1,05.10E-34 J.s"
b : "1,05.10E-34 J/s"
c : "1,05.10E-35 J.s"
d : "1,05.10E-35 J/s"
e : "1,05.10E-35 J.s²"
correct: !!set
? 'a'

3 :
qu: "Complexité de l'algorithme de DIJKSTRA."
keys: "infogrph"
a : "Θ(n²)"
b : "Θ(n³)"
c : "Θ(n log(n))"
d : "Θ(exp(n))"
e : "Θ(n⁴)"
correct: !!set
? 'b'
11 changes: 6 additions & 5 deletions res/maps/l101.tmx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.5" tiledversion="2021.03.23" orientation="orthogonal" renderorder="right-down" width="100" height="100" tilewidth="32" tileheight="32" infinite="0" nextlayerid="4" nextobjectid="8">
<map version="1.5" tiledversion="2021.03.23" orientation="orthogonal" renderorder="right-down" width="100" height="100" tilewidth="32" tileheight="32" infinite="0" nextlayerid="4" nextobjectid="9">
<tileset firstgid="1" source="../textures/tiles.tsx"/>
<layer id="1" name="floor_layer" width="100" height="100">
<data encoding="csv">
Expand Down Expand Up @@ -59,8 +59,8 @@
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2147483654,63,63,63,63,63,63,63,63,63,63,63,63,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2147483654,63,63,63,63,63,63,63,63,63,63,63,63,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2147483654,63,63,63,63,63,63,63,63,63,63,63,63,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,63,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2147483654,63,63,63,63,63,63,63,63,63,63,63,63,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Expand Down Expand Up @@ -213,11 +213,12 @@
<object id="1" name="spawn_l101_main" x="1621.75" y="1311.75">
<point/>
</object>
<object id="2" type="mur" x="1216" y="1216" width="64" height="576"/>
<object id="3" type="mur" x="1664" y="1216" width="64" height="576"/>
<object id="2" type="mur" x="1216" y="1248" width="64" height="576"/>
<object id="3" type="mur" x="1664" y="1248" width="64" height="576"/>
<object id="4" name="to_niv1" x="1664" y="1312" width="32" height="32"/>
<object id="5" type="mur" x="1216" y="1152" width="512" height="128"/>
<object id="6" type="mur" x="1616" y="1269.5" width="62.125" height="26.625"/>
<object id="7" name="in lionel we trust" x="1386" y="1190.67" width="171.333" height="21.3333"/>
<object id="8" type="mur" x="1120" y="1824" width="672" height="96"/>
</objectgroup>
</map>
Binary file added res/textures/minigame/select/arrow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/textures/minigame/select/choiceoff.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/textures/minigame/select/choiceon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/textures/minigame/select/greenbg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/textures/minigame/select/orangebg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/textures/minigame/select/redbg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/textures/minigame/select/violetbg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified res/textures/tiles.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import menu
import debug
import scriptmanager as sm
import minigame as mgm

class Game:
DATABASE_LOCATION = "res/game_data.db"
Expand Down Expand Up @@ -81,6 +82,7 @@ def __init__(self):
self.script_manager = sm.ScriptManager(self)
self.map_manager = maps.MapManager(self.screen, self)
self.menu_manager = menu.MenuManager(self.screen, self)
self.mgm_manager = mgm.MGManager(self)

self.dialogue = None # Contient le dialogue s'il existe

Expand Down Expand Up @@ -118,6 +120,7 @@ def tick(self):
self.menu_manager.draw()
self.player.update()
self.script_manager.update() # Actualisation du mouvement d'un script : toutes commandes bloquées
self.mgm_manager.update()
if self.dialogue != None:
self.dialogue.update() # Met à jour le dialogue
if self.debug:
Expand Down
18 changes: 14 additions & 4 deletions src/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,24 @@ def handle_key_down_event(game, event):
game.menu_manager.open_menu()
elif event.key == controls["MENU_CANCEL"]:
game.menu_manager.close_menu()
elif event.key == controls["MENU_MOVE_UP"]:
elif event.key == controls["MENU_MOVE_UP"] and game.menu_is_open:
game.menu_manager.menu_move("up")
elif event.key == controls["MENU_MOVE_DOWN"]:
elif event.key == controls["MENU_MOVE_DOWN"] and game.menu_is_open:
game.menu_manager.menu_move("down")
elif event.key == controls["MENU_MOVE_LEFT"]:
elif event.key == controls["MENU_MOVE_LEFT"] and game.menu_is_open:
game.menu_manager.menu_move("left")
elif event.key == controls["MENU_MOVE_RIGHT"]:
elif event.key == controls["MENU_MOVE_RIGHT"] and game.menu_is_open:
game.menu_manager.menu_move("right")
elif event.key == controls["MINIGAME_UP"] and game.minigame_opened:
game.mgm_manager.key("up")
elif event.key == controls["MINIGAME_DOWN"] and game.minigame_opened:
game.mgm_manager.key("down")
elif event.key == controls["MINIGAME_LEFT"] and game.minigame_opened:
game.mgm_manager.key("left")
elif event.key == controls["MINIGAME_RIGHT"] and game.minigame_opened:
game.mgm_manager.key("right")
elif event.key == controls["MINIGAME_ENTER"] and game.minigame_opened:
game.mgm_manager.key("enter")
elif event.key == controls["GAME_FULLSCREEN"]:
game.change_window_size(fullscreen = (not game.is_fullscreen))
elif event.key == controls["GAME_TERMINATE"]:
Expand Down
13 changes: 12 additions & 1 deletion src/locale.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,19 @@

import yaml

LOCALE_DIR = "res/locale/"
CURRENT_LANGUAGE = "fr"
LOCALE_DIR = f"res/locale/{CURRENT_LANGUAGE}/"

def get_dir():
"""Retourne l'emplacement des fichiers de traduction"""
return(LOCALE_DIR)


def get_string(file, str_id):
with open(f"{LOCALE_DIR}{file}.yaml", 'r', encoding = "utf-8") as file:
strings = yaml.load(file, Loader = yaml.FullLoader)
return(strings[str_id])


def getstring_dialogue(str_id):
with open(f"{LOCALE_DIR}{CURRENT_LANGUAGE}.yaml", 'r', encoding = "utf-8") as file:
Expand Down
224 changes: 224 additions & 0 deletions src/minigame.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import pygame as pg

import locale
import menu
import dialogue

class MGManager():
"""Classe de gestion des mini-jeux"""

def __init__(self, game):
self.game = game
self.running_mg = None

def update(self):
if self.running_mg is not None:
self.game.player.can_move = False
self.game.minigame_opened = True
self.running_mg.update_graphics()
else:
if not self.game.menu_is_open:
self.game.player.can_move = True
self.game.minigame_opened = False

def launch(self, mgm, *args):
"""Lancement d'un mini-jeu passé en argument"""
if mgm == "select":
texts = locale.get_string("select", args[0])
self.running_mg = SelectGame(self.game, texts["qu"], [texts[p] for p in ['a', 'b', 'c', 'd', 'e']], texts["correct"])

def key(self, key):
"""Gestion de l'appui d'une touche"""
try:
if key == "up":
self.running_mg.up()
if key == "down":
self.running_mg.down()
if key == "left":
self.running_mg.left()
if key == "right":
self.running_mg.right()
if key == "enter":
self.running_mg.enter()
except AttributeError:
pass # Touche non supportée dans le mini-jeu courant ou pas de mini-jeu

class Minigame():
"""Classe des mini-jeux"""

def __init__(self, game):
self.game = game

def launch(self):
"""Exécute un mini-jeu"""
self.game.mgm_manager.running_mg = self

def terminate(self):
"""Arrête l'exécution d'un mini-jeu"""
self.game.mgm_manager.running_mg = None


class SelectGame(Minigame):
"""Classe du mini-jeu de sélection"""
BANK = f"{locale.get_dir()}/select.yaml"
TEXTURES_FOLDER = "res/textures/minigame/select/"
OFFSET_FROM_BORDER = 30
OFFSET_TO_BOTTOM = 30
SPACE_BETWEEN_LINES = 42
ALPHABET = "abcdefghijklmnopqrstuvwxyz"
FONT = "consolas"
QUESTION_FSIZE = 22 # à remplacer par du LaTeΧ ?
PROPOSITION_FSIZE = 16


def __init__(self, game, question, props, correct):
super().__init__(game)

self.bgm = "it's concours time"
self.question = question
self.props = props
self.correct = correct

# Mémoire interne
self.choices = [0 for _ in self.props]
self.cursor_position = 0 # Position du curseur de sélection

# Graphiques : textures de la boîte d'affichage de la question
self.greenbox = pg.image.load(f"{self.TEXTURES_FOLDER}greenbg.png").convert()
self.greenbox.set_colorkey([255, 255, 255])
self.orangebox = pg.image.load(f"{self.TEXTURES_FOLDER}orangebg.png").convert()
self.orangebox.set_colorkey([255, 255, 255])
self.redbox = pg.image.load(f"{self.TEXTURES_FOLDER}redbg.png").convert()
self.redbox.set_colorkey([255, 255, 255])
self.violetbox = pg.image.load(f"{self.TEXTURES_FOLDER}violetbg.png").convert()
self.violetbox.set_colorkey([255, 255, 255])
# Police associée
self.qu_font = pg.font.SysFont(self.FONT, self.QUESTION_FSIZE)
self.qu_font_width = max([metric[1] for metric in self.qu_font.metrics("azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN")]) # Chasse maximale pour la police choisie
self.qu_row_length = self.greenbox.get_size()[0] / self.qu_font_width - 7 # cf dialogue
self.qu_row_height = self.qu_font.get_linesize()
# Texte de la question
self.qu_texts = []
for line in self.format(self.question):
self.qu_texts.append(self.qu_font.render(line, True, [0, 0, 0]))

# Graphiques : textures des boîtes de sélection
self.choiceoff = pg.image.load(f"{self.TEXTURES_FOLDER}choiceoff.png").convert()
self.choiceoff.set_colorkey([255, 255, 255])
self.choiceon = pg.image.load(f"{self.TEXTURES_FOLDER}choiceon.png").convert()
self.choiceon.set_colorkey([255, 255, 255])
self.validate = pg.image.load(f"{self.TEXTURES_FOLDER}choiceoff.png").convert()
self.validate.set_colorkey([255, 255, 255])
# Police associée
self.prop_font = pg.font.SysFont(self.FONT, self.PROPOSITION_FSIZE)
self.prop_font_width = max([metric[1] for metric in self.prop_font.metrics("azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN")]) # Chasse maximale pour la police choisie
self.row_length = self.greenbox.get_size()[0] / self.prop_font_width - 7 # cf dialogue
self.row_height = self.prop_font.get_linesize()
# Textes des propositions
self.props_tex = []
for prop in self.props:
self.props_tex.append(self.prop_font.render(prop, True, [0, 0, 0]))
self.props_tex.append(self.prop_font.render("Valider", True, [0, 0, 0]))

# Graphiques : flèche
self.arrow_tex = pg.image.load(f"{self.TEXTURES_FOLDER}arrow.png").convert()
self.arrow_tex.set_colorkey([255, 255, 255])

def down(self):
self.cursor_position += 1
if self.cursor_position == len(self.props) + 1: # On prend en compte le bouton valider
self.cursor_position = 0

def up(self):
self.cursor_position -= 1
if self.cursor_position == -1:
self.cursor_position = len(self.props)

def enter(self):
if self.cursor_position == 5: # Dans tous les cas (moins de 5 propositions...) le bouton valider est en 6ème position
answer = set([self.ALPHABET[i] for i in range(len(self.choices)) if self.choices[i] == 1])
if answer == self.correct:
self.game.script_manager.change_event("passedSelectMG", 1)
else:
self.game.script_manager.change_event("passedSelectMG", 0)
self.terminate()
else:
self.choices[self.cursor_position] = 1 - self.choices[self.cursor_position]

def format(self, text):
"""Découpage d'un texte en plusieurs lignes de taille adéquate"""
formatted_text = []
splitted_text = text.split()
text_line = ""
line_length = 0
while splitted_text != []:
word_length = len(splitted_text[0])
if line_length + word_length > self.qu_row_length:
formatted_text.append(text_line)
text_line = ""
line_length = 0
text_line += splitted_text[0] + " "
line_length += word_length + 1
del(splitted_text[0])
formatted_text.append(text_line)
return(formatted_text)

def update_graphics(self):
"""Mise à jour de l'affichage des textures des boutons et de la boîte de dialogue"""
# Affichage de la boîte de question
rect_box = self.greenbox.get_rect(center=(self.game.screen.get_size()[0]/2, self.OFFSET_FROM_BORDER + self.greenbox.get_size()[1]/2))
self.game.screen.blit(self.greenbox, rect_box)
for line in range(len(self.qu_texts)):
text_box = self.qu_texts[line].get_rect(center = (self.game.screen.get_size()[0]/2, self.OFFSET_FROM_BORDER + self.greenbox.get_size()[1]/2 + (line-len(self.qu_texts)/2) * self.qu_row_height))
self.game.screen.blit(self.qu_texts[line], text_box)

# Affichage des boîtes de choix
rect_A = self.choiceoff.get_rect(center = (self.game.screen.get_size()[0]/2, self.game.screen.get_size()[1] - self.OFFSET_FROM_BORDER - 5*self.SPACE_BETWEEN_LINES - self.choiceoff.get_size()[1]/2))
if self.choices[0]:
self.game.screen.blit(self.choiceon, rect_A)
else:
self.game.screen.blit(self.choiceoff, rect_A)
text_box = self.props_tex[0].get_rect(center = rect_A.center)
self.game.screen.blit(self.props_tex[0], text_box)

rect_B = self.choiceoff.get_rect(center = (self.game.screen.get_size()[0]/2, self.game.screen.get_size()[1] - self.OFFSET_FROM_BORDER - 4*self.SPACE_BETWEEN_LINES - self.choiceoff.get_size()[1]/2))
if self.choices[1]:
self.game.screen.blit(self.choiceon, rect_B)
else:
self.game.screen.blit(self.choiceoff, rect_B)
text_box = self.props_tex[1].get_rect(center = rect_B.center)
self.game.screen.blit(self.props_tex[1], text_box)

rect_C = self.choiceoff.get_rect(center = (self.game.screen.get_size()[0]/2, self.game.screen.get_size()[1] - self.OFFSET_FROM_BORDER - 3*self.SPACE_BETWEEN_LINES - self.choiceoff.get_size()[1]/2))
if self.choices[2]:
self.game.screen.blit(self.choiceon, rect_C)
else:
self.game.screen.blit(self.choiceoff, rect_C)
text_box = self.props_tex[2].get_rect(center = rect_C.center)
self.game.screen.blit(self.props_tex[2], text_box)

rect_D = self.choiceoff.get_rect(center = (self.game.screen.get_size()[0]/2, self.game.screen.get_size()[1] - self.OFFSET_FROM_BORDER - 2*self.SPACE_BETWEEN_LINES - self.choiceoff.get_size()[1]/2))
if self.choices[3]:
self.game.screen.blit(self.choiceon, rect_D)
else:
self.game.screen.blit(self.choiceoff, rect_D)
text_box = self.props_tex[3].get_rect(center = rect_D.center)
self.game.screen.blit(self.props_tex[3], text_box)

rect_E = self.choiceoff.get_rect(center = (self.game.screen.get_size()[0]/2, self.game.screen.get_size()[1] - self.OFFSET_FROM_BORDER - self.SPACE_BETWEEN_LINES - self.choiceoff.get_size()[1]/2))
if self.choices[4]:
self.game.screen.blit(self.choiceon, rect_E)
else:
self.game.screen.blit(self.choiceoff, rect_E)
text_box = self.props_tex[4].get_rect(center = rect_E.center)
self.game.screen.blit(self.props_tex[4], text_box)

rect_val = self.choiceoff.get_rect(center = (self.game.screen.get_size()[0]/2, self.game.screen.get_size()[1] - self.OFFSET_FROM_BORDER - self.choiceoff.get_size()[1]/2))
self.game.screen.blit(self.choiceoff, rect_val)
text_box = self.props_tex[5].get_rect(center = rect_val.center)
self.game.screen.blit(self.props_tex[5], text_box)

# Affichage de la flèche
rect_arrow = self.arrow_tex.get_rect(center = (self.game.screen.get_size()[0]/2 - self.choiceoff.get_size()[0]/2 + 20, # Terme correctif
self.game.screen.get_size()[1] - self.OFFSET_TO_BOTTOM - (5 - self.cursor_position)*self.SPACE_BETWEEN_LINES - self.choiceoff.get_size()[1]/2))
self.game.screen.blit(self.arrow_tex, rect_arrow)
Loading

1 comment on commit 6baaa47

@fmkr-project
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note à moi-même : Dijkstra n’est absolument pas du tout en Θ(n^3).

Please sign in to comment.