Hide keyboard shortcuts

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/>. 

10 

11"""Gestion des menus.""" 

12 

13import os 

14import rollnjump.conf as cf 

15import rollnjump.utilities as ut 

16 

17FONT_PIXEL = os.path.join(cf.ASSETS, "font", "punk_rockf.ttf") 

18"""Chemin vers la police""" 

19 

20CHARS_LOW = "azertyuiopqsdfghjklmwxcvbn1234567890" 

21"""Caractères acceptés, en minuscules""" 

22CHARS_CAP = "AZERTYUIOPQSDFGHJKLMWXCVBN1234567890" 

23"""Caractères acceptés, en majuscules""" 

24 

25 

26def scaled_mouse_pos(mouse): # pragma: no cover 

27 """ 

28 Renvoie la position de la souris mise à l'échelle de l'image. 

29 

30 Parameters 

31 ---------- 

32 mouse : int * int 

33 La position réelle de la souris 

34 

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() 

42 

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] 

46 

47 return mouse[0] * scale_factor_x, mouse[1] * scale_factor_y 

48 

49 

50def mouse_on_button(scaled_mouse, button_pos, button_size): 

51 """ 

52 Indique si le pointeur de la souris est sur le bouton. 

53 

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 

62 

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]) 

72 

73 

74class Button: 

75 """ 

76 Boutons pour les menus. 

77 

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 """ 

87 

88 def __init__(self, position, size): 

89 """ 

90 Initialisation. 

91 

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]]) 

103 

104 def click(self, mouse): 

105 """ 

106 Indique si le pointeur de la souris est sur le bouton. 

107 

108 Parameters 

109 ---------- 

110 mouse : int * int 

111 Position de la souris 

112 

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) 

119 

120 

121class ButtonText(Button): 

122 """ 

123 Boutons aillant du texte comme étiquette. 

124 

125 Attributes 

126 ---------- 

127 text : str 

128 Étiquette du bouton 

129 text_position : 

130 Position de l'étiquette 

131 """ 

132 

133 def __init__(self, position, size, text): 

134 """ 

135 Initialisation. 

136 

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) 

149 

150 def print(self, mouse, pushed=False): 

151 """ 

152 Affiche le bouton. 

153 

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) 

166 

167 

168class ButtonImage(Button): 

169 """ 

170 Boutons affichant une image. 

171 

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 """ 

181 

182 def __init__(self, position, size, image, image_hover, lang=""): 

183 """ 

184 Initialisation. 

185 

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 

203 

204 def print(self, mouse, pushed=False): 

205 """ 

206 Affiche le bouton. 

207 

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) 

225 

226 def changlang(self, lang): 

227 """ 

228 Changer la langue du bouton. 

229 

230 Parameters 

231 ---------- 

232 lang : str 

233 Langue à utiliser 

234 """ 

235 self.lang = lang 

236 

237 

238class InputZone(Button): 

239 """ 

240 Zones permettant le saisie de texte. 

241 

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 """ 

253 

254 def __init__(self, position, size, font=None): 

255 """ 

256 Initialisation. 

257 

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 

274 

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) 

280 

281 def select(self): 

282 """Active la sélection de la zone.""" 

283 self.selected = True 

284 

285 def deselect(self): 

286 """Désactive la sélection de la zone.""" 

287 self.selected = False 

288 

289 def read(self, key): 

290 """ 

291 Lit les caractères entrés. 

292 

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] 

306 

307 

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.""" 

319 

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.""" 

331 

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.""" 

343 

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.""" 

355 

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.""" 

367 

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.""" 

380 

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.""" 

393 

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.""" 

405 

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.""" 

418 

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.""" 

431 

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.""" 

443 

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'] 

449 

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) 

468 

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 ) 

486 

487Multi_nb_pos = (cf.SCREEN_WIDTH // 2, 70) 

488 

489# Traductions 

490MULTIMENU = { 

491 "fr": "Nombre de joueurs :", 

492 "en": "Number of players:" 

493} 

494"""Dictionnaire pour traduire le menu multijoueur.""" 

495 

496INDICBUTTON = { 

497 "fr": "Pour sauter, appuyer sur ", 

498 "en": "To jump, press " 

499} 

500"""Dictionnaire pour traduire l'instruction de saut.""" 

501 

502NOSCORES = { 

503 "fr": "Pas de scores", 

504 "en": "No scores" 

505} 

506"""Dictionnaire pour traduire qu'il n'y a pas de scores.""" 

507 

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.""" 

516 

517 

518def print_image(image, position, scale=1): 

519 """ 

520 Affiche une image à une position donnée. 

521 

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) 

535 

536 

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. 

541 

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)