├── images ├── bg.png ├── coin.png ├── Mario │ ├── 1.png │ ├── 2.png │ └── 3.png ├── goomba.png ├── thwomp.png ├── exit_btn.png ├── mushroom.png ├── start_btn.png ├── restart_btn.png └── screenshot.png ├── sounds ├── coin.wav ├── life.wav ├── damage.wav └── music.wav ├── README.md └── main.py /images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/bg.png -------------------------------------------------------------------------------- /images/coin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/coin.png -------------------------------------------------------------------------------- /sounds/coin.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/sounds/coin.wav -------------------------------------------------------------------------------- /sounds/life.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/sounds/life.wav -------------------------------------------------------------------------------- /images/Mario/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/Mario/1.png -------------------------------------------------------------------------------- /images/Mario/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/Mario/2.png -------------------------------------------------------------------------------- /images/Mario/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/Mario/3.png -------------------------------------------------------------------------------- /images/goomba.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/goomba.png -------------------------------------------------------------------------------- /images/thwomp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/thwomp.png -------------------------------------------------------------------------------- /sounds/damage.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/sounds/damage.wav -------------------------------------------------------------------------------- /sounds/music.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/sounds/music.wav -------------------------------------------------------------------------------- /images/exit_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/exit_btn.png -------------------------------------------------------------------------------- /images/mushroom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/mushroom.png -------------------------------------------------------------------------------- /images/start_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/start_btn.png -------------------------------------------------------------------------------- /images/restart_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/restart_btn.png -------------------------------------------------------------------------------- /images/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/screenshot.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mario Jumper 2 | 3 | Desenvolvido para o Desafio Simplicode. 4 | 5 | ![img](https://raw.githubusercontent.com/the-akira/MarioJumper/main/images/screenshot.png) 6 | 7 | ## Instalação 8 | 9 | Para jogar **Mario Jumper** é necessário ter o [Python](https://www.python.org/downloads/) instalado em sua máquina. 10 | 11 | Realize a clonagem do repositório: 12 | 13 | ``` 14 | git clone https://github.com/the-akira/MarioJumper.git 15 | ``` 16 | 17 | Instale a biblioteca [PyGame](https://www.pygame.org/wiki/GettingStarted): 18 | 19 | ``` 20 | python3 -m pip install -U pygame --user 21 | ``` 22 | 23 | Dentro do diretório principal, execute o jogo através do comando: 24 | 25 | ``` 26 | python3 main.py 27 | ``` 28 | 29 | Boa diversão! 30 | 31 | ## Regras do Jogo 32 | 33 | - Você deve desviar dos inimigos, seja rápido. 34 | - As moedas aparecem em posições aleatórias, para vencer é necessário coletar 20 moedas. 35 | - Se a barra verde acabar (ou seja, sua vida zerou), significa que você perdeu. 36 | - O cogumelo verde é capaz de curar a sua vida. 37 | 38 | ## Controles 39 | 40 | - `arrow keys`: para mover o personagem 41 | - `barra de espaço`: para pular 42 | - `p`: para pausar o jogo -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from random import randrange 2 | import pygame 3 | 4 | WIDTH = 350 5 | HEIGHT = 600 6 | FPS = 60 7 | 8 | BLACK = (13, 13, 13) 9 | RED = (255, 0, 0) 10 | GREEN = (0, 255, 0) 11 | 12 | pygame.init() 13 | font = pygame.font.SysFont(None, 30) 14 | screen = pygame.display.set_mode((WIDTH, HEIGHT)) 15 | pygame.display.set_caption('Mario Jumper') 16 | clock = pygame.time.Clock() 17 | background = pygame.transform.scale(pygame.image.load('images/bg.png').convert_alpha(), (WIDTH, HEIGHT)) 18 | game_over = False 19 | victory = None 20 | main_menu = True 21 | 22 | music = pygame.mixer.Sound('sounds/music.wav') 23 | music.set_volume(0.2) 24 | music.play(loops=-1) 25 | 26 | coin_fx = pygame.mixer.Sound('sounds/coin.wav') 27 | coin_fx.set_volume(0.4) 28 | 29 | damage_fx = pygame.mixer.Sound('sounds/damage.wav') 30 | damage_fx.set_volume(0.2) 31 | 32 | life_fx = pygame.mixer.Sound('sounds/life.wav') 33 | life_fx.set_volume(0.25) 34 | 35 | def draw_text(text, font, text_color, x, y): 36 | img = font.render(text, True, text_color) 37 | screen.blit(img, (x, y)) 38 | 39 | class Mario(pygame.sprite.Sprite): 40 | def __init__(self, x, y, scale): 41 | pygame.sprite.Sprite.__init__(self) 42 | self.reset(x, y, scale) 43 | 44 | def update(self): 45 | dx = 0 46 | dy = 0 47 | walk_cooldown = 4 48 | key = pygame.key.get_pressed() 49 | 50 | if not self.is_jump: 51 | if key[pygame.K_SPACE]: 52 | self.is_jump = True 53 | else: 54 | if self.jump_count >= -10: 55 | self.rect.y -= (self.jump_count * abs(self.jump_count)) * 0.48 56 | self.jump_count -= 1 57 | else: 58 | self.jump_count = 10 59 | self.is_jump = False 60 | if self.rect.y < 450: 61 | self.rect.y = 450 62 | 63 | if key[pygame.K_LEFT]: 64 | dx -= 6 65 | self.counter += 1 66 | self.direction = -1 67 | if self.rect.left <= 0: 68 | self.rect.left = 0 69 | if key[pygame.K_RIGHT]: 70 | dx += 6 71 | self.counter += 1 72 | self.direction = 1 73 | if self.rect.right >= 350: 74 | self.rect.right = 350 75 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 76 | self.counter = 0 77 | self.index = 0 78 | if self.direction == 1: 79 | self.image = self.images_right[self.index] 80 | if self.direction == -1: 81 | self.image = self.images_left[self.index] 82 | 83 | if self.counter > walk_cooldown: 84 | self.counter = 0 85 | self.index += 1 86 | if self.index >= len(self.images_right): 87 | self.index = 0 88 | if self.direction == 1: 89 | self.image = self.images_right[self.index] 90 | if self.direction == -1: 91 | self.image = self.images_left[self.index] 92 | 93 | self.rect.x += dx 94 | self.rect.y += dy 95 | 96 | def take_damage(self): 97 | now = pygame.time.get_ticks() 98 | if now - self.last_damage > self.damage_cooldown: 99 | self.last_damage = now 100 | self.health -= 1 101 | damage_fx.play() 102 | self.damage_cooldown = 500 103 | 104 | def is_mario_dead(self): 105 | return self.health <= 0 106 | 107 | def gain_life(self): 108 | self.health += 1 109 | life_fx.play() 110 | if self.health >= 5: 111 | self.health = 5 112 | 113 | def gain_score(self): 114 | self.score += 1 115 | coin_fx.play() 116 | 117 | def reset(self, x, y, scale): 118 | self.images_right = [] 119 | self.images_left = [] 120 | self.index = 0 121 | self.counter = 0 122 | for num in range(1,4): 123 | img_right = pygame.image.load(f'images/Mario/{num}.png').convert_alpha() 124 | img_right = pygame.transform.scale(img_right, (int(img_right.get_width() * scale), int(img_right.get_height() * scale))) 125 | img_left = pygame.transform.flip(img_right, True, False) 126 | self.images_right.append(img_right) 127 | self.images_left.append(img_left) 128 | self.image = self.images_right[self.index] 129 | self.rect = self.image.get_rect() 130 | self.rect.center = (x, y) 131 | self.rect.x = x 132 | self.rect.y = y 133 | self.is_jump = False 134 | self.jump_count = 10 135 | self.health = 5 136 | self.damage_cooldown = 0 137 | self.last_damage = pygame.time.get_ticks() 138 | self.score = 0 139 | self.direction = 0 140 | 141 | class Thwomp(pygame.sprite.Sprite): 142 | def __init__(self, x, y, scale): 143 | pygame.sprite.Sprite.__init__(self) 144 | self.image = pygame.image.load('images/thwomp.png').convert_alpha() 145 | self.image = pygame.transform.scale(self.image, (int(self.image.get_width() * scale), int(self.image.get_height() * scale))) 146 | self.rect = self.image.get_rect() 147 | self.rect.center = (x, y) 148 | self.rect.x = x 149 | self.rect.y = y 150 | self.move_direction = 1 151 | self.move_counter = 0 152 | 153 | def update(self): 154 | self.rect.x += self.move_direction 155 | self.move_counter += 1 156 | if abs(self.move_counter) > 120: 157 | self.move_direction *= -1 158 | self.move_counter *= -1 159 | 160 | class Goomba(pygame.sprite.Sprite): 161 | def __init__(self, x, y, scale): 162 | pygame.sprite.Sprite.__init__(self) 163 | self.image = pygame.image.load('images/goomba.png').convert_alpha() 164 | self.image = pygame.transform.scale(self.image, (int(self.image.get_width() * scale), int(self.image.get_height() * scale))) 165 | self.rect = self.image.get_rect() 166 | self.rect.center = (x, y) 167 | self.rect.x = x 168 | self.rect.y = y 169 | self.y_speed = 2 170 | 171 | def update(self): 172 | self.rect.x += 4 173 | self.rect.y += self.y_speed 174 | if self.rect.bottom > HEIGHT - 100: 175 | self.y_speed = -5 176 | if self.rect.top < 100: 177 | self.y_speed = 5 178 | if self.rect.left > WIDTH: 179 | self.rect.right = 0 180 | 181 | class Coin(pygame.sprite.Sprite): 182 | def __init__(self, x, y, scale): 183 | pygame.sprite.Sprite.__init__(self) 184 | self.image = pygame.image.load('images/coin.png').convert_alpha() 185 | self.image = pygame.transform.scale(self.image, (int(self.image.get_width() * scale), int(self.image.get_height() * scale))) 186 | self.rect = self.image.get_rect() 187 | self.rect.center = (x, y) 188 | self.rect.x = x 189 | self.rect.y = y 190 | 191 | def update(self): 192 | new_x = randrange(20,WIDTH - 100) 193 | new_y = randrange(55,HEIGHT - 200) 194 | self.rect.x = new_x 195 | self.rect.y = new_y 196 | 197 | class Mushroom(pygame.sprite.Sprite): 198 | def __init__(self, x, y, scale): 199 | pygame.sprite.Sprite.__init__(self) 200 | self.image = pygame.image.load('images/mushroom.png').convert_alpha() 201 | self.image = pygame.transform.scale(self.image, (int(self.image.get_width() * scale), int(self.image.get_height() * scale))) 202 | self.rect = self.image.get_rect() 203 | self.rect.center = (x, y) 204 | self.rect.x = x 205 | self.rect.y = y 206 | 207 | def update(self): 208 | new_x = randrange(20,WIDTH - 100) 209 | self.rect.x = new_x 210 | self.rect.y = 380 211 | 212 | class HealthBar: 213 | def __init__(self, x, y, health, max_health): 214 | self.x = x 215 | self.y = y 216 | self.health = health 217 | self.max_health = max_health 218 | 219 | def draw(self, health): 220 | self.health = health 221 | ratio = self.health / self.max_health 222 | pygame.draw.rect(screen, BLACK, (self.x - 2, self.y - 2, 154, 24)) 223 | pygame.draw.rect(screen, RED, (self.x, self.y, 150, 20)) 224 | pygame.draw.rect(screen, GREEN, (self.x, self.y, 150 * ratio, 20)) 225 | 226 | class Button: 227 | def __init__(self, x, y, image): 228 | self.image = image 229 | self.rect = self.image.get_rect() 230 | self.rect.x = x 231 | self.rect.y = y 232 | self.clicked = False 233 | 234 | def draw(self): 235 | action = False 236 | pos = pygame.mouse.get_pos() 237 | 238 | if self.rect.collidepoint(pos): 239 | if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False: 240 | action = True 241 | self.clicked = True 242 | 243 | if pygame.mouse.get_pressed()[0] == 0: 244 | self.clicked = False 245 | 246 | screen.blit(self.image, self.rect) 247 | return action 248 | 249 | mario_group = pygame.sprite.GroupSingle() 250 | mario = Mario(5, 450, 0.4) 251 | mario_group.add(mario) 252 | 253 | thwomp_group = pygame.sprite.GroupSingle() 254 | thwomp = Thwomp(150, 450, 0.22) 255 | thwomp_group.add(thwomp) 256 | 257 | goomba_group = pygame.sprite.GroupSingle() 258 | goomba = Goomba(150, 220, 0.20) 259 | goomba_group.add(goomba) 260 | 261 | coin_group = pygame.sprite.Group() 262 | coin_timer = pygame.USEREVENT + 1 263 | pygame.time.set_timer(coin_timer, 2500) 264 | 265 | mushroom_group = pygame.sprite.Group() 266 | mushroom_timer = pygame.USEREVENT + 2 267 | pygame.time.set_timer(mushroom_timer, 10_000) 268 | 269 | health_bar = HealthBar(10, 10, mario.health, mario.health) 270 | 271 | restart_img = pygame.image.load('images/restart_btn.png').convert_alpha() 272 | restart_button = Button(WIDTH // 2 - 60, HEIGHT // 2 - 50, restart_img) 273 | 274 | start_img = pygame.image.load('images/start_btn.png').convert_alpha() 275 | start_button = Button(WIDTH // 2 - 60, HEIGHT // 2 - 60, start_img) 276 | 277 | exit_img = pygame.image.load('images/exit_btn.png').convert_alpha() 278 | exit_button = Button(WIDTH // 2 - 60, HEIGHT // 2 - 10, exit_img) 279 | 280 | running = True 281 | while running: 282 | clock.tick(FPS) 283 | screen.blit(background,(0,0)) 284 | 285 | if main_menu: 286 | if exit_button.draw(): 287 | running = False 288 | if start_button.draw(): 289 | main_menu = False 290 | 291 | elif not game_over: 292 | if pygame.sprite.spritecollide(mario, thwomp_group, False) or pygame.sprite.spritecollide(mario, goomba_group, False): 293 | mario.take_damage() 294 | 295 | if pygame.sprite.spritecollide(mario, coin_group, True): 296 | mario.gain_score() 297 | 298 | if pygame.sprite.spritecollide(mario, mushroom_group, True): 299 | mario.gain_life() 300 | 301 | if mario.is_mario_dead(): 302 | game_over = True 303 | victory = False 304 | 305 | if mario.score == 20: 306 | game_over = True 307 | victory = True 308 | 309 | mario_group.draw(screen) 310 | thwomp_group.draw(screen) 311 | health_bar.draw(mario.health) 312 | goomba_group.draw(screen) 313 | coin_group.draw(screen) 314 | mushroom_group.draw(screen) 315 | 316 | draw_text(f'Pontos: {mario.score}', font, BLACK, 240, 10) 317 | 318 | mario_group.update() 319 | thwomp_group.update() 320 | goomba_group.update() 321 | 322 | for event in pygame.event.get(): 323 | if event.type == pygame.QUIT: 324 | running = False 325 | if event.type == pygame.KEYDOWN: 326 | if event.key == pygame.K_p and not game_over: 327 | main_menu = True 328 | if event.type == coin_timer and not main_menu: 329 | coin = Coin(randrange(20,WIDTH - 100), randrange(55,HEIGHT - 200), 0.13) 330 | coin_group.add(coin) 331 | coin_group.update() 332 | if event.type == mushroom_timer and not main_menu: 333 | mushroom = Mushroom(randrange(20,WIDTH - 100), 380, 0.13) 334 | mushroom_group.add(mushroom) 335 | mushroom_group.update() 336 | 337 | if game_over: 338 | if victory: 339 | draw_text('Você VENCEU!', font, BLACK, (WIDTH // 2) - 70, HEIGHT // 2) 340 | else: 341 | draw_text('Você PERDEU!', font, BLACK, (WIDTH // 2) - 70, HEIGHT // 2) 342 | if restart_button.draw(): 343 | game_over = False 344 | mario.reset(5, 450, 0.4) 345 | mushroom_group.empty() 346 | coin_group.empty() 347 | 348 | pygame.display.update() 349 | 350 | pygame.quit() --------------------------------------------------------------------------------