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"""Module de gestion des joueurs.""" 

12 

13import random as rd 

14 

15import rollnjump.conf as cf 

16import rollnjump.sprites as spt 

17import rollnjump.utilities as ut 

18 

19JUMP_KEYS = [ut.K_SPACE, ut.K_RETURN, ut.K_s, ut.K_u] 

20"""Touches de saut des joueurs.""" 

21WINNER = 0 

22"""Joueur gagnant.""" 

23 

24 

25class Player(ut.Sprite): 

26 """ 

27 Gestion du joueur. 

28 

29 Attributes 

30 ---------- 

31 images : Surface list 

32 Liste des images de l'objet 

33 img : int 

34 Indice dans la liste d'images 

35 rect : Rect 

36 Rectangle de collision du joueur 

37 width : int 

38 largeur du joueur 

39 height : int 

40 hauteur du joueur 

41 alive : bool 

42 True si le joueur est vivant 

43 pos : Vector2 

44 Position du joueur 

45 vel : Vector2 

46 Vitesse du joueur 

47 acc : Vector2 

48 Accélération du joueur 

49 FLAG_JUMP : bool 

50 drapeau de saut 

51 FLAG_JUMP_2 : bool 

52 drapeau pour le double saut 

53 state : str 

54 état du joueur, est modifié par la prise d'item 

55 timer : int 

56 durée des effets d'un item 

57 """ 

58 

59 # pylint: disable=too-many-instance-attributes 

60 

61 def __init__(self, color="green"): 

62 """ 

63 Initialisation du joueur. 

64 

65 Parameters 

66 ---------- 

67 color : str, optionnel 

68 La couleur du joueur parmi cf.COLORS 

69 """ 

70 # Initialisation de la classe parent 

71 # ut.add_to_group(self, cf.player_sprite) 

72 super().__init__() 

73 # Liste d'images de l'objet, et indice de cette liste 

74 # [:] pour une copie parfaite, à cause du multijoueur pour l'instant 

75 self.images = spt.img_dict["mono" + color + "_img"][:] 

76 self.img = 0 

77 # Création de l'objet 

78 self.rect = self.images[0].get_rect() 

79 

80 # dimensions 

81 self.width, self.height = cf.SIZE['normal'] 

82 

83 # Est vivant 

84 self.alive = True 

85 

86 # Position 

87 # X : milieu de l'écran 

88 # moins la largeur sur 2 pour être centré (car topleft) 

89 x = cf.SCREEN_WIDTH // 2 - self.width // 2 

90 y = spt.GROUND_HEIGHT - self.height 

91 self.pos = ut.Vec(x, y) 

92 self.rect.topleft = self.pos 

93 

94 # Vitesse 

95 self.vel = ut.Vec(0, 0) 

96 # Accélération 

97 self.acc = ut.Vec(0, cf.G) 

98 

99 # Drapeau de disponibilité du saut 

100 self.FLAG_JUMP = True 

101 # Drapeau de disponibilité du second saut 

102 self.FLAG_JUMP_2 = False 

103 

104 # état dans lequel est le joueur, est modifié par la prise d'item. 

105 # normal, fast, slow, little, big, delay 

106 self.state = "normal" 

107 

108 # Lorsqu'on prend un item, ça a une durée limitée 

109 # D'où ce timer (en frames) 

110 self.timer = 0 

111 

112 def jump(self): 

113 """Lance le saut du personnage.""" 

114 if self.FLAG_JUMP: 

115 self.FLAG_JUMP = False 

116 self.vel.y = -cf.V_JMP 

117 self.FLAG_JUMP_2 = True 

118 elif self.FLAG_JUMP_2: 

119 self.vel.y = -cf.V_JMP 

120 self.FLAG_JUMP_2 = False 

121 

122 def move(self): 

123 """Met à jour pos, vec et acc.""" 

124 # Gestion de l'état dans lequel on est (selon l'item mangé) 

125 if self.state != "normal": 

126 self.timer -= 1 

127 # si le timer est fini on redevient normal 

128 if self.timer == 0: 

129 # l'état delay permet de devenir big avec un délai pour 

130 # éviter de rentrer dans une plateforme 

131 if self.state == 'delay': 

132 self.change_state('big') 

133 else: 

134 self.end_item() 

135 

136 if self.state == "fast": 

137 self.vel.x = cf.V_ITEM['fast'] 

138 # si on arrive aux 2/3 de l'écran ça arrête d'avancer 

139 if self.pos.x > (cf.SCREEN_WIDTH * 2) // 3: 

140 self.end_item() 

141 

142 elif self.state == "slow": 

143 self.vel.x = cf.V_ITEM['slow'] 

144 # si on sort presque de l'écran ça arrête de ralentir 

145 if self.pos.x < self.width: 

146 self.end_item() 

147 

148 ut.update_pos_vel(self, spt.ground) 

149 

150 for item in spt.items: # Gestion de la prise d'item 

151 if ut.contact(self, item): 

152 self.change_state(item.type) 

153 item.kill() 

154 

155 # On change le sprite du joueur 

156 self.img += 0.03 * cf.SPEED 

157 # Faire par fraction permet d'accélérer plus lentement les pédales 

158 if int(self.img) >= len(self.images): 

159 self.img = 0 

160 

161 cf.DISPLAYSURF.blit(self.images[int(self.img)], self.rect) 

162 if self.in_death_position(): 

163 self.alive = False 

164 

165 def in_death_position(self): 

166 """ 

167 Condition de défaite du joueur. 

168 

169 Returns 

170 ------- 

171 bool 

172 True si le joueur sort suffisamment de l'écran. 

173 """ 

174 return(self.pos.y > cf.SCREEN_HEIGHT + 50 

175 or self.pos.x + self.width < 0) 

176 

177 def change_state(self, item_type): 

178 """ 

179 Modifie l'état après la prise d'un objet et supprime ce dernier. 

180 

181 Parameters 

182 ---------- 

183 item : Item 

184 L'objet récupéré 

185 """ 

186 # resize le player 

187 if item_type in ['little', 'big']: 

188 self.resize('normal', item_type) 

189 

190 # Si quand on devient grand on collide une plateforme, on annule 

191 # Et on passe en 'delay' pour l'activer un peu plus tard 

192 if item_type == 'big' and ut.collide_group(self, spt.ground): 

193 self.resize('big', 'normal') 

194 item_type = 'delay' 

195 

196 self.state = item_type 

197 self.timer = cf.ITEM_TIME[item_type] 

198 

199 def end_item(self): 

200 """Retour à l'état normal.""" 

201 # On se remet à la bonne taille, position, etc. 

202 if self.state in ['little', 'big']: 

203 self.resize(self.state, 'normal') 

204 

205 # Si on était petit et qu'on redevient normal, 

206 # il se peut qu'on collide une plateforme. 

207 # Dans ce cas, on reste petit quelques instants 

208 if self.state == 'little' and ut.collide_group(self, spt.ground): 

209 self.resize('normal', 'little') 

210 self.timer += cf.ITEM_TIME['delay'] 

211 else: 

212 # On se remet dans l'état normal et on annule le FLAG_ITEM 

213 self.state = "normal" 

214 self.vel.x = 0 

215 

216 cf.FLAG_ITEM = False 

217 cf.NEW_ITEM_TIME = cf.SECONDS + rd.randint(cf.ITEM_PROBA_MIN, 

218 cf.ITEM_PROBA_MAX) 

219 

220 def resize(self, size1, size2): 

221 """ 

222 Change la taille du joueur. 

223 

224 Parameters 

225 ---------- 

226 size1 : str 

227 La taille actuelle (parmi "little", "normal", "big") 

228 size2 : str 

229 La taille à atteindre 

230 """ 

231 ut.resize_list(self.images, cf.SIZE[size2]) 

232 self.width, self.height = cf.SIZE[size2] 

233 self.pos[0] = self.pos[0] + cf.SIZE[size1][0] // 2\ 

234 - cf.SIZE[size2][0] // 2 

235 self.pos[1] = self.pos[1] + cf.SIZE[size1][1]\ 

236 - cf.SIZE[size2][1] 

237 self.rect = self.images[0].get_rect() 

238 self.rect.topleft = self.pos