Coverage for rollnjump/menu.py : 100%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Roll 'n' Jump
2# Written in 2020, 2021 by Samuel Arsac, Hugo Buscemi,
3# Matteo Chencerel, Rida Lali
4# To the extent possible under law, the author(s) have dedicated all
5# copyright and related and neighboring rights to this software to the
6# public domain worldwide. This software is distributed without any warranty.
7# You should have received a copy of the CC0 Public Domain Dedication along
8# with this software. If not, see
9# <http://creativecommons.org/publicdomain/zero/1.0/>.
11"""Gestion des menus."""
13import os
14import rollnjump.conf as cf
15import rollnjump.utilities as ut
17FONT_PIXEL = os.path.join(cf.ASSETS, "font", "punk_rockf.ttf")
18"""Chemin vers la police"""
20CHARS_LOW = "azertyuiopqsdfghjklmwxcvbn1234567890"
21"""Caractères acceptés, en minuscules"""
22CHARS_CAP = "AZERTYUIOPQSDFGHJKLMWXCVBN1234567890"
23"""Caractères acceptés, en majuscules"""
26def scaled_mouse_pos(mouse): # pragma: no cover
27 """
28 Renvoie la position de la souris mise à l'échelle de l'image.
30 Parameters
31 ----------
32 mouse : int * int
33 La position réelle de la souris
35 Returns
36 -------
37 int * int
38 La position mise à l'échelle
39 """
40 # Récupération de la dimension de la fenêtre
41 window_dimensions = ut.get_screen_size()
43 # Calcul du facteur d'échelle
44 scale_factor_x = cf.SCREEN_WIDTH / window_dimensions[0]
45 scale_factor_y = cf.SCREEN_HEIGHT / window_dimensions[1]
47 return mouse[0] * scale_factor_x, mouse[1] * scale_factor_y
50def mouse_on_button(scaled_mouse, button_pos, button_size):
51 """
52 Indique si le pointeur de la souris est sur le bouton.
54 Parameters
55 ----------
56 scaled_mouse : int * int
57 Position du pointeur de la souris mise à l'échelle
58 button_pos : int * int
59 Position du bouton
60 button_size : int * int
61 Largeur et hauteur du bouton
63 Returns
64 -------
65 bool
66 True si le pointeur est sur le bouton
67 """
68 return(button_pos[0] <= scaled_mouse[0]
69 <= button_pos[0] + button_size[0]
70 and button_pos[1] <= scaled_mouse[1]
71 <= button_pos[1] + button_size[1])
74class Button:
75 """
76 Boutons pour les menus.
78 Attributes
79 ----------
80 position : int * int
81 Position du bouton
82 size : int * int
83 Taille du bouton
84 rect : Rect
85 Rectangle du bouton
86 """
88 def __init__(self, position, size):
89 """
90 Initialisation.
92 Parameters
93 ----------
94 position : int * int
95 Position du bouton
96 size : int * int
97 Largeur et hauteur du bouton
98 """
99 self.position = position
100 self.size = size
101 self.rect = ut.create_rect([position[0], position[1],
102 size[0], size[1]])
104 def click(self, mouse):
105 """
106 Indique si le pointeur de la souris est sur le bouton.
108 Parameters
109 ----------
110 mouse : int * int
111 Position de la souris
113 Returns
114 -------
115 bool
116 True si le pointeur est sur le bouton
117 """
118 return mouse_on_button(mouse, self.position, self.size)
121class ButtonText(Button):
122 """
123 Boutons aillant du texte comme étiquette.
125 Attributes
126 ----------
127 text : str
128 Étiquette du bouton
129 text_position :
130 Position de l'étiquette
131 """
133 def __init__(self, position, size, text):
134 """
135 Initialisation.
137 Parameters
138 ----------
139 position : int * int
140 Position du bouton
141 size : int * int
142 Largeur et hauteur du bouton
143 text : string
144 Étiquette du bouton
145 """
146 super().__init__(position, size)
147 self.text = ut.font(None, 48).render(text, True, cf.BLACK)
148 self.text_position = (position[0] + 10, position[1] + 10)
150 def print(self, mouse, pushed=False):
151 """
152 Affiche le bouton.
154 Parameters
155 ----------
156 mouse : int * int
157 Position de la souris
158 pushed : bool, optionnel
159 Bouton enfoncé
160 """
161 if mouse_on_button(mouse, self.position, self.size) or pushed:
162 ut.draw_rect(cf.DISPLAYSURF, cf.HOVER, self.rect)
163 else:
164 ut.draw_rect(cf.DISPLAYSURF, cf.IDLE, self.rect)
165 cf.DISPLAYSURF.blit(self.text, self.text_position)
168class ButtonImage(Button):
169 """
170 Boutons affichant une image.
172 Attributes
173 ----------
174 image : str
175 Nom de l'image à afficher quand le bouton est inactif
176 image_hover : str
177 Nom de l'image à afficher quand le pointeur est sur le bouton
178 lang : str
179 Langue à afficher (sous-repertoire à utiliser)
180 """
182 def __init__(self, position, size, image, image_hover, lang=""):
183 """
184 Initialisation.
186 Parameters
187 ----------
188 position : int * int
189 Position du bouton
190 size : int * int
191 Largeur et hauteur du bouton
192 image : str
193 Nom de l'image à afficher quand le bouton est inactif
194 image_hover : str
195 Nom de l'image à afficher quand le pointeur est sur le bouton
196 lang : str, optionnel
197 Langue à afficher (sous-repertoire à utiliser)
198 """
199 super().__init__(position, size)
200 self.image = image
201 self.image_hover = image_hover
202 self.lang = lang
204 def print(self, mouse, pushed=False):
205 """
206 Affiche le bouton.
208 Parameters
209 ----------
210 mouse : int * int
211 Position du pointeur de la souris
212 pushed : bool, optionnel
213 Bouton enfoncé
214 """
215 if mouse_on_button(mouse, self.position, self.size) or pushed:
216 cf.DISPLAYSURF.blit(ut.load_image(os.path.join(cf.UI,
217 self.lang,
218 self.image_hover)),
219 self.position)
220 else:
221 cf.DISPLAYSURF.blit(ut.load_image(os.path.join(cf.UI,
222 self.lang,
223 self.image)),
224 self.position)
226 def changlang(self, lang):
227 """
228 Changer la langue du bouton.
230 Parameters
231 ----------
232 lang : str
233 Langue à utiliser
234 """
235 self.lang = lang
238class InputZone(Button):
239 """
240 Zones permettant le saisie de texte.
242 Attributes
243 ----------
244 input : str
245 Texte inséré dans la zone
246 selescted : bool
247 Indique si la zone est sélectionnée
248 text_position : int * int
249 Position du texte par rapport à la zone
250 font : Font
251 La fonte
252 """
254 def __init__(self, position, size, font=None):
255 """
256 Initialisation.
258 Parameters
259 ----------
260 position : int * int
261 Position du bouton
262 size : int * int
263 Largeur et hauteur du bouton
264 font : Font, optionnel
265 La fonte
266 """
267 super().__init__(position, size)
268 if font is None:
269 font = ut.font(None, cf.INPUT_FONT_SIZE)
270 self.input = ""
271 self.selected = False
272 self.text_position = (position[0] + 10, position[1] + 10)
273 self.font = font
275 def print(self):
276 """Affiche la zone et le texte entré."""
277 ut.draw_rect(cf.DISPLAYSURF, cf.IDLE, self.rect)
278 cf.DISPLAYSURF.blit(self.font.render(self.input, True, cf.WHITE),
279 self.text_position)
281 def select(self):
282 """Active la sélection de la zone."""
283 self.selected = True
285 def deselect(self):
286 """Désactive la sélection de la zone."""
287 self.selected = False
289 def read(self, key):
290 """
291 Lit les caractères entrés.
293 Parameters
294 ----------
295 key : key
296 La touche détectée
297 """
298 if self.selected:
299 key_name = ut.keyname(key)
300 if key_name in CHARS_LOW:
301 self.input += CHARS_CAP[CHARS_LOW.index(key_name)]
302 elif key == ut.K_SPACE:
303 self.input += " "
304 elif key == ut.K_BACKSPACE and self.input != "":
305 self.input = self.input[:-1]
308Oneplayer_pos = (358, 323)
309Oneplayer_size = (100, 100)
310Oneplayer_idle = 'oneplayer.png'
311Oneplayer_hover = 'oneplayerpushed.png'
312oneplayer_button = ButtonImage(
313 Oneplayer_pos,
314 Oneplayer_size,
315 Oneplayer_idle,
316 Oneplayer_hover
317)
318"""Bouton pour lancer le jeu à un joueur."""
320Multiplayer_pos = (591, 323)
321Multiplayer_size = (100, 100)
322Multiplayer_idle = 'multiplayer.png'
323Multiplayer_hover = 'multiplayerpushed.png'
324multiplayer_button = ButtonImage(
325 Multiplayer_pos,
326 Multiplayer_size,
327 Multiplayer_idle,
328 Multiplayer_hover
329)
330"""Bouton pour lancer le jeu en multijoueur."""
332Settings_pos = (824, 323)
333Settings_size = (100, 100)
334Settings_idle = 'settings.png'
335Settings_hover = 'settingspushed.png'
336settings_button = ButtonImage(
337 Settings_pos,
338 Settings_size,
339 Settings_idle,
340 Settings_hover
341)
342"""Bouton des réglages."""
344Records_pos = (358, 460)
345Records_size = (250, 75)
346Records_idle = 'top5.png'
347Records_hover = 'top5pushed.png'
348records_button = ButtonImage(
349 Records_pos,
350 Records_size,
351 Records_idle,
352 Records_hover
353)
354"""Bouton des meilleurs scores."""
356Credits_pos = (674, 460)
357Credits_size = (250, 75)
358Credits_idle = 'credits.png'
359Credits_hover = 'creditspushed.png'
360credits_button = ButtonImage(
361 Credits_pos,
362 Credits_size,
363 Credits_idle,
364 Credits_hover
365)
366"""Bouton des crédits."""
368Restart_pos = (357, 482)
369Restart_size = (567, 101)
370Restart_idle = 'playagain.png'
371Restart_hover = 'playagainpushed.png'
372restart_button = ButtonImage(
373 Restart_pos,
374 Restart_size,
375 Restart_idle,
376 Restart_hover,
377 "fr"
378)
379"""Bouton pour recommencer le jeu."""
381Start_pos = (357, 552)
382Start_size = (567, 101)
383Start_idle = 'begin.png'
384Start_hover = 'beginpushed.png'
385start_button = ButtonImage(
386 Start_pos,
387 Start_size,
388 Start_idle,
389 Start_hover,
390 "fr"
391)
392"""Bouton pour commencer une partie."""
394Return_pos = (20, 20)
395Return_size = (100, 100)
396Return_idle = 'return.png'
397Return_hover = 'returnpushed.png'
398return_button = ButtonImage(
399 Return_pos,
400 Return_size,
401 Return_idle,
402 Return_hover
403)
404"""Bouton pour revenir au menu."""
406Language_pos = (357, 241)
407Language_size = (567, 101)
408Language_idle = 'language.png'
409Language_hover = 'languagepushed.png'
410language_button = ButtonImage(
411 Language_pos,
412 Language_size,
413 Language_idle,
414 Language_hover,
415 "fr"
416)
417"""Bouton pour changer la langue dans les paramètres."""
419Commands_pos = (357, 379)
420Commands_size = (567, 101)
421Commands_idle = 'controls.png'
422Commands_hover = 'controlspushed.png'
423commands_button = ButtonImage(
424 Commands_pos,
425 Commands_size,
426 Commands_idle,
427 Commands_hover,
428 "fr"
429)
430"""Bouton pour changer les touches."""
432Sound_pos = (1168, 11)
433Sound_size = (100, 100)
434Sound_idle = 'soundon.png'
435Sound_hover = 'soundonpushed.png'
436sound_button = ButtonImage(
437 Sound_pos,
438 Sound_size,
439 Sound_idle,
440 Sound_hover
441)
442"""Bouton pour couper ou remettre la musique."""
444# Boutons pour chaque langue
445Flag_size = (180, 120)
446Flag_pos = [(418, 369), (684, 369)]
447Flag_idle = ['fr.png', 'en.png']
448Flag_hover = ['fr_hover.png', 'en_hover.png']
450flagbutton = []
451"""Liste des boutons pour les langues."""
452flagbutton.append(
453 ButtonImage(
454 Flag_pos[0], Flag_size,
455 Flag_idle[0],
456 Flag_hover[0],
457 "flag"
458 )
459)
460flagbutton.append(
461 ButtonImage(
462 Flag_pos[1], Flag_size,
463 Flag_idle[1],
464 Flag_hover[1],
465 "flag"
466 )
467)
469# Boutons pour choisir le nombre de joueurs
470Multi_size = (100, 100)
471Multi_pos = [(cf.SCREEN_WIDTH // 8 + (i + 1) * cf.SCREEN_WIDTH // 4 - 50, 150)
472 for i in range(cf.NB_PLAYERS_MAX)]
473Multi_idle = [str(i + 2) + ".png" for i in range(cf.NB_PLAYERS_MAX)]
474Multi_hover = [str(i + 2) + "pushed.png" for i in range(cf.NB_PLAYERS_MAX)]
475multi_button = []
476"""Liste des boutons pour choisir le nombre de joueurs"""
477for i in range(cf.NB_PLAYERS_MAX - 1):
478 multi_button.append(
479 ButtonImage(
480 Multi_pos[i],
481 Multi_size,
482 Multi_idle[i],
483 Multi_hover[i]
484 )
485 )
487Multi_nb_pos = (cf.SCREEN_WIDTH // 2, 70)
489# Traductions
490MULTIMENU = {
491 "fr": "Nombre de joueurs :",
492 "en": "Number of players:"
493}
494"""Dictionnaire pour traduire le menu multijoueur."""
496INDICBUTTON = {
497 "fr": "Pour sauter, appuyer sur ",
498 "en": "To jump, press "
499}
500"""Dictionnaire pour traduire l'instruction de saut."""
502NOSCORES = {
503 "fr": "Pas de scores",
504 "en": "No scores"
505}
506"""Dictionnaire pour traduire qu'il n'y a pas de scores."""
508Player_pos = (490, 350)
509Player_size = (300, 50)
510player_name_area = InputZone(
511 Player_pos,
512 Player_size,
513 ut.font(FONT_PIXEL, 3 * cf.RESULT_FONT_SIZE // 4)
514)
515"""Zone de texte pour le pseudo du joueur."""
518def print_image(image, position, scale=1):
519 """
520 Affiche une image à une position donnée.
522 Parameters
523 ----------
524 image : string
525 Le chemin vers l'image dans les fichiers
526 position : int * int
527 Les coordonnées de l'image
528 scale : int
529 Le facteur d'échelle
530 """
531 img = ut.load_image(image)
532 w, h = img.get_rect().size
533 img = ut.resize(img, (w * scale, h * scale))
534 cf.DISPLAYSURF.blit(img, position)
537def print_text(text, position_center, color=cf.WHITE,
538 font=None, bold=False):
539 """
540 Affiche une surface de texte centrée sur une position.
542 Parameters
543 ----------
544 text : string
545 Le texte à afficher
546 position_center : int * int
547 La position du centre du texte
548 color : int * int * int, optionnel
549 La couleur du texte
550 font : Font, optionnel
551 La fonte
552 bold : bool, optionnel
553 Indique si le texte doit être en gras
554 """
555 if font is None:
556 font = ut.font(None, cf.TEXT_FONT_SIZE)
557 if bold:
558 font.set_bold(True)
559 size_text = font.size(text)
560 position = (int(position_center[0] - size_text[0] / 2),
561 int(position_center[1] - size_text[1] / 2))
562 txtgen = font.render(text, True, color)
563 cf.DISPLAYSURF.blit(txtgen, position)