├── LICENSE.md ├── Part_1-Create_World └── platformer_tut1.py ├── Part_10-Add_Score_Counter_and_Display_Text └── platformer_tut10.py ├── Part_11-Adding_Sound_Effects_and_Music └── platformer_tut11.py ├── Part_12-Moving_Platforms └── platformer_tut12.py ├── Part_13-Moving_Platform_Collision └── platformer_tut13.py ├── Part_2-Create_Player └── platformer_tut2.py ├── Part_3-Walking_Animation └── platformer_tut3.py ├── Part_4-Collision └── platformer_tut4.py ├── Part_5-Adding_Enemies └── platformer_tut5.py ├── Part_6-Adding_Lava_and_Death └── platformer_tut6.py ├── Part_7-Add_Buttons_and_Reset_Game └── platformer_tut7.py ├── Part_8-Adding_a_Start_Menu └── platformer_tut8.py ├── Part_9-Multiple_Levels_and_Loading_Data └── platformer_tut9.py ├── Platformer.zip ├── README.md ├── img ├── blob.png ├── coin.png ├── coin.wav ├── dirt.png ├── exit.png ├── exit_btn.png ├── game_over.wav ├── ghost.png ├── grass.png ├── guy1.png ├── guy2.png ├── guy3.png ├── guy4.png ├── jump.wav ├── lava.png ├── load_btn.png ├── music.wav ├── platform.png ├── platform_x.png ├── platform_y.png ├── restart_btn.png ├── save_btn.png ├── sky.png ├── start_btn.png └── sun.png ├── level0_data ├── level1_data ├── level2_data ├── level3_data ├── level4_data ├── level5_data ├── level6_data ├── level7_data └── level_editor.py /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 russs123 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Part_1-Create_World/platformer_tut1.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | 4 | pygame.init() 5 | 6 | screen_width = 1000 7 | screen_height = 1000 8 | 9 | screen = pygame.display.set_mode((screen_width, screen_height)) 10 | pygame.display.set_caption('Platformer') 11 | 12 | #define game variables 13 | tile_size = 50 14 | 15 | 16 | #load images 17 | sun_img = pygame.image.load('img/sun.png') 18 | bg_img = pygame.image.load('img/sky.png') 19 | 20 | def draw_grid(): 21 | for line in range(0, 20): 22 | pygame.draw.line(screen, (255, 255, 255), (0, line * tile_size), (screen_width, line * tile_size)) 23 | pygame.draw.line(screen, (255, 255, 255), (line * tile_size, 0), (line * tile_size, screen_height)) 24 | 25 | 26 | 27 | class World(): 28 | def __init__(self, data): 29 | self.tile_list = [] 30 | 31 | #load images 32 | dirt_img = pygame.image.load('img/dirt.png') 33 | grass_img = pygame.image.load('img/grass.png') 34 | 35 | row_count = 0 36 | for row in data: 37 | col_count = 0 38 | for tile in row: 39 | if tile == 1: 40 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 41 | img_rect = img.get_rect() 42 | img_rect.x = col_count * tile_size 43 | img_rect.y = row_count * tile_size 44 | tile = (img, img_rect) 45 | self.tile_list.append(tile) 46 | if tile == 2: 47 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 48 | img_rect = img.get_rect() 49 | img_rect.x = col_count * tile_size 50 | img_rect.y = row_count * tile_size 51 | tile = (img, img_rect) 52 | self.tile_list.append(tile) 53 | col_count += 1 54 | row_count += 1 55 | 56 | def draw(self): 57 | for tile in self.tile_list: 58 | screen.blit(tile[0], tile[1]) 59 | 60 | 61 | 62 | world_data = [ 63 | [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 64 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 65 | [1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1], 66 | [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 1], 67 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 7, 0, 5, 0, 0, 0, 1], 68 | [1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1], 69 | [1, 7, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 70 | [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 71 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 1], 72 | [1, 0, 2, 0, 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 73 | [1, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 1], 74 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1], 75 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 76 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 2, 0, 1], 77 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 78 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 1], 79 | [1, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1], 80 | [1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 81 | [1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 82 | [1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 83 | ] 84 | 85 | 86 | 87 | 88 | world = World(world_data) 89 | 90 | run = True 91 | while run: 92 | 93 | screen.blit(bg_img, (0, 0)) 94 | screen.blit(sun_img, (100, 100)) 95 | 96 | world.draw() 97 | 98 | draw_grid() 99 | 100 | for event in pygame.event.get(): 101 | if event.type == pygame.QUIT: 102 | run = False 103 | 104 | pygame.display.update() 105 | 106 | pygame.quit() -------------------------------------------------------------------------------- /Part_10-Add_Score_Counter_and_Display_Text/platformer_tut10.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | import pickle 4 | from os import path 5 | 6 | pygame.init() 7 | 8 | clock = pygame.time.Clock() 9 | fps = 60 10 | 11 | screen_width = 1000 12 | screen_height = 1000 13 | 14 | screen = pygame.display.set_mode((screen_width, screen_height)) 15 | pygame.display.set_caption('Platformer') 16 | 17 | 18 | #define font 19 | font = pygame.font.SysFont('Bauhaus 93', 70) 20 | font_score = pygame.font.SysFont('Bauhaus 93', 30) 21 | 22 | 23 | #define game variables 24 | tile_size = 50 25 | game_over = 0 26 | main_menu = True 27 | level = 0 28 | max_levels = 7 29 | score = 0 30 | 31 | 32 | #define colours 33 | white = (255, 255, 255) 34 | blue = (0, 0, 255) 35 | 36 | 37 | #load images 38 | sun_img = pygame.image.load('img/sun.png') 39 | bg_img = pygame.image.load('img/sky.png') 40 | restart_img = pygame.image.load('img/restart_btn.png') 41 | start_img = pygame.image.load('img/start_btn.png') 42 | exit_img = pygame.image.load('img/exit_btn.png') 43 | 44 | 45 | def draw_text(text, font, text_col, x, y): 46 | img = font.render(text, True, text_col) 47 | screen.blit(img, (x, y)) 48 | 49 | 50 | #function to reset level 51 | def reset_level(level): 52 | player.reset(100, screen_height - 130) 53 | blob_group.empty() 54 | lava_group.empty() 55 | exit_group.empty() 56 | 57 | #load in level data and create world 58 | if path.exists(f'level{level}_data'): 59 | pickle_in = open(f'level{level}_data', 'rb') 60 | world_data = pickle.load(pickle_in) 61 | world = World(world_data) 62 | 63 | return world 64 | 65 | 66 | class Button(): 67 | def __init__(self, x, y, image): 68 | self.image = image 69 | self.rect = self.image.get_rect() 70 | self.rect.x = x 71 | self.rect.y = y 72 | self.clicked = False 73 | 74 | def draw(self): 75 | action = False 76 | 77 | #get mouse position 78 | pos = pygame.mouse.get_pos() 79 | 80 | #check mouseover and clicked conditions 81 | if self.rect.collidepoint(pos): 82 | if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False: 83 | action = True 84 | self.clicked = True 85 | 86 | if pygame.mouse.get_pressed()[0] == 0: 87 | self.clicked = False 88 | 89 | 90 | #draw button 91 | screen.blit(self.image, self.rect) 92 | 93 | return action 94 | 95 | 96 | class Player(): 97 | def __init__(self, x, y): 98 | self.reset(x, y) 99 | 100 | 101 | 102 | def update(self, game_over): 103 | dx = 0 104 | dy = 0 105 | walk_cooldown = 5 106 | 107 | if game_over == 0: 108 | #get keypresses 109 | key = pygame.key.get_pressed() 110 | if key[pygame.K_SPACE] and self.jumped == False and self.in_air == False: 111 | self.vel_y = -15 112 | self.jumped = True 113 | if key[pygame.K_SPACE] == False: 114 | self.jumped = False 115 | if key[pygame.K_LEFT]: 116 | dx -= 5 117 | self.counter += 1 118 | self.direction = -1 119 | if key[pygame.K_RIGHT]: 120 | dx += 5 121 | self.counter += 1 122 | self.direction = 1 123 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 124 | self.counter = 0 125 | self.index = 0 126 | if self.direction == 1: 127 | self.image = self.images_right[self.index] 128 | if self.direction == -1: 129 | self.image = self.images_left[self.index] 130 | 131 | 132 | #handle animation 133 | if self.counter > walk_cooldown: 134 | self.counter = 0 135 | self.index += 1 136 | if self.index >= len(self.images_right): 137 | self.index = 0 138 | if self.direction == 1: 139 | self.image = self.images_right[self.index] 140 | if self.direction == -1: 141 | self.image = self.images_left[self.index] 142 | 143 | 144 | #add gravity 145 | self.vel_y += 1 146 | if self.vel_y > 10: 147 | self.vel_y = 10 148 | dy += self.vel_y 149 | 150 | #check for collision 151 | self.in_air = True 152 | for tile in world.tile_list: 153 | #check for collision in x direction 154 | if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): 155 | dx = 0 156 | #check for collision in y direction 157 | if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): 158 | #check if below the ground i.e. jumping 159 | if self.vel_y < 0: 160 | dy = tile[1].bottom - self.rect.top 161 | self.vel_y = 0 162 | #check if above the ground i.e. falling 163 | elif self.vel_y >= 0: 164 | dy = tile[1].top - self.rect.bottom 165 | self.vel_y = 0 166 | self.in_air = False 167 | 168 | 169 | #check for collision with enemies 170 | if pygame.sprite.spritecollide(self, blob_group, False): 171 | game_over = -1 172 | 173 | #check for collision with lava 174 | if pygame.sprite.spritecollide(self, lava_group, False): 175 | game_over = -1 176 | 177 | #check for collision with exit 178 | if pygame.sprite.spritecollide(self, exit_group, False): 179 | game_over = 1 180 | 181 | 182 | #update player coordinates 183 | self.rect.x += dx 184 | self.rect.y += dy 185 | 186 | 187 | elif game_over == -1: 188 | self.image = self.dead_image 189 | draw_text('GAME OVER!', font, blue, (screen_width // 2) - 200, screen_height // 2) 190 | if self.rect.y > 200: 191 | self.rect.y -= 5 192 | 193 | #draw player onto screen 194 | screen.blit(self.image, self.rect) 195 | pygame.draw.rect(screen, (255, 255, 255), self.rect, 2) 196 | 197 | return game_over 198 | 199 | 200 | def reset(self, x, y): 201 | self.images_right = [] 202 | self.images_left = [] 203 | self.index = 0 204 | self.counter = 0 205 | for num in range(1, 5): 206 | img_right = pygame.image.load(f'img/guy{num}.png') 207 | img_right = pygame.transform.scale(img_right, (40, 80)) 208 | img_left = pygame.transform.flip(img_right, True, False) 209 | self.images_right.append(img_right) 210 | self.images_left.append(img_left) 211 | self.dead_image = pygame.image.load('img/ghost.png') 212 | self.image = self.images_right[self.index] 213 | self.rect = self.image.get_rect() 214 | self.rect.x = x 215 | self.rect.y = y 216 | self.width = self.image.get_width() 217 | self.height = self.image.get_height() 218 | self.vel_y = 0 219 | self.jumped = False 220 | self.direction = 0 221 | self.in_air = True 222 | 223 | 224 | 225 | class World(): 226 | def __init__(self, data): 227 | self.tile_list = [] 228 | 229 | #load images 230 | dirt_img = pygame.image.load('img/dirt.png') 231 | grass_img = pygame.image.load('img/grass.png') 232 | 233 | row_count = 0 234 | for row in data: 235 | col_count = 0 236 | for tile in row: 237 | if tile == 1: 238 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 239 | img_rect = img.get_rect() 240 | img_rect.x = col_count * tile_size 241 | img_rect.y = row_count * tile_size 242 | tile = (img, img_rect) 243 | self.tile_list.append(tile) 244 | if tile == 2: 245 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 246 | img_rect = img.get_rect() 247 | img_rect.x = col_count * tile_size 248 | img_rect.y = row_count * tile_size 249 | tile = (img, img_rect) 250 | self.tile_list.append(tile) 251 | if tile == 3: 252 | blob = Enemy(col_count * tile_size, row_count * tile_size + 15) 253 | blob_group.add(blob) 254 | if tile == 6: 255 | lava = Lava(col_count * tile_size, row_count * tile_size + (tile_size // 2)) 256 | lava_group.add(lava) 257 | if tile == 7: 258 | coin = Coin(col_count * tile_size + (tile_size // 2), row_count * tile_size + (tile_size // 2)) 259 | coin_group.add(coin) 260 | if tile == 8: 261 | exit = Exit(col_count * tile_size, row_count * tile_size - (tile_size // 2)) 262 | exit_group.add(exit) 263 | col_count += 1 264 | row_count += 1 265 | 266 | 267 | def draw(self): 268 | for tile in self.tile_list: 269 | screen.blit(tile[0], tile[1]) 270 | pygame.draw.rect(screen, (255, 255, 255), tile[1], 2) 271 | 272 | 273 | 274 | class Enemy(pygame.sprite.Sprite): 275 | def __init__(self, x, y): 276 | pygame.sprite.Sprite.__init__(self) 277 | self.image = pygame.image.load('img/blob.png') 278 | self.rect = self.image.get_rect() 279 | self.rect.x = x 280 | self.rect.y = y 281 | self.move_direction = 1 282 | self.move_counter = 0 283 | 284 | def update(self): 285 | self.rect.x += self.move_direction 286 | self.move_counter += 1 287 | if abs(self.move_counter) > 50: 288 | self.move_direction *= -1 289 | self.move_counter *= -1 290 | 291 | 292 | class Lava(pygame.sprite.Sprite): 293 | def __init__(self, x, y): 294 | pygame.sprite.Sprite.__init__(self) 295 | img = pygame.image.load('img/lava.png') 296 | self.image = pygame.transform.scale(img, (tile_size, tile_size // 2)) 297 | self.rect = self.image.get_rect() 298 | self.rect.x = x 299 | self.rect.y = y 300 | 301 | 302 | class Coin(pygame.sprite.Sprite): 303 | def __init__(self, x, y): 304 | pygame.sprite.Sprite.__init__(self) 305 | img = pygame.image.load('img/coin.png') 306 | self.image = pygame.transform.scale(img, (tile_size // 2, tile_size // 2)) 307 | self.rect = self.image.get_rect() 308 | self.rect.center = (x, y) 309 | 310 | 311 | class Exit(pygame.sprite.Sprite): 312 | def __init__(self, x, y): 313 | pygame.sprite.Sprite.__init__(self) 314 | img = pygame.image.load('img/exit.png') 315 | self.image = pygame.transform.scale(img, (tile_size, int(tile_size * 1.5))) 316 | self.rect = self.image.get_rect() 317 | self.rect.x = x 318 | self.rect.y = y 319 | 320 | 321 | 322 | player = Player(100, screen_height - 130) 323 | 324 | blob_group = pygame.sprite.Group() 325 | lava_group = pygame.sprite.Group() 326 | coin_group = pygame.sprite.Group() 327 | exit_group = pygame.sprite.Group() 328 | 329 | #create dummy coin for showing the score 330 | score_coin = Coin(tile_size // 2, tile_size // 2) 331 | coin_group.add(score_coin) 332 | 333 | #load in level data and create world 334 | if path.exists(f'level{level}_data'): 335 | pickle_in = open(f'level{level}_data', 'rb') 336 | world_data = pickle.load(pickle_in) 337 | world = World(world_data) 338 | 339 | 340 | #create buttons 341 | restart_button = Button(screen_width // 2 - 50, screen_height // 2 + 100, restart_img) 342 | start_button = Button(screen_width // 2 - 350, screen_height // 2, start_img) 343 | exit_button = Button(screen_width // 2 + 150, screen_height // 2, exit_img) 344 | 345 | 346 | run = True 347 | while run: 348 | 349 | clock.tick(fps) 350 | 351 | screen.blit(bg_img, (0, 0)) 352 | screen.blit(sun_img, (100, 100)) 353 | 354 | if main_menu == True: 355 | if exit_button.draw(): 356 | run = False 357 | if start_button.draw(): 358 | main_menu = False 359 | else: 360 | world.draw() 361 | 362 | if game_over == 0: 363 | blob_group.update() 364 | #update score 365 | #check if a coin has been collected 366 | if pygame.sprite.spritecollide(player, coin_group, True): 367 | score += 1 368 | draw_text('X ' + str(score), font_score, white, tile_size - 10, 10) 369 | 370 | blob_group.draw(screen) 371 | lava_group.draw(screen) 372 | coin_group.draw(screen) 373 | exit_group.draw(screen) 374 | 375 | game_over = player.update(game_over) 376 | 377 | #if player has died 378 | if game_over == -1: 379 | if restart_button.draw(): 380 | world_data = [] 381 | world = reset_level(level) 382 | game_over = 0 383 | score = 0 384 | 385 | #if player has completed the level 386 | if game_over == 1: 387 | #reset game and go to next level 388 | level += 1 389 | if level <= max_levels: 390 | #reset level 391 | world_data = [] 392 | world = reset_level(level) 393 | game_over = 0 394 | else: 395 | draw_text('YOU WIN!', font, blue, (screen_width // 2) - 140, screen_height // 2) 396 | if restart_button.draw(): 397 | level = 1 398 | #reset level 399 | world_data = [] 400 | world = reset_level(level) 401 | game_over = 0 402 | score = 0 403 | 404 | 405 | 406 | for event in pygame.event.get(): 407 | if event.type == pygame.QUIT: 408 | run = False 409 | 410 | pygame.display.update() 411 | 412 | pygame.quit() -------------------------------------------------------------------------------- /Part_11-Adding_Sound_Effects_and_Music/platformer_tut11.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | from pygame import mixer 4 | import pickle 5 | from os import path 6 | 7 | pygame.mixer.pre_init(44100, -16, 2, 512) 8 | mixer.init() 9 | pygame.init() 10 | 11 | clock = pygame.time.Clock() 12 | fps = 60 13 | 14 | screen_width = 1000 15 | screen_height = 1000 16 | 17 | screen = pygame.display.set_mode((screen_width, screen_height)) 18 | pygame.display.set_caption('Platformer') 19 | 20 | 21 | #define font 22 | font = pygame.font.SysFont('Bauhaus 93', 70) 23 | font_score = pygame.font.SysFont('Bauhaus 93', 30) 24 | 25 | 26 | #define game variables 27 | tile_size = 50 28 | game_over = 0 29 | main_menu = True 30 | level = 0 31 | max_levels = 7 32 | score = 0 33 | 34 | 35 | #define colours 36 | white = (255, 255, 255) 37 | blue = (0, 0, 255) 38 | 39 | 40 | #load images 41 | sun_img = pygame.image.load('img/sun.png') 42 | bg_img = pygame.image.load('img/sky.png') 43 | restart_img = pygame.image.load('img/restart_btn.png') 44 | start_img = pygame.image.load('img/start_btn.png') 45 | exit_img = pygame.image.load('img/exit_btn.png') 46 | 47 | #load sounds 48 | pygame.mixer.music.load('img/music.wav') 49 | pygame.mixer.music.play(-1, 0.0, 5000) 50 | coin_fx = pygame.mixer.Sound('img/coin.wav') 51 | coin_fx.set_volume(0.5) 52 | jump_fx = pygame.mixer.Sound('img/jump.wav') 53 | jump_fx.set_volume(0.5) 54 | game_over_fx = pygame.mixer.Sound('img/game_over.wav') 55 | game_over_fx.set_volume(0.5) 56 | 57 | 58 | def draw_text(text, font, text_col, x, y): 59 | img = font.render(text, True, text_col) 60 | screen.blit(img, (x, y)) 61 | 62 | 63 | #function to reset level 64 | def reset_level(level): 65 | player.reset(100, screen_height - 130) 66 | blob_group.empty() 67 | lava_group.empty() 68 | exit_group.empty() 69 | 70 | #load in level data and create world 71 | if path.exists(f'level{level}_data'): 72 | pickle_in = open(f'level{level}_data', 'rb') 73 | world_data = pickle.load(pickle_in) 74 | world = World(world_data) 75 | 76 | return world 77 | 78 | 79 | class Button(): 80 | def __init__(self, x, y, image): 81 | self.image = image 82 | self.rect = self.image.get_rect() 83 | self.rect.x = x 84 | self.rect.y = y 85 | self.clicked = False 86 | 87 | def draw(self): 88 | action = False 89 | 90 | #get mouse position 91 | pos = pygame.mouse.get_pos() 92 | 93 | #check mouseover and clicked conditions 94 | if self.rect.collidepoint(pos): 95 | if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False: 96 | action = True 97 | self.clicked = True 98 | 99 | if pygame.mouse.get_pressed()[0] == 0: 100 | self.clicked = False 101 | 102 | 103 | #draw button 104 | screen.blit(self.image, self.rect) 105 | 106 | return action 107 | 108 | 109 | class Player(): 110 | def __init__(self, x, y): 111 | self.reset(x, y) 112 | 113 | 114 | 115 | def update(self, game_over): 116 | dx = 0 117 | dy = 0 118 | walk_cooldown = 5 119 | 120 | if game_over == 0: 121 | #get keypresses 122 | key = pygame.key.get_pressed() 123 | if key[pygame.K_SPACE] and self.jumped == False and self.in_air == False: 124 | jump_fx.play() 125 | self.vel_y = -15 126 | self.jumped = True 127 | if key[pygame.K_SPACE] == False: 128 | self.jumped = False 129 | if key[pygame.K_LEFT]: 130 | dx -= 5 131 | self.counter += 1 132 | self.direction = -1 133 | if key[pygame.K_RIGHT]: 134 | dx += 5 135 | self.counter += 1 136 | self.direction = 1 137 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 138 | self.counter = 0 139 | self.index = 0 140 | if self.direction == 1: 141 | self.image = self.images_right[self.index] 142 | if self.direction == -1: 143 | self.image = self.images_left[self.index] 144 | 145 | 146 | #handle animation 147 | if self.counter > walk_cooldown: 148 | self.counter = 0 149 | self.index += 1 150 | if self.index >= len(self.images_right): 151 | self.index = 0 152 | if self.direction == 1: 153 | self.image = self.images_right[self.index] 154 | if self.direction == -1: 155 | self.image = self.images_left[self.index] 156 | 157 | 158 | #add gravity 159 | self.vel_y += 1 160 | if self.vel_y > 10: 161 | self.vel_y = 10 162 | dy += self.vel_y 163 | 164 | #check for collision 165 | self.in_air = True 166 | for tile in world.tile_list: 167 | #check for collision in x direction 168 | if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): 169 | dx = 0 170 | #check for collision in y direction 171 | if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): 172 | #check if below the ground i.e. jumping 173 | if self.vel_y < 0: 174 | dy = tile[1].bottom - self.rect.top 175 | self.vel_y = 0 176 | #check if above the ground i.e. falling 177 | elif self.vel_y >= 0: 178 | dy = tile[1].top - self.rect.bottom 179 | self.vel_y = 0 180 | self.in_air = False 181 | 182 | 183 | #check for collision with enemies 184 | if pygame.sprite.spritecollide(self, blob_group, False): 185 | game_over = -1 186 | game_over_fx.play() 187 | 188 | #check for collision with lava 189 | if pygame.sprite.spritecollide(self, lava_group, False): 190 | game_over = -1 191 | game_over_fx.play() 192 | 193 | #check for collision with exit 194 | if pygame.sprite.spritecollide(self, exit_group, False): 195 | game_over = 1 196 | 197 | 198 | #update player coordinates 199 | self.rect.x += dx 200 | self.rect.y += dy 201 | 202 | 203 | elif game_over == -1: 204 | self.image = self.dead_image 205 | draw_text('GAME OVER!', font, blue, (screen_width // 2) - 200, screen_height // 2) 206 | if self.rect.y > 200: 207 | self.rect.y -= 5 208 | 209 | #draw player onto screen 210 | screen.blit(self.image, self.rect) 211 | pygame.draw.rect(screen, (255, 255, 255), self.rect, 2) 212 | 213 | return game_over 214 | 215 | 216 | def reset(self, x, y): 217 | self.images_right = [] 218 | self.images_left = [] 219 | self.index = 0 220 | self.counter = 0 221 | for num in range(1, 5): 222 | img_right = pygame.image.load(f'img/guy{num}.png') 223 | img_right = pygame.transform.scale(img_right, (40, 80)) 224 | img_left = pygame.transform.flip(img_right, True, False) 225 | self.images_right.append(img_right) 226 | self.images_left.append(img_left) 227 | self.dead_image = pygame.image.load('img/ghost.png') 228 | self.image = self.images_right[self.index] 229 | self.rect = self.image.get_rect() 230 | self.rect.x = x 231 | self.rect.y = y 232 | self.width = self.image.get_width() 233 | self.height = self.image.get_height() 234 | self.vel_y = 0 235 | self.jumped = False 236 | self.direction = 0 237 | self.in_air = True 238 | 239 | 240 | 241 | class World(): 242 | def __init__(self, data): 243 | self.tile_list = [] 244 | 245 | #load images 246 | dirt_img = pygame.image.load('img/dirt.png') 247 | grass_img = pygame.image.load('img/grass.png') 248 | 249 | row_count = 0 250 | for row in data: 251 | col_count = 0 252 | for tile in row: 253 | if tile == 1: 254 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 255 | img_rect = img.get_rect() 256 | img_rect.x = col_count * tile_size 257 | img_rect.y = row_count * tile_size 258 | tile = (img, img_rect) 259 | self.tile_list.append(tile) 260 | if tile == 2: 261 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 262 | img_rect = img.get_rect() 263 | img_rect.x = col_count * tile_size 264 | img_rect.y = row_count * tile_size 265 | tile = (img, img_rect) 266 | self.tile_list.append(tile) 267 | if tile == 3: 268 | blob = Enemy(col_count * tile_size, row_count * tile_size + 15) 269 | blob_group.add(blob) 270 | if tile == 6: 271 | lava = Lava(col_count * tile_size, row_count * tile_size + (tile_size // 2)) 272 | lava_group.add(lava) 273 | if tile == 7: 274 | coin = Coin(col_count * tile_size + (tile_size // 2), row_count * tile_size + (tile_size // 2)) 275 | coin_group.add(coin) 276 | if tile == 8: 277 | exit = Exit(col_count * tile_size, row_count * tile_size - (tile_size // 2)) 278 | exit_group.add(exit) 279 | col_count += 1 280 | row_count += 1 281 | 282 | 283 | def draw(self): 284 | for tile in self.tile_list: 285 | screen.blit(tile[0], tile[1]) 286 | pygame.draw.rect(screen, (255, 255, 255), tile[1], 2) 287 | 288 | 289 | 290 | class Enemy(pygame.sprite.Sprite): 291 | def __init__(self, x, y): 292 | pygame.sprite.Sprite.__init__(self) 293 | self.image = pygame.image.load('img/blob.png') 294 | self.rect = self.image.get_rect() 295 | self.rect.x = x 296 | self.rect.y = y 297 | self.move_direction = 1 298 | self.move_counter = 0 299 | 300 | def update(self): 301 | self.rect.x += self.move_direction 302 | self.move_counter += 1 303 | if abs(self.move_counter) > 50: 304 | self.move_direction *= -1 305 | self.move_counter *= -1 306 | 307 | 308 | class Lava(pygame.sprite.Sprite): 309 | def __init__(self, x, y): 310 | pygame.sprite.Sprite.__init__(self) 311 | img = pygame.image.load('img/lava.png') 312 | self.image = pygame.transform.scale(img, (tile_size, tile_size // 2)) 313 | self.rect = self.image.get_rect() 314 | self.rect.x = x 315 | self.rect.y = y 316 | 317 | 318 | class Coin(pygame.sprite.Sprite): 319 | def __init__(self, x, y): 320 | pygame.sprite.Sprite.__init__(self) 321 | img = pygame.image.load('img/coin.png') 322 | self.image = pygame.transform.scale(img, (tile_size // 2, tile_size // 2)) 323 | self.rect = self.image.get_rect() 324 | self.rect.center = (x, y) 325 | 326 | 327 | class Exit(pygame.sprite.Sprite): 328 | def __init__(self, x, y): 329 | pygame.sprite.Sprite.__init__(self) 330 | img = pygame.image.load('img/exit.png') 331 | self.image = pygame.transform.scale(img, (tile_size, int(tile_size * 1.5))) 332 | self.rect = self.image.get_rect() 333 | self.rect.x = x 334 | self.rect.y = y 335 | 336 | 337 | 338 | player = Player(100, screen_height - 130) 339 | 340 | blob_group = pygame.sprite.Group() 341 | lava_group = pygame.sprite.Group() 342 | coin_group = pygame.sprite.Group() 343 | exit_group = pygame.sprite.Group() 344 | 345 | #create dummy coin for showing the score 346 | score_coin = Coin(tile_size // 2, tile_size // 2) 347 | coin_group.add(score_coin) 348 | 349 | #load in level data and create world 350 | if path.exists(f'level{level}_data'): 351 | pickle_in = open(f'level{level}_data', 'rb') 352 | world_data = pickle.load(pickle_in) 353 | world = World(world_data) 354 | 355 | 356 | #create buttons 357 | restart_button = Button(screen_width // 2 - 50, screen_height // 2 + 100, restart_img) 358 | start_button = Button(screen_width // 2 - 350, screen_height // 2, start_img) 359 | exit_button = Button(screen_width // 2 + 150, screen_height // 2, exit_img) 360 | 361 | 362 | run = True 363 | while run: 364 | 365 | clock.tick(fps) 366 | 367 | screen.blit(bg_img, (0, 0)) 368 | screen.blit(sun_img, (100, 100)) 369 | 370 | if main_menu == True: 371 | if exit_button.draw(): 372 | run = False 373 | if start_button.draw(): 374 | main_menu = False 375 | else: 376 | world.draw() 377 | 378 | if game_over == 0: 379 | blob_group.update() 380 | #update score 381 | #check if a coin has been collected 382 | if pygame.sprite.spritecollide(player, coin_group, True): 383 | score += 1 384 | coin_fx.play() 385 | draw_text('X ' + str(score), font_score, white, tile_size - 10, 10) 386 | 387 | blob_group.draw(screen) 388 | lava_group.draw(screen) 389 | coin_group.draw(screen) 390 | exit_group.draw(screen) 391 | 392 | game_over = player.update(game_over) 393 | 394 | #if player has died 395 | if game_over == -1: 396 | if restart_button.draw(): 397 | world_data = [] 398 | world = reset_level(level) 399 | game_over = 0 400 | score = 0 401 | 402 | #if player has completed the level 403 | if game_over == 1: 404 | #reset game and go to next level 405 | level += 1 406 | if level <= max_levels: 407 | #reset level 408 | world_data = [] 409 | world = reset_level(level) 410 | game_over = 0 411 | else: 412 | draw_text('YOU WIN!', font, blue, (screen_width // 2) - 140, screen_height // 2) 413 | if restart_button.draw(): 414 | level = 1 415 | #reset level 416 | world_data = [] 417 | world = reset_level(level) 418 | game_over = 0 419 | score = 0 420 | 421 | 422 | 423 | for event in pygame.event.get(): 424 | if event.type == pygame.QUIT: 425 | run = False 426 | 427 | pygame.display.update() 428 | 429 | pygame.quit() -------------------------------------------------------------------------------- /Part_12-Moving_Platforms/platformer_tut12.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | from pygame import mixer 4 | import pickle 5 | from os import path 6 | 7 | pygame.mixer.pre_init(44100, -16, 2, 512) 8 | mixer.init() 9 | pygame.init() 10 | 11 | clock = pygame.time.Clock() 12 | fps = 60 13 | 14 | screen_width = 1000 15 | screen_height = 1000 16 | 17 | screen = pygame.display.set_mode((screen_width, screen_height)) 18 | pygame.display.set_caption('Platformer') 19 | 20 | 21 | #define font 22 | font = pygame.font.SysFont('Bauhaus 93', 70) 23 | font_score = pygame.font.SysFont('Bauhaus 93', 30) 24 | 25 | 26 | #define game variables 27 | tile_size = 50 28 | game_over = 0 29 | main_menu = True 30 | level = 3 31 | max_levels = 7 32 | score = 0 33 | 34 | 35 | #define colours 36 | white = (255, 255, 255) 37 | blue = (0, 0, 255) 38 | 39 | 40 | #load images 41 | sun_img = pygame.image.load('img/sun.png') 42 | bg_img = pygame.image.load('img/sky.png') 43 | restart_img = pygame.image.load('img/restart_btn.png') 44 | start_img = pygame.image.load('img/start_btn.png') 45 | exit_img = pygame.image.load('img/exit_btn.png') 46 | 47 | #load sounds 48 | #pygame.mixer.music.load('img/music.wav') 49 | #pygame.mixer.music.play(-1, 0.0, 5000) 50 | coin_fx = pygame.mixer.Sound('img/coin.wav') 51 | coin_fx.set_volume(0.5) 52 | jump_fx = pygame.mixer.Sound('img/jump.wav') 53 | jump_fx.set_volume(0.5) 54 | game_over_fx = pygame.mixer.Sound('img/game_over.wav') 55 | game_over_fx.set_volume(0.5) 56 | 57 | 58 | def draw_text(text, font, text_col, x, y): 59 | img = font.render(text, True, text_col) 60 | screen.blit(img, (x, y)) 61 | 62 | 63 | #function to reset level 64 | def reset_level(level): 65 | player.reset(100, screen_height - 130) 66 | blob_group.empty() 67 | lava_group.empty() 68 | exit_group.empty() 69 | 70 | #load in level data and create world 71 | if path.exists(f'level{level}_data'): 72 | pickle_in = open(f'level{level}_data', 'rb') 73 | world_data = pickle.load(pickle_in) 74 | world = World(world_data) 75 | 76 | return world 77 | 78 | 79 | class Button(): 80 | def __init__(self, x, y, image): 81 | self.image = image 82 | self.rect = self.image.get_rect() 83 | self.rect.x = x 84 | self.rect.y = y 85 | self.clicked = False 86 | 87 | def draw(self): 88 | action = False 89 | 90 | #get mouse position 91 | pos = pygame.mouse.get_pos() 92 | 93 | #check mouseover and clicked conditions 94 | if self.rect.collidepoint(pos): 95 | if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False: 96 | action = True 97 | self.clicked = True 98 | 99 | if pygame.mouse.get_pressed()[0] == 0: 100 | self.clicked = False 101 | 102 | 103 | #draw button 104 | screen.blit(self.image, self.rect) 105 | 106 | return action 107 | 108 | 109 | class Player(): 110 | def __init__(self, x, y): 111 | self.reset(x, y) 112 | 113 | 114 | 115 | def update(self, game_over): 116 | dx = 0 117 | dy = 0 118 | walk_cooldown = 5 119 | 120 | if game_over == 0: 121 | #get keypresses 122 | key = pygame.key.get_pressed() 123 | if key[pygame.K_SPACE] and self.jumped == False and self.in_air == False: 124 | jump_fx.play() 125 | self.vel_y = -15 126 | self.jumped = True 127 | if key[pygame.K_SPACE] == False: 128 | self.jumped = False 129 | if key[pygame.K_LEFT]: 130 | dx -= 5 131 | self.counter += 1 132 | self.direction = -1 133 | if key[pygame.K_RIGHT]: 134 | dx += 5 135 | self.counter += 1 136 | self.direction = 1 137 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 138 | self.counter = 0 139 | self.index = 0 140 | if self.direction == 1: 141 | self.image = self.images_right[self.index] 142 | if self.direction == -1: 143 | self.image = self.images_left[self.index] 144 | 145 | 146 | #handle animation 147 | if self.counter > walk_cooldown: 148 | self.counter = 0 149 | self.index += 1 150 | if self.index >= len(self.images_right): 151 | self.index = 0 152 | if self.direction == 1: 153 | self.image = self.images_right[self.index] 154 | if self.direction == -1: 155 | self.image = self.images_left[self.index] 156 | 157 | 158 | #add gravity 159 | self.vel_y += 1 160 | if self.vel_y > 10: 161 | self.vel_y = 10 162 | dy += self.vel_y 163 | 164 | #check for collision 165 | self.in_air = True 166 | for tile in world.tile_list: 167 | #check for collision in x direction 168 | if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): 169 | dx = 0 170 | #check for collision in y direction 171 | if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): 172 | #check if below the ground i.e. jumping 173 | if self.vel_y < 0: 174 | dy = tile[1].bottom - self.rect.top 175 | self.vel_y = 0 176 | #check if above the ground i.e. falling 177 | elif self.vel_y >= 0: 178 | dy = tile[1].top - self.rect.bottom 179 | self.vel_y = 0 180 | self.in_air = False 181 | 182 | 183 | #check for collision with enemies 184 | if pygame.sprite.spritecollide(self, blob_group, False): 185 | game_over = -1 186 | game_over_fx.play() 187 | 188 | #check for collision with lava 189 | if pygame.sprite.spritecollide(self, lava_group, False): 190 | game_over = -1 191 | game_over_fx.play() 192 | 193 | #check for collision with exit 194 | if pygame.sprite.spritecollide(self, exit_group, False): 195 | game_over = 1 196 | 197 | 198 | #update player coordinates 199 | self.rect.x += dx 200 | self.rect.y += dy 201 | 202 | 203 | elif game_over == -1: 204 | self.image = self.dead_image 205 | draw_text('GAME OVER!', font, blue, (screen_width // 2) - 200, screen_height // 2) 206 | if self.rect.y > 200: 207 | self.rect.y -= 5 208 | 209 | #draw player onto screen 210 | screen.blit(self.image, self.rect) 211 | pygame.draw.rect(screen, (255, 255, 255), self.rect, 2) 212 | 213 | return game_over 214 | 215 | 216 | def reset(self, x, y): 217 | self.images_right = [] 218 | self.images_left = [] 219 | self.index = 0 220 | self.counter = 0 221 | for num in range(1, 5): 222 | img_right = pygame.image.load(f'img/guy{num}.png') 223 | img_right = pygame.transform.scale(img_right, (40, 80)) 224 | img_left = pygame.transform.flip(img_right, True, False) 225 | self.images_right.append(img_right) 226 | self.images_left.append(img_left) 227 | self.dead_image = pygame.image.load('img/ghost.png') 228 | self.image = self.images_right[self.index] 229 | self.rect = self.image.get_rect() 230 | self.rect.x = x 231 | self.rect.y = y 232 | self.width = self.image.get_width() 233 | self.height = self.image.get_height() 234 | self.vel_y = 0 235 | self.jumped = False 236 | self.direction = 0 237 | self.in_air = True 238 | 239 | 240 | 241 | class World(): 242 | def __init__(self, data): 243 | self.tile_list = [] 244 | 245 | #load images 246 | dirt_img = pygame.image.load('img/dirt.png') 247 | grass_img = pygame.image.load('img/grass.png') 248 | 249 | row_count = 0 250 | for row in data: 251 | col_count = 0 252 | for tile in row: 253 | if tile == 1: 254 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 255 | img_rect = img.get_rect() 256 | img_rect.x = col_count * tile_size 257 | img_rect.y = row_count * tile_size 258 | tile = (img, img_rect) 259 | self.tile_list.append(tile) 260 | if tile == 2: 261 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 262 | img_rect = img.get_rect() 263 | img_rect.x = col_count * tile_size 264 | img_rect.y = row_count * tile_size 265 | tile = (img, img_rect) 266 | self.tile_list.append(tile) 267 | if tile == 3: 268 | blob = Enemy(col_count * tile_size, row_count * tile_size + 15) 269 | blob_group.add(blob) 270 | if tile == 4: 271 | platform = Platform(col_count * tile_size, row_count * tile_size, 1, 0) 272 | platform_group.add(platform) 273 | if tile == 5: 274 | platform = Platform(col_count * tile_size, row_count * tile_size, 0, 1) 275 | platform_group.add(platform) 276 | if tile == 6: 277 | lava = Lava(col_count * tile_size, row_count * tile_size + (tile_size // 2)) 278 | lava_group.add(lava) 279 | if tile == 7: 280 | coin = Coin(col_count * tile_size + (tile_size // 2), row_count * tile_size + (tile_size // 2)) 281 | coin_group.add(coin) 282 | if tile == 8: 283 | exit = Exit(col_count * tile_size, row_count * tile_size - (tile_size // 2)) 284 | exit_group.add(exit) 285 | col_count += 1 286 | row_count += 1 287 | 288 | 289 | def draw(self): 290 | for tile in self.tile_list: 291 | screen.blit(tile[0], tile[1]) 292 | pygame.draw.rect(screen, (255, 255, 255), tile[1], 2) 293 | 294 | 295 | 296 | class Enemy(pygame.sprite.Sprite): 297 | def __init__(self, x, y): 298 | pygame.sprite.Sprite.__init__(self) 299 | self.image = pygame.image.load('img/blob.png') 300 | self.rect = self.image.get_rect() 301 | self.rect.x = x 302 | self.rect.y = y 303 | self.move_direction = 1 304 | self.move_counter = 0 305 | 306 | def update(self): 307 | self.rect.x += self.move_direction 308 | self.move_counter += 1 309 | if abs(self.move_counter) > 50: 310 | self.move_direction *= -1 311 | self.move_counter *= -1 312 | 313 | 314 | class Platform(pygame.sprite.Sprite): 315 | def __init__(self, x, y, move_x, move_y): 316 | pygame.sprite.Sprite.__init__(self) 317 | img = pygame.image.load('img/platform.png') 318 | self.image = pygame.transform.scale(img, (tile_size, tile_size // 2)) 319 | self.rect = self.image.get_rect() 320 | self.rect.x = x 321 | self.rect.y = y 322 | self.move_counter = 0 323 | self.move_direction = 1 324 | self.move_x = move_x 325 | self.move_y = move_y 326 | 327 | 328 | def update(self): 329 | self.rect.x += self.move_direction * self.move_x 330 | self.rect.y += self.move_direction * self.move_y 331 | self.move_counter += 1 332 | if abs(self.move_counter) > 50: 333 | self.move_direction *= -1 334 | self.move_counter *= -1 335 | 336 | 337 | 338 | 339 | 340 | class Lava(pygame.sprite.Sprite): 341 | def __init__(self, x, y): 342 | pygame.sprite.Sprite.__init__(self) 343 | img = pygame.image.load('img/lava.png') 344 | self.image = pygame.transform.scale(img, (tile_size, tile_size // 2)) 345 | self.rect = self.image.get_rect() 346 | self.rect.x = x 347 | self.rect.y = y 348 | 349 | 350 | class Coin(pygame.sprite.Sprite): 351 | def __init__(self, x, y): 352 | pygame.sprite.Sprite.__init__(self) 353 | img = pygame.image.load('img/coin.png') 354 | self.image = pygame.transform.scale(img, (tile_size // 2, tile_size // 2)) 355 | self.rect = self.image.get_rect() 356 | self.rect.center = (x, y) 357 | 358 | 359 | class Exit(pygame.sprite.Sprite): 360 | def __init__(self, x, y): 361 | pygame.sprite.Sprite.__init__(self) 362 | img = pygame.image.load('img/exit.png') 363 | self.image = pygame.transform.scale(img, (tile_size, int(tile_size * 1.5))) 364 | self.rect = self.image.get_rect() 365 | self.rect.x = x 366 | self.rect.y = y 367 | 368 | 369 | 370 | player = Player(100, screen_height - 130) 371 | 372 | blob_group = pygame.sprite.Group() 373 | platform_group = pygame.sprite.Group() 374 | lava_group = pygame.sprite.Group() 375 | coin_group = pygame.sprite.Group() 376 | exit_group = pygame.sprite.Group() 377 | 378 | #create dummy coin for showing the score 379 | score_coin = Coin(tile_size // 2, tile_size // 2) 380 | coin_group.add(score_coin) 381 | 382 | #load in level data and create world 383 | if path.exists(f'level{level}_data'): 384 | pickle_in = open(f'level{level}_data', 'rb') 385 | world_data = pickle.load(pickle_in) 386 | world = World(world_data) 387 | 388 | 389 | #create buttons 390 | restart_button = Button(screen_width // 2 - 50, screen_height // 2 + 100, restart_img) 391 | start_button = Button(screen_width // 2 - 350, screen_height // 2, start_img) 392 | exit_button = Button(screen_width // 2 + 150, screen_height // 2, exit_img) 393 | 394 | 395 | run = True 396 | while run: 397 | 398 | clock.tick(fps) 399 | 400 | screen.blit(bg_img, (0, 0)) 401 | screen.blit(sun_img, (100, 100)) 402 | 403 | if main_menu == True: 404 | if exit_button.draw(): 405 | run = False 406 | if start_button.draw(): 407 | main_menu = False 408 | else: 409 | world.draw() 410 | 411 | if game_over == 0: 412 | blob_group.update() 413 | platform_group.update() 414 | #update score 415 | #check if a coin has been collected 416 | if pygame.sprite.spritecollide(player, coin_group, True): 417 | score += 1 418 | coin_fx.play() 419 | draw_text('X ' + str(score), font_score, white, tile_size - 10, 10) 420 | 421 | blob_group.draw(screen) 422 | platform_group.draw(screen) 423 | lava_group.draw(screen) 424 | coin_group.draw(screen) 425 | exit_group.draw(screen) 426 | 427 | game_over = player.update(game_over) 428 | 429 | #if player has died 430 | if game_over == -1: 431 | if restart_button.draw(): 432 | world_data = [] 433 | world = reset_level(level) 434 | game_over = 0 435 | score = 0 436 | 437 | #if player has completed the level 438 | if game_over == 1: 439 | #reset game and go to next level 440 | level += 1 441 | if level <= max_levels: 442 | #reset level 443 | world_data = [] 444 | world = reset_level(level) 445 | game_over = 0 446 | else: 447 | draw_text('YOU WIN!', font, blue, (screen_width // 2) - 140, screen_height // 2) 448 | if restart_button.draw(): 449 | level = 1 450 | #reset level 451 | world_data = [] 452 | world = reset_level(level) 453 | game_over = 0 454 | score = 0 455 | 456 | 457 | 458 | for event in pygame.event.get(): 459 | if event.type == pygame.QUIT: 460 | run = False 461 | 462 | pygame.display.update() 463 | 464 | pygame.quit() -------------------------------------------------------------------------------- /Part_13-Moving_Platform_Collision/platformer_tut13.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | from pygame import mixer 4 | import pickle 5 | from os import path 6 | 7 | pygame.mixer.pre_init(44100, -16, 2, 512) 8 | mixer.init() 9 | pygame.init() 10 | 11 | clock = pygame.time.Clock() 12 | fps = 60 13 | 14 | screen_width = 1000 15 | screen_height = 1000 16 | 17 | screen = pygame.display.set_mode((screen_width, screen_height)) 18 | pygame.display.set_caption('Platformer') 19 | 20 | 21 | #define font 22 | font = pygame.font.SysFont('Bauhaus 93', 70) 23 | font_score = pygame.font.SysFont('Bauhaus 93', 30) 24 | 25 | 26 | #define game variables 27 | tile_size = 50 28 | game_over = 0 29 | main_menu = True 30 | level = 3 31 | max_levels = 7 32 | score = 0 33 | 34 | 35 | #define colours 36 | white = (255, 255, 255) 37 | blue = (0, 0, 255) 38 | 39 | 40 | #load images 41 | sun_img = pygame.image.load('img/sun.png') 42 | bg_img = pygame.image.load('img/sky.png') 43 | restart_img = pygame.image.load('img/restart_btn.png') 44 | start_img = pygame.image.load('img/start_btn.png') 45 | exit_img = pygame.image.load('img/exit_btn.png') 46 | 47 | #load sounds 48 | pygame.mixer.music.load('img/music.wav') 49 | pygame.mixer.music.play(-1, 0.0, 5000) 50 | coin_fx = pygame.mixer.Sound('img/coin.wav') 51 | coin_fx.set_volume(0.5) 52 | jump_fx = pygame.mixer.Sound('img/jump.wav') 53 | jump_fx.set_volume(0.5) 54 | game_over_fx = pygame.mixer.Sound('img/game_over.wav') 55 | game_over_fx.set_volume(0.5) 56 | 57 | 58 | def draw_text(text, font, text_col, x, y): 59 | img = font.render(text, True, text_col) 60 | screen.blit(img, (x, y)) 61 | 62 | 63 | #function to reset level 64 | def reset_level(level): 65 | player.reset(100, screen_height - 130) 66 | blob_group.empty() 67 | platform_group.empty() 68 | coin_group.empty() 69 | lava_group.empty() 70 | exit_group.empty() 71 | 72 | #load in level data and create world 73 | if path.exists(f'level{level}_data'): 74 | pickle_in = open(f'level{level}_data', 'rb') 75 | world_data = pickle.load(pickle_in) 76 | world = World(world_data) 77 | #create dummy coin for showing the score 78 | score_coin = Coin(tile_size // 2, tile_size // 2) 79 | coin_group.add(score_coin) 80 | return world 81 | 82 | 83 | class Button(): 84 | def __init__(self, x, y, image): 85 | self.image = image 86 | self.rect = self.image.get_rect() 87 | self.rect.x = x 88 | self.rect.y = y 89 | self.clicked = False 90 | 91 | def draw(self): 92 | action = False 93 | 94 | #get mouse position 95 | pos = pygame.mouse.get_pos() 96 | 97 | #check mouseover and clicked conditions 98 | if self.rect.collidepoint(pos): 99 | if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False: 100 | action = True 101 | self.clicked = True 102 | 103 | if pygame.mouse.get_pressed()[0] == 0: 104 | self.clicked = False 105 | 106 | 107 | #draw button 108 | screen.blit(self.image, self.rect) 109 | 110 | return action 111 | 112 | 113 | class Player(): 114 | def __init__(self, x, y): 115 | self.reset(x, y) 116 | 117 | def update(self, game_over): 118 | dx = 0 119 | dy = 0 120 | walk_cooldown = 5 121 | col_thresh = 20 122 | 123 | if game_over == 0: 124 | #get keypresses 125 | key = pygame.key.get_pressed() 126 | if key[pygame.K_SPACE] and self.jumped == False and self.in_air == False: 127 | jump_fx.play() 128 | self.vel_y = -15 129 | self.jumped = True 130 | if key[pygame.K_SPACE] == False: 131 | self.jumped = False 132 | if key[pygame.K_LEFT]: 133 | dx -= 5 134 | self.counter += 1 135 | self.direction = -1 136 | if key[pygame.K_RIGHT]: 137 | dx += 5 138 | self.counter += 1 139 | self.direction = 1 140 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 141 | self.counter = 0 142 | self.index = 0 143 | if self.direction == 1: 144 | self.image = self.images_right[self.index] 145 | if self.direction == -1: 146 | self.image = self.images_left[self.index] 147 | 148 | 149 | #handle animation 150 | if self.counter > walk_cooldown: 151 | self.counter = 0 152 | self.index += 1 153 | if self.index >= len(self.images_right): 154 | self.index = 0 155 | if self.direction == 1: 156 | self.image = self.images_right[self.index] 157 | if self.direction == -1: 158 | self.image = self.images_left[self.index] 159 | 160 | 161 | #add gravity 162 | self.vel_y += 1 163 | if self.vel_y > 10: 164 | self.vel_y = 10 165 | dy += self.vel_y 166 | 167 | #check for collision 168 | self.in_air = True 169 | for tile in world.tile_list: 170 | #check for collision in x direction 171 | if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): 172 | dx = 0 173 | #check for collision in y direction 174 | if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): 175 | #check if below the ground i.e. jumping 176 | if self.vel_y < 0: 177 | dy = tile[1].bottom - self.rect.top 178 | self.vel_y = 0 179 | #check if above the ground i.e. falling 180 | elif self.vel_y >= 0: 181 | dy = tile[1].top - self.rect.bottom 182 | self.vel_y = 0 183 | self.in_air = False 184 | 185 | 186 | #check for collision with enemies 187 | if pygame.sprite.spritecollide(self, blob_group, False): 188 | game_over = -1 189 | game_over_fx.play() 190 | 191 | #check for collision with lava 192 | if pygame.sprite.spritecollide(self, lava_group, False): 193 | game_over = -1 194 | game_over_fx.play() 195 | 196 | #check for collision with exit 197 | if pygame.sprite.spritecollide(self, exit_group, False): 198 | game_over = 1 199 | 200 | 201 | #check for collision with platforms 202 | for platform in platform_group: 203 | #collision in the x direction 204 | if platform.rect.colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): 205 | dx = 0 206 | #collision in the y direction 207 | if platform.rect.colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): 208 | #check if below platform 209 | if abs((self.rect.top + dy) - platform.rect.bottom) < col_thresh: 210 | self.vel_y = 0 211 | dy = platform.rect.bottom - self.rect.top 212 | #check if above platform 213 | elif abs((self.rect.bottom + dy) - platform.rect.top) < col_thresh: 214 | self.rect.bottom = platform.rect.top - 1 215 | self.in_air = False 216 | dy = 0 217 | #move sideways with the platform 218 | if platform.move_x != 0: 219 | self.rect.x += platform.move_direction 220 | 221 | 222 | #update player coordinates 223 | self.rect.x += dx 224 | self.rect.y += dy 225 | 226 | 227 | elif game_over == -1: 228 | self.image = self.dead_image 229 | draw_text('GAME OVER!', font, blue, (screen_width // 2) - 200, screen_height // 2) 230 | if self.rect.y > 200: 231 | self.rect.y -= 5 232 | 233 | #draw player onto screen 234 | screen.blit(self.image, self.rect) 235 | 236 | return game_over 237 | 238 | 239 | def reset(self, x, y): 240 | self.images_right = [] 241 | self.images_left = [] 242 | self.index = 0 243 | self.counter = 0 244 | for num in range(1, 5): 245 | img_right = pygame.image.load(f'img/guy{num}.png') 246 | img_right = pygame.transform.scale(img_right, (40, 80)) 247 | img_left = pygame.transform.flip(img_right, True, False) 248 | self.images_right.append(img_right) 249 | self.images_left.append(img_left) 250 | self.dead_image = pygame.image.load('img/ghost.png') 251 | self.image = self.images_right[self.index] 252 | self.rect = self.image.get_rect() 253 | self.rect.x = x 254 | self.rect.y = y 255 | self.width = self.image.get_width() 256 | self.height = self.image.get_height() 257 | self.vel_y = 0 258 | self.jumped = False 259 | self.direction = 0 260 | self.in_air = True 261 | 262 | 263 | 264 | class World(): 265 | def __init__(self, data): 266 | self.tile_list = [] 267 | 268 | #load images 269 | dirt_img = pygame.image.load('img/dirt.png') 270 | grass_img = pygame.image.load('img/grass.png') 271 | 272 | row_count = 0 273 | for row in data: 274 | col_count = 0 275 | for tile in row: 276 | if tile == 1: 277 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 278 | img_rect = img.get_rect() 279 | img_rect.x = col_count * tile_size 280 | img_rect.y = row_count * tile_size 281 | tile = (img, img_rect) 282 | self.tile_list.append(tile) 283 | if tile == 2: 284 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 285 | img_rect = img.get_rect() 286 | img_rect.x = col_count * tile_size 287 | img_rect.y = row_count * tile_size 288 | tile = (img, img_rect) 289 | self.tile_list.append(tile) 290 | if tile == 3: 291 | blob = Enemy(col_count * tile_size, row_count * tile_size + 15) 292 | blob_group.add(blob) 293 | if tile == 4: 294 | platform = Platform(col_count * tile_size, row_count * tile_size, 1, 0) 295 | platform_group.add(platform) 296 | if tile == 5: 297 | platform = Platform(col_count * tile_size, row_count * tile_size, 0, 1) 298 | platform_group.add(platform) 299 | if tile == 6: 300 | lava = Lava(col_count * tile_size, row_count * tile_size + (tile_size // 2)) 301 | lava_group.add(lava) 302 | if tile == 7: 303 | coin = Coin(col_count * tile_size + (tile_size // 2), row_count * tile_size + (tile_size // 2)) 304 | coin_group.add(coin) 305 | if tile == 8: 306 | exit = Exit(col_count * tile_size, row_count * tile_size - (tile_size // 2)) 307 | exit_group.add(exit) 308 | col_count += 1 309 | row_count += 1 310 | 311 | 312 | def draw(self): 313 | for tile in self.tile_list: 314 | screen.blit(tile[0], tile[1]) 315 | 316 | 317 | 318 | class Enemy(pygame.sprite.Sprite): 319 | def __init__(self, x, y): 320 | pygame.sprite.Sprite.__init__(self) 321 | self.image = pygame.image.load('img/blob.png') 322 | self.rect = self.image.get_rect() 323 | self.rect.x = x 324 | self.rect.y = y 325 | self.move_direction = 1 326 | self.move_counter = 0 327 | 328 | def update(self): 329 | self.rect.x += self.move_direction 330 | self.move_counter += 1 331 | if abs(self.move_counter) > 50: 332 | self.move_direction *= -1 333 | self.move_counter *= -1 334 | 335 | 336 | class Platform(pygame.sprite.Sprite): 337 | def __init__(self, x, y, move_x, move_y): 338 | pygame.sprite.Sprite.__init__(self) 339 | img = pygame.image.load('img/platform.png') 340 | self.image = pygame.transform.scale(img, (tile_size, tile_size // 2)) 341 | self.rect = self.image.get_rect() 342 | self.rect.x = x 343 | self.rect.y = y 344 | self.move_counter = 0 345 | self.move_direction = 1 346 | self.move_x = move_x 347 | self.move_y = move_y 348 | 349 | 350 | def update(self): 351 | self.rect.x += self.move_direction * self.move_x 352 | self.rect.y += self.move_direction * self.move_y 353 | self.move_counter += 1 354 | if abs(self.move_counter) > 50: 355 | self.move_direction *= -1 356 | self.move_counter *= -1 357 | 358 | 359 | 360 | 361 | 362 | class Lava(pygame.sprite.Sprite): 363 | def __init__(self, x, y): 364 | pygame.sprite.Sprite.__init__(self) 365 | img = pygame.image.load('img/lava.png') 366 | self.image = pygame.transform.scale(img, (tile_size, tile_size // 2)) 367 | self.rect = self.image.get_rect() 368 | self.rect.x = x 369 | self.rect.y = y 370 | 371 | 372 | class Coin(pygame.sprite.Sprite): 373 | def __init__(self, x, y): 374 | pygame.sprite.Sprite.__init__(self) 375 | img = pygame.image.load('img/coin.png') 376 | self.image = pygame.transform.scale(img, (tile_size // 2, tile_size // 2)) 377 | self.rect = self.image.get_rect() 378 | self.rect.center = (x, y) 379 | 380 | 381 | class Exit(pygame.sprite.Sprite): 382 | def __init__(self, x, y): 383 | pygame.sprite.Sprite.__init__(self) 384 | img = pygame.image.load('img/exit.png') 385 | self.image = pygame.transform.scale(img, (tile_size, int(tile_size * 1.5))) 386 | self.rect = self.image.get_rect() 387 | self.rect.x = x 388 | self.rect.y = y 389 | 390 | 391 | 392 | player = Player(100, screen_height - 130) 393 | 394 | blob_group = pygame.sprite.Group() 395 | platform_group = pygame.sprite.Group() 396 | lava_group = pygame.sprite.Group() 397 | coin_group = pygame.sprite.Group() 398 | exit_group = pygame.sprite.Group() 399 | 400 | #create dummy coin for showing the score 401 | score_coin = Coin(tile_size // 2, tile_size // 2) 402 | coin_group.add(score_coin) 403 | 404 | #load in level data and create world 405 | if path.exists(f'level{level}_data'): 406 | pickle_in = open(f'level{level}_data', 'rb') 407 | world_data = pickle.load(pickle_in) 408 | world = World(world_data) 409 | 410 | 411 | #create buttons 412 | restart_button = Button(screen_width // 2 - 50, screen_height // 2 + 100, restart_img) 413 | start_button = Button(screen_width // 2 - 350, screen_height // 2, start_img) 414 | exit_button = Button(screen_width // 2 + 150, screen_height // 2, exit_img) 415 | 416 | 417 | run = True 418 | while run: 419 | 420 | clock.tick(fps) 421 | 422 | screen.blit(bg_img, (0, 0)) 423 | screen.blit(sun_img, (100, 100)) 424 | 425 | if main_menu == True: 426 | if exit_button.draw(): 427 | run = False 428 | if start_button.draw(): 429 | main_menu = False 430 | else: 431 | world.draw() 432 | 433 | if game_over == 0: 434 | blob_group.update() 435 | platform_group.update() 436 | #update score 437 | #check if a coin has been collected 438 | if pygame.sprite.spritecollide(player, coin_group, True): 439 | score += 1 440 | coin_fx.play() 441 | draw_text('X ' + str(score), font_score, white, tile_size - 10, 10) 442 | 443 | blob_group.draw(screen) 444 | platform_group.draw(screen) 445 | lava_group.draw(screen) 446 | coin_group.draw(screen) 447 | exit_group.draw(screen) 448 | 449 | game_over = player.update(game_over) 450 | 451 | #if player has died 452 | if game_over == -1: 453 | if restart_button.draw(): 454 | world_data = [] 455 | world = reset_level(level) 456 | game_over = 0 457 | score = 0 458 | 459 | #if player has completed the level 460 | if game_over == 1: 461 | #reset game and go to next level 462 | level += 1 463 | if level <= max_levels: 464 | #reset level 465 | world_data = [] 466 | world = reset_level(level) 467 | game_over = 0 468 | else: 469 | draw_text('YOU WIN!', font, blue, (screen_width // 2) - 140, screen_height // 2) 470 | if restart_button.draw(): 471 | level = 1 472 | #reset level 473 | world_data = [] 474 | world = reset_level(level) 475 | game_over = 0 476 | score = 0 477 | 478 | for event in pygame.event.get(): 479 | if event.type == pygame.QUIT: 480 | run = False 481 | 482 | pygame.display.update() 483 | 484 | pygame.quit() -------------------------------------------------------------------------------- /Part_2-Create_Player/platformer_tut2.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | 4 | pygame.init() 5 | 6 | screen_width = 1000 7 | screen_height = 1000 8 | 9 | screen = pygame.display.set_mode((screen_width, screen_height)) 10 | pygame.display.set_caption('Platformer') 11 | 12 | #define game variables 13 | tile_size = 50 14 | 15 | 16 | #load images 17 | sun_img = pygame.image.load('img/sun.png') 18 | bg_img = pygame.image.load('img/sky.png') 19 | 20 | 21 | class Player(): 22 | def __init__(self, x, y): 23 | img = pygame.image.load('img/guy1.png') 24 | self.image = pygame.transform.scale(img, (40, 80)) 25 | self.rect = self.image.get_rect() 26 | self.rect.x = x 27 | self.rect.y = y 28 | self.vel_y = 0 29 | self.jumped = False 30 | 31 | def update(self): 32 | dx = 0 33 | dy = 0 34 | 35 | #get keypresses 36 | key = pygame.key.get_pressed() 37 | if key[pygame.K_SPACE] and self.jumped == False: 38 | self.vel_y = -15 39 | self.jumped = True 40 | if key[pygame.K_SPACE] == False: 41 | self.jumped = False 42 | if key[pygame.K_LEFT]: 43 | dx -= 5 44 | if key[pygame.K_RIGHT]: 45 | dx += 5 46 | 47 | 48 | #add gravity 49 | self.vel_y += 1 50 | if self.vel_y > 10: 51 | self.vel_y = 10 52 | dy += self.vel_y 53 | 54 | #check for collision 55 | 56 | #update player coordinates 57 | self.rect.x += dx 58 | self.rect.y += dy 59 | 60 | if self.rect.bottom > screen_height: 61 | self.rect.bottom = screen_height 62 | dy = 0 63 | 64 | #draw player onto screen 65 | screen.blit(self.image, self.rect) 66 | 67 | 68 | 69 | 70 | class World(): 71 | def __init__(self, data): 72 | self.tile_list = [] 73 | 74 | #load images 75 | dirt_img = pygame.image.load('img/dirt.png') 76 | grass_img = pygame.image.load('img/grass.png') 77 | 78 | row_count = 0 79 | for row in data: 80 | col_count = 0 81 | for tile in row: 82 | if tile == 1: 83 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 84 | img_rect = img.get_rect() 85 | img_rect.x = col_count * tile_size 86 | img_rect.y = row_count * tile_size 87 | tile = (img, img_rect) 88 | self.tile_list.append(tile) 89 | if tile == 2: 90 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 91 | img_rect = img.get_rect() 92 | img_rect.x = col_count * tile_size 93 | img_rect.y = row_count * tile_size 94 | tile = (img, img_rect) 95 | self.tile_list.append(tile) 96 | col_count += 1 97 | row_count += 1 98 | 99 | def draw(self): 100 | for tile in self.tile_list: 101 | screen.blit(tile[0], tile[1]) 102 | 103 | 104 | 105 | world_data = [ 106 | [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 107 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 108 | [1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1], 109 | [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 1], 110 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 7, 0, 5, 0, 0, 0, 1], 111 | [1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1], 112 | [1, 7, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 113 | [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 114 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 1], 115 | [1, 0, 2, 0, 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 116 | [1, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 1], 117 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1], 118 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 119 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 2, 0, 1], 120 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 121 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 1], 122 | [1, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1], 123 | [1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 124 | [1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 125 | [1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 126 | ] 127 | 128 | 129 | 130 | player = Player(100, screen_height - 130) 131 | world = World(world_data) 132 | 133 | run = True 134 | while run: 135 | 136 | screen.blit(bg_img, (0, 0)) 137 | screen.blit(sun_img, (100, 100)) 138 | 139 | world.draw() 140 | 141 | player.update() 142 | 143 | for event in pygame.event.get(): 144 | if event.type == pygame.QUIT: 145 | run = False 146 | 147 | pygame.display.update() 148 | 149 | pygame.quit() -------------------------------------------------------------------------------- /Part_3-Walking_Animation/platformer_tut3.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | 4 | pygame.init() 5 | 6 | clock = pygame.time.Clock() 7 | fps = 60 8 | 9 | screen_width = 1000 10 | screen_height = 1000 11 | 12 | screen = pygame.display.set_mode((screen_width, screen_height)) 13 | pygame.display.set_caption('Platformer') 14 | 15 | #define game variables 16 | tile_size = 50 17 | 18 | 19 | #load images 20 | sun_img = pygame.image.load('img/sun.png') 21 | bg_img = pygame.image.load('img/sky.png') 22 | 23 | 24 | class Player(): 25 | def __init__(self, x, y): 26 | self.images_right = [] 27 | self.images_left = [] 28 | self.index = 0 29 | self.counter = 0 30 | for num in range(1, 5): 31 | img_right = pygame.image.load(f'img/guy{num}.png') 32 | img_right = pygame.transform.scale(img_right, (40, 80)) 33 | img_left = pygame.transform.flip(img_right, True, False) 34 | self.images_right.append(img_right) 35 | self.images_left.append(img_left) 36 | self.image = self.images_right[self.index] 37 | self.rect = self.image.get_rect() 38 | self.rect.x = x 39 | self.rect.y = y 40 | self.vel_y = 0 41 | self.jumped = False 42 | self.direction = 0 43 | 44 | def update(self): 45 | dx = 0 46 | dy = 0 47 | walk_cooldown = 5 48 | 49 | #get keypresses 50 | key = pygame.key.get_pressed() 51 | if key[pygame.K_SPACE] and self.jumped == False: 52 | self.vel_y = -15 53 | self.jumped = True 54 | if key[pygame.K_SPACE] == False: 55 | self.jumped = False 56 | if key[pygame.K_LEFT]: 57 | dx -= 5 58 | self.counter += 1 59 | self.direction = -1 60 | if key[pygame.K_RIGHT]: 61 | dx += 5 62 | self.counter += 1 63 | self.direction = 1 64 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 65 | self.counter = 0 66 | self.index = 0 67 | if self.direction == 1: 68 | self.image = self.images_right[self.index] 69 | if self.direction == -1: 70 | self.image = self.images_left[self.index] 71 | 72 | 73 | #handle animation 74 | if self.counter > walk_cooldown: 75 | self.counter = 0 76 | self.index += 1 77 | if self.index >= len(self.images_right): 78 | self.index = 0 79 | if self.direction == 1: 80 | self.image = self.images_right[self.index] 81 | if self.direction == -1: 82 | self.image = self.images_left[self.index] 83 | 84 | 85 | #add gravity 86 | self.vel_y += 1 87 | if self.vel_y > 10: 88 | self.vel_y = 10 89 | dy += self.vel_y 90 | 91 | #check for collision 92 | 93 | #update player coordinates 94 | self.rect.x += dx 95 | self.rect.y += dy 96 | 97 | if self.rect.bottom > screen_height: 98 | self.rect.bottom = screen_height 99 | dy = 0 100 | 101 | #draw player onto screen 102 | screen.blit(self.image, self.rect) 103 | 104 | 105 | 106 | 107 | class World(): 108 | def __init__(self, data): 109 | self.tile_list = [] 110 | 111 | #load images 112 | dirt_img = pygame.image.load('img/dirt.png') 113 | grass_img = pygame.image.load('img/grass.png') 114 | 115 | row_count = 0 116 | for row in data: 117 | col_count = 0 118 | for tile in row: 119 | if tile == 1: 120 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 121 | img_rect = img.get_rect() 122 | img_rect.x = col_count * tile_size 123 | img_rect.y = row_count * tile_size 124 | tile = (img, img_rect) 125 | self.tile_list.append(tile) 126 | if tile == 2: 127 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 128 | img_rect = img.get_rect() 129 | img_rect.x = col_count * tile_size 130 | img_rect.y = row_count * tile_size 131 | tile = (img, img_rect) 132 | self.tile_list.append(tile) 133 | col_count += 1 134 | row_count += 1 135 | 136 | def draw(self): 137 | for tile in self.tile_list: 138 | screen.blit(tile[0], tile[1]) 139 | 140 | 141 | 142 | world_data = [ 143 | [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 144 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 145 | [1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1], 146 | [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 1], 147 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 7, 0, 5, 0, 0, 0, 1], 148 | [1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1], 149 | [1, 7, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 150 | [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 151 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 1], 152 | [1, 0, 2, 0, 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 153 | [1, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 1], 154 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1], 155 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 156 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 2, 0, 1], 157 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 158 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 1], 159 | [1, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1], 160 | [1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 161 | [1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 162 | [1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 163 | ] 164 | 165 | 166 | 167 | player = Player(100, screen_height - 130) 168 | world = World(world_data) 169 | 170 | run = True 171 | while run: 172 | 173 | clock.tick(fps) 174 | 175 | screen.blit(bg_img, (0, 0)) 176 | screen.blit(sun_img, (100, 100)) 177 | 178 | world.draw() 179 | 180 | player.update() 181 | 182 | for event in pygame.event.get(): 183 | if event.type == pygame.QUIT: 184 | run = False 185 | 186 | pygame.display.update() 187 | 188 | pygame.quit() -------------------------------------------------------------------------------- /Part_4-Collision/platformer_tut4.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | 4 | pygame.init() 5 | 6 | clock = pygame.time.Clock() 7 | fps = 60 8 | 9 | screen_width = 1000 10 | screen_height = 1000 11 | 12 | screen = pygame.display.set_mode((screen_width, screen_height)) 13 | pygame.display.set_caption('Platformer') 14 | 15 | #define game variables 16 | tile_size = 50 17 | 18 | 19 | #load images 20 | sun_img = pygame.image.load('img/sun.png') 21 | bg_img = pygame.image.load('img/sky.png') 22 | 23 | 24 | class Player(): 25 | def __init__(self, x, y): 26 | self.images_right = [] 27 | self.images_left = [] 28 | self.index = 0 29 | self.counter = 0 30 | for num in range(1, 5): 31 | img_right = pygame.image.load(f'img/guy{num}.png') 32 | img_right = pygame.transform.scale(img_right, (40, 80)) 33 | img_left = pygame.transform.flip(img_right, True, False) 34 | self.images_right.append(img_right) 35 | self.images_left.append(img_left) 36 | self.image = self.images_right[self.index] 37 | self.rect = self.image.get_rect() 38 | self.rect.x = x 39 | self.rect.y = y 40 | self.width = self.image.get_width() 41 | self.height = self.image.get_height() 42 | self.vel_y = 0 43 | self.jumped = False 44 | self.direction = 0 45 | 46 | def update(self): 47 | dx = 0 48 | dy = 0 49 | walk_cooldown = 5 50 | 51 | #get keypresses 52 | key = pygame.key.get_pressed() 53 | if key[pygame.K_SPACE] and self.jumped == False: 54 | self.vel_y = -15 55 | self.jumped = True 56 | if key[pygame.K_SPACE] == False: 57 | self.jumped = False 58 | if key[pygame.K_LEFT]: 59 | dx -= 5 60 | self.counter += 1 61 | self.direction = -1 62 | if key[pygame.K_RIGHT]: 63 | dx += 5 64 | self.counter += 1 65 | self.direction = 1 66 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 67 | self.counter = 0 68 | self.index = 0 69 | if self.direction == 1: 70 | self.image = self.images_right[self.index] 71 | if self.direction == -1: 72 | self.image = self.images_left[self.index] 73 | 74 | 75 | #handle animation 76 | if self.counter > walk_cooldown: 77 | self.counter = 0 78 | self.index += 1 79 | if self.index >= len(self.images_right): 80 | self.index = 0 81 | if self.direction == 1: 82 | self.image = self.images_right[self.index] 83 | if self.direction == -1: 84 | self.image = self.images_left[self.index] 85 | 86 | 87 | #add gravity 88 | self.vel_y += 1 89 | if self.vel_y > 10: 90 | self.vel_y = 10 91 | dy += self.vel_y 92 | 93 | #check for collision 94 | for tile in world.tile_list: 95 | #check for collision in x direction 96 | if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): 97 | dx = 0 98 | #check for collision in y direction 99 | if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): 100 | #check if below the ground i.e. jumping 101 | if self.vel_y < 0: 102 | dy = tile[1].bottom - self.rect.top 103 | self.vel_y = 0 104 | #check if above the ground i.e. falling 105 | elif self.vel_y >= 0: 106 | dy = tile[1].top - self.rect.bottom 107 | self.vel_y = 0 108 | 109 | 110 | 111 | 112 | #update player coordinates 113 | self.rect.x += dx 114 | self.rect.y += dy 115 | 116 | if self.rect.bottom > screen_height: 117 | self.rect.bottom = screen_height 118 | dy = 0 119 | 120 | #draw player onto screen 121 | screen.blit(self.image, self.rect) 122 | pygame.draw.rect(screen, (255, 255, 255), self.rect, 2) 123 | 124 | 125 | 126 | 127 | class World(): 128 | def __init__(self, data): 129 | self.tile_list = [] 130 | 131 | #load images 132 | dirt_img = pygame.image.load('img/dirt.png') 133 | grass_img = pygame.image.load('img/grass.png') 134 | 135 | row_count = 0 136 | for row in data: 137 | col_count = 0 138 | for tile in row: 139 | if tile == 1: 140 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 141 | img_rect = img.get_rect() 142 | img_rect.x = col_count * tile_size 143 | img_rect.y = row_count * tile_size 144 | tile = (img, img_rect) 145 | self.tile_list.append(tile) 146 | if tile == 2: 147 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 148 | img_rect = img.get_rect() 149 | img_rect.x = col_count * tile_size 150 | img_rect.y = row_count * tile_size 151 | tile = (img, img_rect) 152 | self.tile_list.append(tile) 153 | col_count += 1 154 | row_count += 1 155 | 156 | def draw(self): 157 | for tile in self.tile_list: 158 | screen.blit(tile[0], tile[1]) 159 | pygame.draw.rect(screen, (255, 255, 255), tile[1], 2) 160 | 161 | 162 | 163 | world_data = [ 164 | [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 165 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 166 | [1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1], 167 | [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 1], 168 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 7, 0, 5, 0, 0, 0, 1], 169 | [1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1], 170 | [1, 7, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 171 | [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 172 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 1], 173 | [1, 0, 2, 0, 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 174 | [1, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 1], 175 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1], 176 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 177 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 2, 0, 1], 178 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 179 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 1], 180 | [1, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1], 181 | [1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 182 | [1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 183 | [1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 184 | ] 185 | 186 | 187 | 188 | player = Player(100, screen_height - 130) 189 | world = World(world_data) 190 | 191 | run = True 192 | while run: 193 | 194 | clock.tick(fps) 195 | 196 | screen.blit(bg_img, (0, 0)) 197 | screen.blit(sun_img, (100, 100)) 198 | 199 | world.draw() 200 | 201 | player.update() 202 | 203 | for event in pygame.event.get(): 204 | if event.type == pygame.QUIT: 205 | run = False 206 | 207 | pygame.display.update() 208 | 209 | pygame.quit() -------------------------------------------------------------------------------- /Part_5-Adding_Enemies/platformer_tut5.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | 4 | pygame.init() 5 | 6 | clock = pygame.time.Clock() 7 | fps = 60 8 | 9 | screen_width = 1000 10 | screen_height = 1000 11 | 12 | screen = pygame.display.set_mode((screen_width, screen_height)) 13 | pygame.display.set_caption('Platformer') 14 | 15 | #define game variables 16 | tile_size = 50 17 | 18 | 19 | #load images 20 | sun_img = pygame.image.load('img/sun.png') 21 | bg_img = pygame.image.load('img/sky.png') 22 | 23 | 24 | class Player(): 25 | def __init__(self, x, y): 26 | self.images_right = [] 27 | self.images_left = [] 28 | self.index = 0 29 | self.counter = 0 30 | for num in range(1, 5): 31 | img_right = pygame.image.load(f'img/guy{num}.png') 32 | img_right = pygame.transform.scale(img_right, (40, 80)) 33 | img_left = pygame.transform.flip(img_right, True, False) 34 | self.images_right.append(img_right) 35 | self.images_left.append(img_left) 36 | self.image = self.images_right[self.index] 37 | self.rect = self.image.get_rect() 38 | self.rect.x = x 39 | self.rect.y = y 40 | self.width = self.image.get_width() 41 | self.height = self.image.get_height() 42 | self.vel_y = 0 43 | self.jumped = False 44 | self.direction = 0 45 | 46 | def update(self): 47 | dx = 0 48 | dy = 0 49 | walk_cooldown = 5 50 | 51 | #get keypresses 52 | key = pygame.key.get_pressed() 53 | if key[pygame.K_SPACE] and self.jumped == False: 54 | self.vel_y = -15 55 | self.jumped = True 56 | if key[pygame.K_SPACE] == False: 57 | self.jumped = False 58 | if key[pygame.K_LEFT]: 59 | dx -= 5 60 | self.counter += 1 61 | self.direction = -1 62 | if key[pygame.K_RIGHT]: 63 | dx += 5 64 | self.counter += 1 65 | self.direction = 1 66 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 67 | self.counter = 0 68 | self.index = 0 69 | if self.direction == 1: 70 | self.image = self.images_right[self.index] 71 | if self.direction == -1: 72 | self.image = self.images_left[self.index] 73 | 74 | 75 | #handle animation 76 | if self.counter > walk_cooldown: 77 | self.counter = 0 78 | self.index += 1 79 | if self.index >= len(self.images_right): 80 | self.index = 0 81 | if self.direction == 1: 82 | self.image = self.images_right[self.index] 83 | if self.direction == -1: 84 | self.image = self.images_left[self.index] 85 | 86 | 87 | #add gravity 88 | self.vel_y += 1 89 | if self.vel_y > 10: 90 | self.vel_y = 10 91 | dy += self.vel_y 92 | 93 | #check for collision 94 | for tile in world.tile_list: 95 | #check for collision in x direction 96 | if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): 97 | dx = 0 98 | #check for collision in y direction 99 | if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): 100 | #check if below the ground i.e. jumping 101 | if self.vel_y < 0: 102 | dy = tile[1].bottom - self.rect.top 103 | self.vel_y = 0 104 | #check if above the ground i.e. falling 105 | elif self.vel_y >= 0: 106 | dy = tile[1].top - self.rect.bottom 107 | self.vel_y = 0 108 | 109 | 110 | 111 | 112 | #update player coordinates 113 | self.rect.x += dx 114 | self.rect.y += dy 115 | 116 | if self.rect.bottom > screen_height: 117 | self.rect.bottom = screen_height 118 | dy = 0 119 | 120 | #draw player onto screen 121 | screen.blit(self.image, self.rect) 122 | pygame.draw.rect(screen, (255, 255, 255), self.rect, 2) 123 | 124 | 125 | 126 | 127 | class World(): 128 | def __init__(self, data): 129 | self.tile_list = [] 130 | 131 | #load images 132 | dirt_img = pygame.image.load('img/dirt.png') 133 | grass_img = pygame.image.load('img/grass.png') 134 | 135 | row_count = 0 136 | for row in data: 137 | col_count = 0 138 | for tile in row: 139 | if tile == 1: 140 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 141 | img_rect = img.get_rect() 142 | img_rect.x = col_count * tile_size 143 | img_rect.y = row_count * tile_size 144 | tile = (img, img_rect) 145 | self.tile_list.append(tile) 146 | if tile == 2: 147 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 148 | img_rect = img.get_rect() 149 | img_rect.x = col_count * tile_size 150 | img_rect.y = row_count * tile_size 151 | tile = (img, img_rect) 152 | self.tile_list.append(tile) 153 | if tile == 3: 154 | blob = Enemy(col_count * tile_size, row_count * tile_size + 15) 155 | blob_group.add(blob) 156 | col_count += 1 157 | row_count += 1 158 | 159 | def draw(self): 160 | for tile in self.tile_list: 161 | screen.blit(tile[0], tile[1]) 162 | pygame.draw.rect(screen, (255, 255, 255), tile[1], 2) 163 | 164 | 165 | 166 | class Enemy(pygame.sprite.Sprite): 167 | def __init__(self, x, y): 168 | pygame.sprite.Sprite.__init__(self) 169 | self.image = pygame.image.load('img/blob.png') 170 | self.rect = self.image.get_rect() 171 | self.rect.x = x 172 | self.rect.y = y 173 | self.move_direction = 1 174 | self.move_counter = 0 175 | 176 | def update(self): 177 | self.rect.x += self.move_direction 178 | self.move_counter += 1 179 | if abs(self.move_counter) > 50: 180 | self.move_direction *= -1 181 | self.move_counter *= -1 182 | 183 | 184 | 185 | 186 | 187 | 188 | world_data = [ 189 | [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 190 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 191 | [1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1], 192 | [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 1], 193 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 7, 0, 5, 0, 0, 0, 1], 194 | [1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1], 195 | [1, 7, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 196 | [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 197 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 1], 198 | [1, 0, 2, 0, 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 199 | [1, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 1], 200 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1], 201 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 202 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 2, 0, 1], 203 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 204 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 1], 205 | [1, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1], 206 | [1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 207 | [1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 208 | [1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 209 | ] 210 | 211 | 212 | 213 | player = Player(100, screen_height - 130) 214 | 215 | blob_group = pygame.sprite.Group() 216 | 217 | world = World(world_data) 218 | 219 | run = True 220 | while run: 221 | 222 | clock.tick(fps) 223 | 224 | screen.blit(bg_img, (0, 0)) 225 | screen.blit(sun_img, (100, 100)) 226 | 227 | world.draw() 228 | 229 | blob_group.update() 230 | blob_group.draw(screen) 231 | 232 | player.update() 233 | 234 | for event in pygame.event.get(): 235 | if event.type == pygame.QUIT: 236 | run = False 237 | 238 | pygame.display.update() 239 | 240 | pygame.quit() -------------------------------------------------------------------------------- /Part_6-Adding_Lava_and_Death/platformer_tut6.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | 4 | pygame.init() 5 | 6 | clock = pygame.time.Clock() 7 | fps = 60 8 | 9 | screen_width = 1000 10 | screen_height = 1000 11 | 12 | screen = pygame.display.set_mode((screen_width, screen_height)) 13 | pygame.display.set_caption('Platformer') 14 | 15 | #define game variables 16 | tile_size = 50 17 | game_over = 0 18 | 19 | 20 | #load images 21 | sun_img = pygame.image.load('img/sun.png') 22 | bg_img = pygame.image.load('img/sky.png') 23 | 24 | 25 | class Player(): 26 | def __init__(self, x, y): 27 | self.images_right = [] 28 | self.images_left = [] 29 | self.index = 0 30 | self.counter = 0 31 | for num in range(1, 5): 32 | img_right = pygame.image.load(f'img/guy{num}.png') 33 | img_right = pygame.transform.scale(img_right, (40, 80)) 34 | img_left = pygame.transform.flip(img_right, True, False) 35 | self.images_right.append(img_right) 36 | self.images_left.append(img_left) 37 | self.dead_image = pygame.image.load('img/ghost.png') 38 | self.image = self.images_right[self.index] 39 | self.rect = self.image.get_rect() 40 | self.rect.x = x 41 | self.rect.y = y 42 | self.width = self.image.get_width() 43 | self.height = self.image.get_height() 44 | self.vel_y = 0 45 | self.jumped = False 46 | self.direction = 0 47 | 48 | def update(self, game_over): 49 | dx = 0 50 | dy = 0 51 | walk_cooldown = 5 52 | 53 | if game_over == 0: 54 | #get keypresses 55 | key = pygame.key.get_pressed() 56 | if key[pygame.K_SPACE] and self.jumped == False: 57 | self.vel_y = -15 58 | self.jumped = True 59 | if key[pygame.K_SPACE] == False: 60 | self.jumped = False 61 | if key[pygame.K_LEFT]: 62 | dx -= 5 63 | self.counter += 1 64 | self.direction = -1 65 | if key[pygame.K_RIGHT]: 66 | dx += 5 67 | self.counter += 1 68 | self.direction = 1 69 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 70 | self.counter = 0 71 | self.index = 0 72 | if self.direction == 1: 73 | self.image = self.images_right[self.index] 74 | if self.direction == -1: 75 | self.image = self.images_left[self.index] 76 | 77 | 78 | #handle animation 79 | if self.counter > walk_cooldown: 80 | self.counter = 0 81 | self.index += 1 82 | if self.index >= len(self.images_right): 83 | self.index = 0 84 | if self.direction == 1: 85 | self.image = self.images_right[self.index] 86 | if self.direction == -1: 87 | self.image = self.images_left[self.index] 88 | 89 | 90 | #add gravity 91 | self.vel_y += 1 92 | if self.vel_y > 10: 93 | self.vel_y = 10 94 | dy += self.vel_y 95 | 96 | #check for collision 97 | for tile in world.tile_list: 98 | #check for collision in x direction 99 | if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): 100 | dx = 0 101 | #check for collision in y direction 102 | if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): 103 | #check if below the ground i.e. jumping 104 | if self.vel_y < 0: 105 | dy = tile[1].bottom - self.rect.top 106 | self.vel_y = 0 107 | #check if above the ground i.e. falling 108 | elif self.vel_y >= 0: 109 | dy = tile[1].top - self.rect.bottom 110 | self.vel_y = 0 111 | 112 | 113 | #check for collision with enemies 114 | if pygame.sprite.spritecollide(self, blob_group, False): 115 | game_over = -1 116 | 117 | #check for collision with lava 118 | if pygame.sprite.spritecollide(self, lava_group, False): 119 | game_over = -1 120 | 121 | #update player coordinates 122 | self.rect.x += dx 123 | self.rect.y += dy 124 | 125 | 126 | elif game_over == -1: 127 | self.image = self.dead_image 128 | if self.rect.y > 200: 129 | self.rect.y -= 5 130 | 131 | #draw player onto screen 132 | screen.blit(self.image, self.rect) 133 | pygame.draw.rect(screen, (255, 255, 255), self.rect, 2) 134 | 135 | return game_over 136 | 137 | 138 | class World(): 139 | def __init__(self, data): 140 | self.tile_list = [] 141 | 142 | #load images 143 | dirt_img = pygame.image.load('img/dirt.png') 144 | grass_img = pygame.image.load('img/grass.png') 145 | 146 | row_count = 0 147 | for row in data: 148 | col_count = 0 149 | for tile in row: 150 | if tile == 1: 151 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 152 | img_rect = img.get_rect() 153 | img_rect.x = col_count * tile_size 154 | img_rect.y = row_count * tile_size 155 | tile = (img, img_rect) 156 | self.tile_list.append(tile) 157 | if tile == 2: 158 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 159 | img_rect = img.get_rect() 160 | img_rect.x = col_count * tile_size 161 | img_rect.y = row_count * tile_size 162 | tile = (img, img_rect) 163 | self.tile_list.append(tile) 164 | if tile == 3: 165 | blob = Enemy(col_count * tile_size, row_count * tile_size + 15) 166 | blob_group.add(blob) 167 | if tile == 6: 168 | lava = Lava(col_count * tile_size, row_count * tile_size + (tile_size // 2)) 169 | lava_group.add(lava) 170 | 171 | col_count += 1 172 | row_count += 1 173 | 174 | def draw(self): 175 | for tile in self.tile_list: 176 | screen.blit(tile[0], tile[1]) 177 | pygame.draw.rect(screen, (255, 255, 255), tile[1], 2) 178 | 179 | 180 | 181 | class Enemy(pygame.sprite.Sprite): 182 | def __init__(self, x, y): 183 | pygame.sprite.Sprite.__init__(self) 184 | self.image = pygame.image.load('img/blob.png') 185 | self.rect = self.image.get_rect() 186 | self.rect.x = x 187 | self.rect.y = y 188 | self.move_direction = 1 189 | self.move_counter = 0 190 | 191 | def update(self): 192 | self.rect.x += self.move_direction 193 | self.move_counter += 1 194 | if abs(self.move_counter) > 50: 195 | self.move_direction *= -1 196 | self.move_counter *= -1 197 | 198 | 199 | class Lava(pygame.sprite.Sprite): 200 | def __init__(self, x, y): 201 | pygame.sprite.Sprite.__init__(self) 202 | img = pygame.image.load('img/lava.png') 203 | self.image = pygame.transform.scale(img, (tile_size, tile_size // 2)) 204 | self.rect = self.image.get_rect() 205 | self.rect.x = x 206 | self.rect.y = y 207 | 208 | 209 | 210 | 211 | world_data = [ 212 | [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 213 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 214 | [1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1], 215 | [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 1], 216 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 7, 0, 5, 0, 0, 0, 1], 217 | [1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1], 218 | [1, 7, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 219 | [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 220 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 1], 221 | [1, 0, 2, 0, 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 222 | [1, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 1], 223 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1], 224 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 225 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 2, 0, 1], 226 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 227 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 1], 228 | [1, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1], 229 | [1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 230 | [1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 231 | [1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 232 | ] 233 | 234 | 235 | 236 | player = Player(100, screen_height - 130) 237 | 238 | blob_group = pygame.sprite.Group() 239 | lava_group = pygame.sprite.Group() 240 | 241 | world = World(world_data) 242 | 243 | run = True 244 | while run: 245 | 246 | clock.tick(fps) 247 | 248 | screen.blit(bg_img, (0, 0)) 249 | screen.blit(sun_img, (100, 100)) 250 | 251 | world.draw() 252 | 253 | if game_over == 0: 254 | blob_group.update() 255 | 256 | blob_group.draw(screen) 257 | lava_group.draw(screen) 258 | 259 | game_over = player.update(game_over) 260 | 261 | for event in pygame.event.get(): 262 | if event.type == pygame.QUIT: 263 | run = False 264 | 265 | pygame.display.update() 266 | 267 | pygame.quit() -------------------------------------------------------------------------------- /Part_7-Add_Buttons_and_Reset_Game/platformer_tut7.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | 4 | pygame.init() 5 | 6 | clock = pygame.time.Clock() 7 | fps = 60 8 | 9 | screen_width = 1000 10 | screen_height = 1000 11 | 12 | screen = pygame.display.set_mode((screen_width, screen_height)) 13 | pygame.display.set_caption('Platformer') 14 | 15 | #define game variables 16 | tile_size = 50 17 | game_over = 0 18 | 19 | 20 | #load images 21 | sun_img = pygame.image.load('img/sun.png') 22 | bg_img = pygame.image.load('img/sky.png') 23 | restart_img = pygame.image.load('img/restart_btn.png') 24 | 25 | 26 | 27 | class Button(): 28 | def __init__(self, x, y, image): 29 | self.image = image 30 | self.rect = self.image.get_rect() 31 | self.rect.x = x 32 | self.rect.y = y 33 | self.clicked = False 34 | 35 | def draw(self): 36 | action = False 37 | 38 | #get mouse position 39 | pos = pygame.mouse.get_pos() 40 | 41 | #check mouseover and clicked conditions 42 | if self.rect.collidepoint(pos): 43 | if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False: 44 | action = True 45 | self.clicked = True 46 | 47 | if pygame.mouse.get_pressed()[0] == 0: 48 | self.clicked = False 49 | 50 | 51 | #draw button 52 | screen.blit(self.image, self.rect) 53 | 54 | return action 55 | 56 | 57 | class Player(): 58 | def __init__(self, x, y): 59 | self.reset(x, y) 60 | 61 | 62 | 63 | def update(self, game_over): 64 | dx = 0 65 | dy = 0 66 | walk_cooldown = 5 67 | 68 | if game_over == 0: 69 | #get keypresses 70 | key = pygame.key.get_pressed() 71 | if key[pygame.K_SPACE] and self.jumped == False and self.in_air == False: 72 | self.vel_y = -15 73 | self.jumped = True 74 | if key[pygame.K_SPACE] == False: 75 | self.jumped = False 76 | if key[pygame.K_LEFT]: 77 | dx -= 5 78 | self.counter += 1 79 | self.direction = -1 80 | if key[pygame.K_RIGHT]: 81 | dx += 5 82 | self.counter += 1 83 | self.direction = 1 84 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 85 | self.counter = 0 86 | self.index = 0 87 | if self.direction == 1: 88 | self.image = self.images_right[self.index] 89 | if self.direction == -1: 90 | self.image = self.images_left[self.index] 91 | 92 | 93 | #handle animation 94 | if self.counter > walk_cooldown: 95 | self.counter = 0 96 | self.index += 1 97 | if self.index >= len(self.images_right): 98 | self.index = 0 99 | if self.direction == 1: 100 | self.image = self.images_right[self.index] 101 | if self.direction == -1: 102 | self.image = self.images_left[self.index] 103 | 104 | 105 | #add gravity 106 | self.vel_y += 1 107 | if self.vel_y > 10: 108 | self.vel_y = 10 109 | dy += self.vel_y 110 | 111 | #check for collision 112 | self.in_air = True 113 | for tile in world.tile_list: 114 | #check for collision in x direction 115 | if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): 116 | dx = 0 117 | #check for collision in y direction 118 | if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): 119 | #check if below the ground i.e. jumping 120 | if self.vel_y < 0: 121 | dy = tile[1].bottom - self.rect.top 122 | self.vel_y = 0 123 | #check if above the ground i.e. falling 124 | elif self.vel_y >= 0: 125 | dy = tile[1].top - self.rect.bottom 126 | self.vel_y = 0 127 | self.in_air = False 128 | 129 | 130 | #check for collision with enemies 131 | if pygame.sprite.spritecollide(self, blob_group, False): 132 | game_over = -1 133 | 134 | #check for collision with lava 135 | if pygame.sprite.spritecollide(self, lava_group, False): 136 | game_over = -1 137 | 138 | #update player coordinates 139 | self.rect.x += dx 140 | self.rect.y += dy 141 | 142 | 143 | elif game_over == -1: 144 | self.image = self.dead_image 145 | if self.rect.y > 200: 146 | self.rect.y -= 5 147 | 148 | #draw player onto screen 149 | screen.blit(self.image, self.rect) 150 | pygame.draw.rect(screen, (255, 255, 255), self.rect, 2) 151 | 152 | return game_over 153 | 154 | 155 | def reset(self, x, y): 156 | self.images_right = [] 157 | self.images_left = [] 158 | self.index = 0 159 | self.counter = 0 160 | for num in range(1, 5): 161 | img_right = pygame.image.load(f'img/guy{num}.png') 162 | img_right = pygame.transform.scale(img_right, (40, 80)) 163 | img_left = pygame.transform.flip(img_right, True, False) 164 | self.images_right.append(img_right) 165 | self.images_left.append(img_left) 166 | self.dead_image = pygame.image.load('img/ghost.png') 167 | self.image = self.images_right[self.index] 168 | self.rect = self.image.get_rect() 169 | self.rect.x = x 170 | self.rect.y = y 171 | self.width = self.image.get_width() 172 | self.height = self.image.get_height() 173 | self.vel_y = 0 174 | self.jumped = False 175 | self.direction = 0 176 | self.in_air = True 177 | 178 | 179 | 180 | class World(): 181 | def __init__(self, data): 182 | self.tile_list = [] 183 | 184 | #load images 185 | dirt_img = pygame.image.load('img/dirt.png') 186 | grass_img = pygame.image.load('img/grass.png') 187 | 188 | row_count = 0 189 | for row in data: 190 | col_count = 0 191 | for tile in row: 192 | if tile == 1: 193 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 194 | img_rect = img.get_rect() 195 | img_rect.x = col_count * tile_size 196 | img_rect.y = row_count * tile_size 197 | tile = (img, img_rect) 198 | self.tile_list.append(tile) 199 | if tile == 2: 200 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 201 | img_rect = img.get_rect() 202 | img_rect.x = col_count * tile_size 203 | img_rect.y = row_count * tile_size 204 | tile = (img, img_rect) 205 | self.tile_list.append(tile) 206 | if tile == 3: 207 | blob = Enemy(col_count * tile_size, row_count * tile_size + 15) 208 | blob_group.add(blob) 209 | if tile == 6: 210 | lava = Lava(col_count * tile_size, row_count * tile_size + (tile_size // 2)) 211 | lava_group.add(lava) 212 | 213 | col_count += 1 214 | row_count += 1 215 | 216 | def draw(self): 217 | for tile in self.tile_list: 218 | screen.blit(tile[0], tile[1]) 219 | pygame.draw.rect(screen, (255, 255, 255), tile[1], 2) 220 | 221 | 222 | 223 | class Enemy(pygame.sprite.Sprite): 224 | def __init__(self, x, y): 225 | pygame.sprite.Sprite.__init__(self) 226 | self.image = pygame.image.load('img/blob.png') 227 | self.rect = self.image.get_rect() 228 | self.rect.x = x 229 | self.rect.y = y 230 | self.move_direction = 1 231 | self.move_counter = 0 232 | 233 | def update(self): 234 | self.rect.x += self.move_direction 235 | self.move_counter += 1 236 | if abs(self.move_counter) > 50: 237 | self.move_direction *= -1 238 | self.move_counter *= -1 239 | 240 | 241 | class Lava(pygame.sprite.Sprite): 242 | def __init__(self, x, y): 243 | pygame.sprite.Sprite.__init__(self) 244 | img = pygame.image.load('img/lava.png') 245 | self.image = pygame.transform.scale(img, (tile_size, tile_size // 2)) 246 | self.rect = self.image.get_rect() 247 | self.rect.x = x 248 | self.rect.y = y 249 | 250 | 251 | 252 | 253 | world_data = [ 254 | [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 255 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 256 | [1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1], 257 | [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 1], 258 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 7, 0, 5, 0, 0, 0, 1], 259 | [1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1], 260 | [1, 7, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 261 | [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 262 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 1], 263 | [1, 0, 2, 0, 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 264 | [1, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 1], 265 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1], 266 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 267 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 2, 0, 1], 268 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 269 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 1], 270 | [1, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1], 271 | [1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 272 | [1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 273 | [1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 274 | ] 275 | 276 | 277 | 278 | player = Player(100, screen_height - 130) 279 | 280 | blob_group = pygame.sprite.Group() 281 | lava_group = pygame.sprite.Group() 282 | 283 | world = World(world_data) 284 | 285 | #create buttons 286 | restart_button = Button(screen_width // 2 - 50, screen_height // 2 + 100, restart_img) 287 | 288 | run = True 289 | while run: 290 | 291 | clock.tick(fps) 292 | 293 | screen.blit(bg_img, (0, 0)) 294 | screen.blit(sun_img, (100, 100)) 295 | 296 | world.draw() 297 | 298 | if game_over == 0: 299 | blob_group.update() 300 | 301 | blob_group.draw(screen) 302 | lava_group.draw(screen) 303 | 304 | game_over = player.update(game_over) 305 | 306 | #if player has died 307 | if game_over == -1: 308 | if restart_button.draw(): 309 | player.reset(100, screen_height - 130) 310 | game_over = 0 311 | 312 | 313 | for event in pygame.event.get(): 314 | if event.type == pygame.QUIT: 315 | run = False 316 | 317 | pygame.display.update() 318 | 319 | pygame.quit() -------------------------------------------------------------------------------- /Part_8-Adding_a_Start_Menu/platformer_tut8.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | 4 | pygame.init() 5 | 6 | clock = pygame.time.Clock() 7 | fps = 60 8 | 9 | screen_width = 1000 10 | screen_height = 1000 11 | 12 | screen = pygame.display.set_mode((screen_width, screen_height)) 13 | pygame.display.set_caption('Platformer') 14 | 15 | #define game variables 16 | tile_size = 50 17 | game_over = 0 18 | main_menu = True 19 | 20 | 21 | #load images 22 | sun_img = pygame.image.load('img/sun.png') 23 | bg_img = pygame.image.load('img/sky.png') 24 | restart_img = pygame.image.load('img/restart_btn.png') 25 | start_img = pygame.image.load('img/start_btn.png') 26 | exit_img = pygame.image.load('img/exit_btn.png') 27 | 28 | 29 | 30 | class Button(): 31 | def __init__(self, x, y, image): 32 | self.image = image 33 | self.rect = self.image.get_rect() 34 | self.rect.x = x 35 | self.rect.y = y 36 | self.clicked = False 37 | 38 | def draw(self): 39 | action = False 40 | 41 | #get mouse position 42 | pos = pygame.mouse.get_pos() 43 | 44 | #check mouseover and clicked conditions 45 | if self.rect.collidepoint(pos): 46 | if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False: 47 | action = True 48 | self.clicked = True 49 | 50 | if pygame.mouse.get_pressed()[0] == 0: 51 | self.clicked = False 52 | 53 | 54 | #draw button 55 | screen.blit(self.image, self.rect) 56 | 57 | return action 58 | 59 | 60 | class Player(): 61 | def __init__(self, x, y): 62 | self.reset(x, y) 63 | 64 | 65 | 66 | def update(self, game_over): 67 | dx = 0 68 | dy = 0 69 | walk_cooldown = 5 70 | 71 | if game_over == 0: 72 | #get keypresses 73 | key = pygame.key.get_pressed() 74 | if key[pygame.K_SPACE] and self.jumped == False and self.in_air == False: 75 | self.vel_y = -15 76 | self.jumped = True 77 | if key[pygame.K_SPACE] == False: 78 | self.jumped = False 79 | if key[pygame.K_LEFT]: 80 | dx -= 5 81 | self.counter += 1 82 | self.direction = -1 83 | if key[pygame.K_RIGHT]: 84 | dx += 5 85 | self.counter += 1 86 | self.direction = 1 87 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 88 | self.counter = 0 89 | self.index = 0 90 | if self.direction == 1: 91 | self.image = self.images_right[self.index] 92 | if self.direction == -1: 93 | self.image = self.images_left[self.index] 94 | 95 | 96 | #handle animation 97 | if self.counter > walk_cooldown: 98 | self.counter = 0 99 | self.index += 1 100 | if self.index >= len(self.images_right): 101 | self.index = 0 102 | if self.direction == 1: 103 | self.image = self.images_right[self.index] 104 | if self.direction == -1: 105 | self.image = self.images_left[self.index] 106 | 107 | 108 | #add gravity 109 | self.vel_y += 1 110 | if self.vel_y > 10: 111 | self.vel_y = 10 112 | dy += self.vel_y 113 | 114 | #check for collision 115 | self.in_air = True 116 | for tile in world.tile_list: 117 | #check for collision in x direction 118 | if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): 119 | dx = 0 120 | #check for collision in y direction 121 | if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): 122 | #check if below the ground i.e. jumping 123 | if self.vel_y < 0: 124 | dy = tile[1].bottom - self.rect.top 125 | self.vel_y = 0 126 | #check if above the ground i.e. falling 127 | elif self.vel_y >= 0: 128 | dy = tile[1].top - self.rect.bottom 129 | self.vel_y = 0 130 | self.in_air = False 131 | 132 | 133 | #check for collision with enemies 134 | if pygame.sprite.spritecollide(self, blob_group, False): 135 | game_over = -1 136 | 137 | #check for collision with lava 138 | if pygame.sprite.spritecollide(self, lava_group, False): 139 | game_over = -1 140 | 141 | #update player coordinates 142 | self.rect.x += dx 143 | self.rect.y += dy 144 | 145 | 146 | elif game_over == -1: 147 | self.image = self.dead_image 148 | if self.rect.y > 200: 149 | self.rect.y -= 5 150 | 151 | #draw player onto screen 152 | screen.blit(self.image, self.rect) 153 | pygame.draw.rect(screen, (255, 255, 255), self.rect, 2) 154 | 155 | return game_over 156 | 157 | 158 | def reset(self, x, y): 159 | self.images_right = [] 160 | self.images_left = [] 161 | self.index = 0 162 | self.counter = 0 163 | for num in range(1, 5): 164 | img_right = pygame.image.load(f'img/guy{num}.png') 165 | img_right = pygame.transform.scale(img_right, (40, 80)) 166 | img_left = pygame.transform.flip(img_right, True, False) 167 | self.images_right.append(img_right) 168 | self.images_left.append(img_left) 169 | self.dead_image = pygame.image.load('img/ghost.png') 170 | self.image = self.images_right[self.index] 171 | self.rect = self.image.get_rect() 172 | self.rect.x = x 173 | self.rect.y = y 174 | self.width = self.image.get_width() 175 | self.height = self.image.get_height() 176 | self.vel_y = 0 177 | self.jumped = False 178 | self.direction = 0 179 | self.in_air = True 180 | 181 | 182 | 183 | class World(): 184 | def __init__(self, data): 185 | self.tile_list = [] 186 | 187 | #load images 188 | dirt_img = pygame.image.load('img/dirt.png') 189 | grass_img = pygame.image.load('img/grass.png') 190 | 191 | row_count = 0 192 | for row in data: 193 | col_count = 0 194 | for tile in row: 195 | if tile == 1: 196 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 197 | img_rect = img.get_rect() 198 | img_rect.x = col_count * tile_size 199 | img_rect.y = row_count * tile_size 200 | tile = (img, img_rect) 201 | self.tile_list.append(tile) 202 | if tile == 2: 203 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 204 | img_rect = img.get_rect() 205 | img_rect.x = col_count * tile_size 206 | img_rect.y = row_count * tile_size 207 | tile = (img, img_rect) 208 | self.tile_list.append(tile) 209 | if tile == 3: 210 | blob = Enemy(col_count * tile_size, row_count * tile_size + 15) 211 | blob_group.add(blob) 212 | if tile == 6: 213 | lava = Lava(col_count * tile_size, row_count * tile_size + (tile_size // 2)) 214 | lava_group.add(lava) 215 | 216 | col_count += 1 217 | row_count += 1 218 | 219 | def draw(self): 220 | for tile in self.tile_list: 221 | screen.blit(tile[0], tile[1]) 222 | pygame.draw.rect(screen, (255, 255, 255), tile[1], 2) 223 | 224 | 225 | 226 | class Enemy(pygame.sprite.Sprite): 227 | def __init__(self, x, y): 228 | pygame.sprite.Sprite.__init__(self) 229 | self.image = pygame.image.load('img/blob.png') 230 | self.rect = self.image.get_rect() 231 | self.rect.x = x 232 | self.rect.y = y 233 | self.move_direction = 1 234 | self.move_counter = 0 235 | 236 | def update(self): 237 | self.rect.x += self.move_direction 238 | self.move_counter += 1 239 | if abs(self.move_counter) > 50: 240 | self.move_direction *= -1 241 | self.move_counter *= -1 242 | 243 | 244 | class Lava(pygame.sprite.Sprite): 245 | def __init__(self, x, y): 246 | pygame.sprite.Sprite.__init__(self) 247 | img = pygame.image.load('img/lava.png') 248 | self.image = pygame.transform.scale(img, (tile_size, tile_size // 2)) 249 | self.rect = self.image.get_rect() 250 | self.rect.x = x 251 | self.rect.y = y 252 | 253 | 254 | 255 | 256 | world_data = [ 257 | [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 258 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 259 | [1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1], 260 | [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 1], 261 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 7, 0, 5, 0, 0, 0, 1], 262 | [1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1], 263 | [1, 7, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 264 | [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 265 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 1], 266 | [1, 0, 2, 0, 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 267 | [1, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 1], 268 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1], 269 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 270 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 2, 0, 1], 271 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 272 | [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 1], 273 | [1, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1], 274 | [1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 275 | [1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 276 | [1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 277 | ] 278 | 279 | 280 | 281 | player = Player(100, screen_height - 130) 282 | 283 | blob_group = pygame.sprite.Group() 284 | lava_group = pygame.sprite.Group() 285 | 286 | world = World(world_data) 287 | 288 | #create buttons 289 | restart_button = Button(screen_width // 2 - 50, screen_height // 2 + 100, restart_img) 290 | start_button = Button(screen_width // 2 - 350, screen_height // 2, start_img) 291 | exit_button = Button(screen_width // 2 + 150, screen_height // 2, exit_img) 292 | 293 | 294 | run = True 295 | while run: 296 | 297 | clock.tick(fps) 298 | 299 | screen.blit(bg_img, (0, 0)) 300 | screen.blit(sun_img, (100, 100)) 301 | 302 | if main_menu == True: 303 | if exit_button.draw(): 304 | run = False 305 | if start_button.draw(): 306 | main_menu = False 307 | else: 308 | world.draw() 309 | 310 | if game_over == 0: 311 | blob_group.update() 312 | 313 | blob_group.draw(screen) 314 | lava_group.draw(screen) 315 | 316 | game_over = player.update(game_over) 317 | 318 | #if player has died 319 | if game_over == -1: 320 | if restart_button.draw(): 321 | player.reset(100, screen_height - 130) 322 | game_over = 0 323 | 324 | 325 | for event in pygame.event.get(): 326 | if event.type == pygame.QUIT: 327 | run = False 328 | 329 | pygame.display.update() 330 | 331 | pygame.quit() -------------------------------------------------------------------------------- /Part_9-Multiple_Levels_and_Loading_Data/platformer_tut9.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | import pickle 4 | from os import path 5 | 6 | pygame.init() 7 | 8 | clock = pygame.time.Clock() 9 | fps = 60 10 | 11 | screen_width = 1000 12 | screen_height = 1000 13 | 14 | screen = pygame.display.set_mode((screen_width, screen_height)) 15 | pygame.display.set_caption('Platformer') 16 | 17 | #define game variables 18 | tile_size = 50 19 | game_over = 0 20 | main_menu = True 21 | level = 0 22 | max_levels = 7 23 | 24 | 25 | #load images 26 | sun_img = pygame.image.load('img/sun.png') 27 | bg_img = pygame.image.load('img/sky.png') 28 | restart_img = pygame.image.load('img/restart_btn.png') 29 | start_img = pygame.image.load('img/start_btn.png') 30 | exit_img = pygame.image.load('img/exit_btn.png') 31 | 32 | 33 | #function to reset level 34 | def reset_level(level): 35 | player.reset(100, screen_height - 130) 36 | blob_group.empty() 37 | lava_group.empty() 38 | exit_group.empty() 39 | 40 | #load in level data and create world 41 | if path.exists(f'level{level}_data'): 42 | pickle_in = open(f'level{level}_data', 'rb') 43 | world_data = pickle.load(pickle_in) 44 | world = World(world_data) 45 | 46 | return world 47 | 48 | 49 | class Button(): 50 | def __init__(self, x, y, image): 51 | self.image = image 52 | self.rect = self.image.get_rect() 53 | self.rect.x = x 54 | self.rect.y = y 55 | self.clicked = False 56 | 57 | def draw(self): 58 | action = False 59 | 60 | #get mouse position 61 | pos = pygame.mouse.get_pos() 62 | 63 | #check mouseover and clicked conditions 64 | if self.rect.collidepoint(pos): 65 | if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False: 66 | action = True 67 | self.clicked = True 68 | 69 | if pygame.mouse.get_pressed()[0] == 0: 70 | self.clicked = False 71 | 72 | 73 | #draw button 74 | screen.blit(self.image, self.rect) 75 | 76 | return action 77 | 78 | 79 | class Player(): 80 | def __init__(self, x, y): 81 | self.reset(x, y) 82 | 83 | 84 | 85 | def update(self, game_over): 86 | dx = 0 87 | dy = 0 88 | walk_cooldown = 5 89 | 90 | if game_over == 0: 91 | #get keypresses 92 | key = pygame.key.get_pressed() 93 | if key[pygame.K_SPACE] and self.jumped == False and self.in_air == False: 94 | self.vel_y = -15 95 | self.jumped = True 96 | if key[pygame.K_SPACE] == False: 97 | self.jumped = False 98 | if key[pygame.K_LEFT]: 99 | dx -= 5 100 | self.counter += 1 101 | self.direction = -1 102 | if key[pygame.K_RIGHT]: 103 | dx += 5 104 | self.counter += 1 105 | self.direction = 1 106 | if key[pygame.K_LEFT] == False and key[pygame.K_RIGHT] == False: 107 | self.counter = 0 108 | self.index = 0 109 | if self.direction == 1: 110 | self.image = self.images_right[self.index] 111 | if self.direction == -1: 112 | self.image = self.images_left[self.index] 113 | 114 | 115 | #handle animation 116 | if self.counter > walk_cooldown: 117 | self.counter = 0 118 | self.index += 1 119 | if self.index >= len(self.images_right): 120 | self.index = 0 121 | if self.direction == 1: 122 | self.image = self.images_right[self.index] 123 | if self.direction == -1: 124 | self.image = self.images_left[self.index] 125 | 126 | 127 | #add gravity 128 | self.vel_y += 1 129 | if self.vel_y > 10: 130 | self.vel_y = 10 131 | dy += self.vel_y 132 | 133 | #check for collision 134 | self.in_air = True 135 | for tile in world.tile_list: 136 | #check for collision in x direction 137 | if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): 138 | dx = 0 139 | #check for collision in y direction 140 | if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): 141 | #check if below the ground i.e. jumping 142 | if self.vel_y < 0: 143 | dy = tile[1].bottom - self.rect.top 144 | self.vel_y = 0 145 | #check if above the ground i.e. falling 146 | elif self.vel_y >= 0: 147 | dy = tile[1].top - self.rect.bottom 148 | self.vel_y = 0 149 | self.in_air = False 150 | 151 | 152 | #check for collision with enemies 153 | if pygame.sprite.spritecollide(self, blob_group, False): 154 | game_over = -1 155 | 156 | #check for collision with lava 157 | if pygame.sprite.spritecollide(self, lava_group, False): 158 | game_over = -1 159 | 160 | #check for collision with exit 161 | if pygame.sprite.spritecollide(self, exit_group, False): 162 | game_over = 1 163 | 164 | 165 | #update player coordinates 166 | self.rect.x += dx 167 | self.rect.y += dy 168 | 169 | 170 | elif game_over == -1: 171 | self.image = self.dead_image 172 | if self.rect.y > 200: 173 | self.rect.y -= 5 174 | 175 | #draw player onto screen 176 | screen.blit(self.image, self.rect) 177 | pygame.draw.rect(screen, (255, 255, 255), self.rect, 2) 178 | 179 | return game_over 180 | 181 | 182 | def reset(self, x, y): 183 | self.images_right = [] 184 | self.images_left = [] 185 | self.index = 0 186 | self.counter = 0 187 | for num in range(1, 5): 188 | img_right = pygame.image.load(f'img/guy{num}.png') 189 | img_right = pygame.transform.scale(img_right, (40, 80)) 190 | img_left = pygame.transform.flip(img_right, True, False) 191 | self.images_right.append(img_right) 192 | self.images_left.append(img_left) 193 | self.dead_image = pygame.image.load('img/ghost.png') 194 | self.image = self.images_right[self.index] 195 | self.rect = self.image.get_rect() 196 | self.rect.x = x 197 | self.rect.y = y 198 | self.width = self.image.get_width() 199 | self.height = self.image.get_height() 200 | self.vel_y = 0 201 | self.jumped = False 202 | self.direction = 0 203 | self.in_air = True 204 | 205 | 206 | 207 | class World(): 208 | def __init__(self, data): 209 | self.tile_list = [] 210 | 211 | #load images 212 | dirt_img = pygame.image.load('img/dirt.png') 213 | grass_img = pygame.image.load('img/grass.png') 214 | 215 | row_count = 0 216 | for row in data: 217 | col_count = 0 218 | for tile in row: 219 | if tile == 1: 220 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 221 | img_rect = img.get_rect() 222 | img_rect.x = col_count * tile_size 223 | img_rect.y = row_count * tile_size 224 | tile = (img, img_rect) 225 | self.tile_list.append(tile) 226 | if tile == 2: 227 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 228 | img_rect = img.get_rect() 229 | img_rect.x = col_count * tile_size 230 | img_rect.y = row_count * tile_size 231 | tile = (img, img_rect) 232 | self.tile_list.append(tile) 233 | if tile == 3: 234 | blob = Enemy(col_count * tile_size, row_count * tile_size + 15) 235 | blob_group.add(blob) 236 | if tile == 6: 237 | lava = Lava(col_count * tile_size, row_count * tile_size + (tile_size // 2)) 238 | lava_group.add(lava) 239 | if tile == 8: 240 | exit = Exit(col_count * tile_size, row_count * tile_size - (tile_size // 2)) 241 | exit_group.add(exit) 242 | col_count += 1 243 | row_count += 1 244 | 245 | 246 | def draw(self): 247 | for tile in self.tile_list: 248 | screen.blit(tile[0], tile[1]) 249 | pygame.draw.rect(screen, (255, 255, 255), tile[1], 2) 250 | 251 | 252 | 253 | class Enemy(pygame.sprite.Sprite): 254 | def __init__(self, x, y): 255 | pygame.sprite.Sprite.__init__(self) 256 | self.image = pygame.image.load('img/blob.png') 257 | self.rect = self.image.get_rect() 258 | self.rect.x = x 259 | self.rect.y = y 260 | self.move_direction = 1 261 | self.move_counter = 0 262 | 263 | def update(self): 264 | self.rect.x += self.move_direction 265 | self.move_counter += 1 266 | if abs(self.move_counter) > 50: 267 | self.move_direction *= -1 268 | self.move_counter *= -1 269 | 270 | 271 | class Lava(pygame.sprite.Sprite): 272 | def __init__(self, x, y): 273 | pygame.sprite.Sprite.__init__(self) 274 | img = pygame.image.load('img/lava.png') 275 | self.image = pygame.transform.scale(img, (tile_size, tile_size // 2)) 276 | self.rect = self.image.get_rect() 277 | self.rect.x = x 278 | self.rect.y = y 279 | 280 | 281 | class Exit(pygame.sprite.Sprite): 282 | def __init__(self, x, y): 283 | pygame.sprite.Sprite.__init__(self) 284 | img = pygame.image.load('img/exit.png') 285 | self.image = pygame.transform.scale(img, (tile_size, int(tile_size * 1.5))) 286 | self.rect = self.image.get_rect() 287 | self.rect.x = x 288 | self.rect.y = y 289 | 290 | 291 | 292 | player = Player(100, screen_height - 130) 293 | 294 | blob_group = pygame.sprite.Group() 295 | lava_group = pygame.sprite.Group() 296 | exit_group = pygame.sprite.Group() 297 | 298 | 299 | #load in level data and create world 300 | if path.exists(f'level{level}_data'): 301 | pickle_in = open(f'level{level}_data', 'rb') 302 | world_data = pickle.load(pickle_in) 303 | world = World(world_data) 304 | 305 | 306 | #create buttons 307 | restart_button = Button(screen_width // 2 - 50, screen_height // 2 + 100, restart_img) 308 | start_button = Button(screen_width // 2 - 350, screen_height // 2, start_img) 309 | exit_button = Button(screen_width // 2 + 150, screen_height // 2, exit_img) 310 | 311 | 312 | run = True 313 | while run: 314 | 315 | clock.tick(fps) 316 | 317 | screen.blit(bg_img, (0, 0)) 318 | screen.blit(sun_img, (100, 100)) 319 | 320 | if main_menu == True: 321 | if exit_button.draw(): 322 | run = False 323 | if start_button.draw(): 324 | main_menu = False 325 | else: 326 | world.draw() 327 | 328 | if game_over == 0: 329 | blob_group.update() 330 | 331 | blob_group.draw(screen) 332 | lava_group.draw(screen) 333 | exit_group.draw(screen) 334 | 335 | game_over = player.update(game_over) 336 | 337 | #if player has died 338 | if game_over == -1: 339 | if restart_button.draw(): 340 | world_data = [] 341 | world = reset_level(level) 342 | game_over = 0 343 | 344 | #if player has completed the level 345 | if game_over == 1: 346 | #reset game and go to next level 347 | level += 1 348 | if level <= max_levels: 349 | #reset level 350 | world_data = [] 351 | world = reset_level(level) 352 | game_over = 0 353 | else: 354 | if restart_button.draw(): 355 | level = 1 356 | #reset level 357 | world_data = [] 358 | world = reset_level(level) 359 | game_over = 0 360 | 361 | 362 | 363 | for event in pygame.event.get(): 364 | if event.type == pygame.QUIT: 365 | run = False 366 | 367 | pygame.display.update() 368 | 369 | pygame.quit() -------------------------------------------------------------------------------- /Platformer.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/Platformer.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project Title: 2 | 3 | Tile Based Platformer Game 4 | 5 | ## 1. Project Description: 6 | 7 | This project is a Tile Based Platformer Game. It has been developed in Python programming language, using the Pygame library. 8 | 9 | ## 2. Tech Stack: 10 | 11 | - Python 3 12 | - Pygame 13 | 14 | URL: [https://www.pygame.org/news ](https://www.pygame.org/news) 15 | 16 | ## 3. Installing: 17 | 18 | 1. Clone the git repo 19 | 20 | ``` 21 | https://github.com/russs123/Platformer.git 22 | ``` 23 | 24 | 2. Open project folder 25 | 26 | 3. Explore 27 | 28 | 4. Open platformer_tut13.py and run 29 | 30 | 5. Play the game 31 | 32 | Enjoy 😎 33 | 34 | 35 | ## 4. Demo: 36 | 37 | https://www.youtube.com/watch?v=v6rjaPzngLI 38 | 39 | ## 5. Contributing: 40 | 41 | Pull requests are welcome. 42 | 43 | For major changes, please open an issue first to discuss what you would like to change with project owner (Coding With Russ). 44 | 45 | 46 | ## 6. Created By: 47 | 48 | Name: Coding With Russ 49 | 50 | Project Name: PyGame Tile Based Platformer Game Beginner Tutorial in Python 51 | 52 | Youtube: https://www.youtube.com/playlist?list=PLjcN1EyupaQnHM1I9SmiXfbT6aG4ezUvu 53 | 54 | Github: https://github.com/russs123/Platformer 55 | 56 | 57 | ## 7. Licence: 58 | 59 | MIT License 60 | 61 | Copyright (c) 2022 russs123 62 | 63 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 64 | 65 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 66 | 67 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 68 | 69 | -------------------------------------------------------------------------------- /img/blob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/blob.png -------------------------------------------------------------------------------- /img/coin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/coin.png -------------------------------------------------------------------------------- /img/coin.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/coin.wav -------------------------------------------------------------------------------- /img/dirt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/dirt.png -------------------------------------------------------------------------------- /img/exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/exit.png -------------------------------------------------------------------------------- /img/exit_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/exit_btn.png -------------------------------------------------------------------------------- /img/game_over.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/game_over.wav -------------------------------------------------------------------------------- /img/ghost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/ghost.png -------------------------------------------------------------------------------- /img/grass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/grass.png -------------------------------------------------------------------------------- /img/guy1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/guy1.png -------------------------------------------------------------------------------- /img/guy2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/guy2.png -------------------------------------------------------------------------------- /img/guy3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/guy3.png -------------------------------------------------------------------------------- /img/guy4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/guy4.png -------------------------------------------------------------------------------- /img/jump.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/jump.wav -------------------------------------------------------------------------------- /img/lava.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/lava.png -------------------------------------------------------------------------------- /img/load_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/load_btn.png -------------------------------------------------------------------------------- /img/music.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/music.wav -------------------------------------------------------------------------------- /img/platform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/platform.png -------------------------------------------------------------------------------- /img/platform_x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/platform_x.png -------------------------------------------------------------------------------- /img/platform_y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/platform_y.png -------------------------------------------------------------------------------- /img/restart_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/restart_btn.png -------------------------------------------------------------------------------- /img/save_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/save_btn.png -------------------------------------------------------------------------------- /img/sky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/sky.png -------------------------------------------------------------------------------- /img/start_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/start_btn.png -------------------------------------------------------------------------------- /img/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/img/sun.png -------------------------------------------------------------------------------- /level0_data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/level0_data -------------------------------------------------------------------------------- /level1_data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/level1_data -------------------------------------------------------------------------------- /level2_data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/level2_data -------------------------------------------------------------------------------- /level3_data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/level3_data -------------------------------------------------------------------------------- /level4_data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/level4_data -------------------------------------------------------------------------------- /level5_data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/level5_data -------------------------------------------------------------------------------- /level6_data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/level6_data -------------------------------------------------------------------------------- /level7_data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/russs123/Platformer/96f0fc1ad4d515d2f8c8d58719ce3f9c88931ed8/level7_data -------------------------------------------------------------------------------- /level_editor.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pickle 3 | from os import path 4 | 5 | 6 | pygame.init() 7 | 8 | clock = pygame.time.Clock() 9 | fps = 60 10 | 11 | #game window 12 | tile_size = 50 13 | cols = 20 14 | margin = 100 15 | screen_width = tile_size * cols 16 | screen_height = (tile_size * cols) + margin 17 | 18 | screen = pygame.display.set_mode((screen_width, screen_height)) 19 | pygame.display.set_caption('Level Editor') 20 | 21 | 22 | #load images 23 | sun_img = pygame.image.load('img/sun.png') 24 | sun_img = pygame.transform.scale(sun_img, (tile_size, tile_size)) 25 | bg_img = pygame.image.load('img/sky.png') 26 | bg_img = pygame.transform.scale(bg_img, (screen_width, screen_height - margin)) 27 | dirt_img = pygame.image.load('img/dirt.png') 28 | grass_img = pygame.image.load('img/grass.png') 29 | blob_img = pygame.image.load('img/blob.png') 30 | platform_x_img = pygame.image.load('img/platform_x.png') 31 | platform_y_img = pygame.image.load('img/platform_y.png') 32 | lava_img = pygame.image.load('img/lava.png') 33 | coin_img = pygame.image.load('img/coin.png') 34 | exit_img = pygame.image.load('img/exit.png') 35 | save_img = pygame.image.load('img/save_btn.png') 36 | load_img = pygame.image.load('img/load_btn.png') 37 | 38 | 39 | #define game variables 40 | clicked = False 41 | level = 1 42 | 43 | #define colours 44 | white = (255, 255, 255) 45 | green = (144, 201, 120) 46 | 47 | font = pygame.font.SysFont('Futura', 24) 48 | 49 | #create empty tile list 50 | world_data = [] 51 | for row in range(20): 52 | r = [0] * 20 53 | world_data.append(r) 54 | 55 | #create boundary 56 | for tile in range(0, 20): 57 | world_data[19][tile] = 2 58 | world_data[0][tile] = 1 59 | world_data[tile][0] = 1 60 | world_data[tile][19] = 1 61 | 62 | #function for outputting text onto the screen 63 | def draw_text(text, font, text_col, x, y): 64 | img = font.render(text, True, text_col) 65 | screen.blit(img, (x, y)) 66 | 67 | def draw_grid(): 68 | for c in range(21): 69 | #vertical lines 70 | pygame.draw.line(screen, white, (c * tile_size, 0), (c * tile_size, screen_height - margin)) 71 | #horizontal lines 72 | pygame.draw.line(screen, white, (0, c * tile_size), (screen_width, c * tile_size)) 73 | 74 | 75 | def draw_world(): 76 | for row in range(20): 77 | for col in range(20): 78 | if world_data[row][col] > 0: 79 | if world_data[row][col] == 1: 80 | #dirt blocks 81 | img = pygame.transform.scale(dirt_img, (tile_size, tile_size)) 82 | screen.blit(img, (col * tile_size, row * tile_size)) 83 | if world_data[row][col] == 2: 84 | #grass blocks 85 | img = pygame.transform.scale(grass_img, (tile_size, tile_size)) 86 | screen.blit(img, (col * tile_size, row * tile_size)) 87 | if world_data[row][col] == 3: 88 | #enemy blocks 89 | img = pygame.transform.scale(blob_img, (tile_size, int(tile_size * 0.75))) 90 | screen.blit(img, (col * tile_size, row * tile_size + (tile_size * 0.25))) 91 | if world_data[row][col] == 4: 92 | #horizontally moving platform 93 | img = pygame.transform.scale(platform_x_img, (tile_size, tile_size // 2)) 94 | screen.blit(img, (col * tile_size, row * tile_size)) 95 | if world_data[row][col] == 5: 96 | #vertically moving platform 97 | img = pygame.transform.scale(platform_y_img, (tile_size, tile_size // 2)) 98 | screen.blit(img, (col * tile_size, row * tile_size)) 99 | if world_data[row][col] == 6: 100 | #lava 101 | img = pygame.transform.scale(lava_img, (tile_size, tile_size // 2)) 102 | screen.blit(img, (col * tile_size, row * tile_size + (tile_size // 2))) 103 | if world_data[row][col] == 7: 104 | #coin 105 | img = pygame.transform.scale(coin_img, (tile_size // 2, tile_size // 2)) 106 | screen.blit(img, (col * tile_size + (tile_size // 4), row * tile_size + (tile_size // 4))) 107 | if world_data[row][col] == 8: 108 | #exit 109 | img = pygame.transform.scale(exit_img, (tile_size, int(tile_size * 1.5))) 110 | screen.blit(img, (col * tile_size, row * tile_size - (tile_size // 2))) 111 | 112 | 113 | 114 | class Button(): 115 | def __init__(self, x, y, image): 116 | self.image = image 117 | self.rect = self.image.get_rect() 118 | self.rect.topleft = (x, y) 119 | self.clicked = False 120 | 121 | def draw(self): 122 | action = False 123 | 124 | #get mouse position 125 | pos = pygame.mouse.get_pos() 126 | 127 | #check mouseover and clicked conditions 128 | if self.rect.collidepoint(pos): 129 | if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False: 130 | action = True 131 | self.clicked = True 132 | 133 | if pygame.mouse.get_pressed()[0] == 0: 134 | self.clicked = False 135 | 136 | #draw button 137 | screen.blit(self.image, (self.rect.x, self.rect.y)) 138 | 139 | return action 140 | 141 | #create load and save buttons 142 | save_button = Button(screen_width // 2 - 150, screen_height - 80, save_img) 143 | load_button = Button(screen_width // 2 + 50, screen_height - 80, load_img) 144 | 145 | #main game loop 146 | run = True 147 | while run: 148 | 149 | clock.tick(fps) 150 | 151 | #draw background 152 | screen.fill(green) 153 | screen.blit(bg_img, (0, 0)) 154 | screen.blit(sun_img, (tile_size * 2, tile_size * 2)) 155 | 156 | #load and save level 157 | if save_button.draw(): 158 | #save level data 159 | pickle_out = open(f'level{level}_data', 'wb') 160 | pickle.dump(world_data, pickle_out) 161 | pickle_out.close() 162 | if load_button.draw(): 163 | #load in level data 164 | if path.exists(f'level{level}_data'): 165 | pickle_in = open(f'level{level}_data', 'rb') 166 | world_data = pickle.load(pickle_in) 167 | 168 | 169 | #show the grid and draw the level tiles 170 | draw_grid() 171 | draw_world() 172 | 173 | 174 | #text showing current level 175 | draw_text(f'Level: {level}', font, white, tile_size, screen_height - 60) 176 | draw_text('Press UP or DOWN to change level', font, white, tile_size, screen_height - 40) 177 | 178 | #event handler 179 | for event in pygame.event.get(): 180 | #quit game 181 | if event.type == pygame.QUIT: 182 | run = False 183 | #mouseclicks to change tiles 184 | if event.type == pygame.MOUSEBUTTONDOWN and clicked == False: 185 | clicked = True 186 | pos = pygame.mouse.get_pos() 187 | x = pos[0] // tile_size 188 | y = pos[1] // tile_size 189 | #check that the coordinates are within the tile area 190 | if x < 20 and y < 20: 191 | #update tile value 192 | if pygame.mouse.get_pressed()[0] == 1: 193 | world_data[y][x] += 1 194 | if world_data[y][x] > 8: 195 | world_data[y][x] = 0 196 | elif pygame.mouse.get_pressed()[2] == 1: 197 | world_data[y][x] -= 1 198 | if world_data[y][x] < 0: 199 | world_data[y][x] = 8 200 | if event.type == pygame.MOUSEBUTTONUP: 201 | clicked = False 202 | #up and down key presses to change level number 203 | if event.type == pygame.KEYDOWN: 204 | if event.key == pygame.K_UP: 205 | level += 1 206 | elif event.key == pygame.K_DOWN and level > 1: 207 | level -= 1 208 | 209 | #update game display window 210 | pygame.display.update() 211 | 212 | pygame.quit() --------------------------------------------------------------------------------