Guest User

Untitled

a guest
Mar 13th, 2021
160
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # KidsCanCode - Game Development with Pygame video series
  2. # Tile-based game - Part 22
  3. # Game Over
  4. # Video link: https://youtu.be/DZYY9hCOxLQ
  5. import pygame as pg
  6. import sys
  7. from random import choice, random
  8. from os import path
  9. from settings import *
  10. from sprites import *
  11. from tilemap import *
  12.  
  13. # HUD functions
  14. def draw_player_health(surf, x, y, pct):
  15.     if pct < 0:
  16.         pct = 0
  17.     BAR_LENGTH = 100
  18.     BAR_HEIGHT = 20
  19.     fill = pct * BAR_LENGTH
  20.     outline_rect = pg.Rect(x, y, BAR_LENGTH, BAR_HEIGHT)
  21.     fill_rect = pg.Rect(x, y, fill, BAR_HEIGHT)
  22.     if pct > 0.6:
  23.         col = GREEN
  24.     elif pct > 0.3:
  25.         col = YELLOW
  26.     else:
  27.         col = RED
  28.     pg.draw.rect(surf, col, fill_rect)
  29.     pg.draw.rect(surf, WHITE, outline_rect, 2)
  30.  
  31. class Game:
  32.     def __init__(self):
  33.         pg.mixer.pre_init(44100, -16, 4, 2048)
  34.         pg.init()
  35.         self.screen = pg.display.set_mode((WIDTH, HEIGHT))
  36.         pg.display.set_caption(TITLE)
  37.         self.clock = pg.time.Clock()
  38.         self.load_data()
  39.  
  40.     def draw_text(self, text, font_name, size, color, x, y, align="nw"):
  41.         font = pg.font.Font(font_name, size)
  42.         text_surface = font.render(text, True, color)
  43.         text_rect = text_surface.get_rect()
  44.         if align == "nw":
  45.             text_rect.topleft = (x, y)
  46.         if align == "ne":
  47.             text_rect.topright = (x, y)
  48.         if align == "sw":
  49.             text_rect.bottomleft = (x, y)
  50.         if align == "se":
  51.             text_rect.bottomright = (x, y)
  52.         if align == "n":
  53.             text_rect.midtop = (x, y)
  54.         if align == "s":
  55.             text_rect.midbottom = (x, y)
  56.         if align == "e":
  57.             text_rect.midright = (x, y)
  58.         if align == "w":
  59.             text_rect.midleft = (x, y)
  60.         if align == "center":
  61.             text_rect.center = (x, y)
  62.         self.screen.blit(text_surface, text_rect)
  63.  
  64.     def load_data(self):
  65.         game_folder = path.dirname(__file__)
  66.         font_folder = path.join(game_folder, 'fonts')
  67.         img_folder = path.join(game_folder, 'img')
  68.         weapon_folder = path.join(img_folder, 'weapons')
  69.         item_folder = path.join(img_folder, 'items')
  70.         potion_folder = path.join(item_folder, 'potions')
  71.         enemy_folder = path.join(img_folder, 'enemies')
  72.         snd_folder = path.join(game_folder, 'snd')
  73.         music_folder = path.join(game_folder, 'music')
  74.         self.map_folder = path.join(game_folder, 'maps')
  75.         self.title_font = path.join(font_folder, 'AlegreyaSC-Italic.ttf')
  76.         self.hud_font = path.join(font_folder, 'AlegreyaSC-Italic.ttf')
  77.         self.dim_screen = pg.Surface(self.screen.get_size()).convert_alpha()
  78.         self.dim_screen.fill((0, 0, 0, 180))
  79.         self.player_img = pg.image.load(path.join(img_folder, PLAYER_IMG)).convert_alpha()
  80.         self.player_spritesheet = Spritesheet(path.join(img_folder, PLAYER_SPRITESHEET))
  81.         self.bullet_images = {}
  82.         self.bullet_images['lg'] = pg.image.load(path.join(weapon_folder, BULLET_IMG)).convert_alpha()
  83.         self.bullet_images['sm'] = pg.transform.scale(self.bullet_images['lg'], (10, 10))
  84.         self.mob_img = pg.image.load(path.join(enemy_folder, MOB_IMG)).convert_alpha()
  85.         self.splat = pg.image.load(path.join(img_folder, SPLAT)).convert_alpha()
  86.         self.splat = pg.transform.scale(self.splat, (64, 64))
  87.         self.gun_flashes = []
  88.         self.item_images = {}
  89.         for item in ITEM_IMAGES:
  90.             self.item_images[item] = pg.image.load(path.join(potion_folder, ITEM_IMAGES[item])).convert_alpha()
  91.         # Sound loading
  92.         pg.mixer.music.load(path.join(music_folder, BG_MUSIC))
  93.         self.effects_sounds = {}
  94.         for type in EFFECTS_SOUNDS:
  95.             self.effects_sounds[type] = pg.mixer.Sound(path.join(snd_folder, EFFECTS_SOUNDS[type]))
  96.         self.weapon_sounds = {}
  97.         for weapon in WEAPON_SOUNDS:
  98.             self.weapon_sounds[weapon] = []
  99.             for snd in WEAPON_SOUNDS[weapon]:
  100.                 s = pg.mixer.Sound(path.join(snd_folder, snd))
  101.                 s.set_volume(0.3)
  102.                 self.weapon_sounds[weapon].append(s)
  103.         self.zombie_moan_sounds = []
  104.         for snd in ZOMBIE_MOAN_SOUNDS:
  105.             s = pg.mixer.Sound(path.join(snd_folder, snd))
  106.             s.set_volume(0.2)
  107.             self.zombie_moan_sounds.append(s)
  108.         self.player_hit_sounds = []
  109.         for snd in PLAYER_HIT_SOUNDS:
  110.             self.player_hit_sounds.append(pg.mixer.Sound(path.join(snd_folder, snd)))
  111.         self.zombie_hit_sounds = []
  112.         for snd in ZOMBIE_HIT_SOUNDS:
  113.             self.zombie_hit_sounds.append(pg.mixer.Sound(path.join(snd_folder, snd)))
  114.  
  115.     def new(self):
  116.         # initialize all variables and do all the setup for a new game
  117.         self.all_sprites = pg.sprite.LayeredUpdates()
  118.         self.walls = pg.sprite.Group()
  119.         self.mobs = pg.sprite.Group()
  120.         self.bullets = pg.sprite.Group()
  121.         self.items = pg.sprite.Group()
  122.         self.map = TiledMap(path.join(self.map_folder, 'overworld.tmx'))
  123.         self.map_img = self.map.make_map()
  124.         self.map.rect = self.map_img.get_rect()
  125.         for tile_object in self.map.tmxdata.objects:
  126.             obj_center = vec(tile_object.x + tile_object.width / 2,
  127.                              tile_object.y + tile_object.height / 2)
  128.             if tile_object.name == 'player':
  129.                 self.player = Player(self, obj_center.x, obj_center.y)
  130.             if tile_object.name == 'zombie':
  131.                 Mob(self, obj_center.x, obj_center.y)
  132.             if tile_object.name == '#':
  133.                 Obstacle(self, tile_object.x, tile_object.y,
  134.                          tile_object.width, tile_object.height)
  135.             if tile_object.name in ['health', 'shotgun']:
  136.                 Item(self, obj_center, tile_object.name)
  137.             if tile_object.name == 'portal':
  138.                 self.map = TiledMap(path.join(self.map_folder, tile_object.type))
  139.         self.camera = Camera(self.map.width, self.map.height)
  140.         self.draw_debug = False
  141.         self.paused = False
  142.         self.effects_sounds['level_start'].play()
  143.  
  144.     def run(self):
  145.         # game loop - set self.playing = False to end the game
  146.         self.playing = True
  147.         pg.mixer.music.play(loops=-1)
  148.         while self.playing:
  149.             self.dt = self.clock.tick(FPS) / 1000.00 # fix for Python 2.x
  150.             self.events()
  151.             if not self.paused:
  152.                 self.update()
  153.             self.draw()
  154.  
  155.     def quit(self):
  156.         pg.quit()
  157.         sys.exit()
  158.  
  159.     def update(self):
  160.         # update portion of the game loop
  161.         self.all_sprites.update()
  162.         self.camera.update(self.player)
  163.         # player hits items
  164.         hits = pg.sprite.spritecollide(self.player, self.items, False)
  165.         for hit in hits:
  166.             if hit.type == 'health' and self.player.health < PLAYER_HEALTH:
  167.                 hit.kill()
  168.                 self.effects_sounds['health_up'].play()
  169.                 self.player.add_health(HEALTH_PACK_AMOUNT)
  170.             if hit.type == 'shotgun':
  171.                 hit.kill()
  172.                 self.effects_sounds['gun_pickup'].play()
  173.                 self.player.weapon = 'shotgun'
  174.         # mobs hit player
  175.         hits = pg.sprite.spritecollide(self.player, self.mobs, False, collide_hit_rect)
  176.         for hit in hits:
  177.             if random() < 0.7:
  178.                 choice(self.player_hit_sounds).play()
  179.             self.player.health -= MOB_DAMAGE
  180.             hit.vel = vec(0, 0)
  181.             if self.player.health <= 0:
  182.                 self.playing = False
  183.         if hits:
  184.             self.player.hit()
  185.             self.player.pos += vec(MOB_KNOCKBACK, 0).rotate(-hits[0].rot)
  186.         # bullets hit mobs
  187.         hits = pg.sprite.groupcollide(self.mobs, self.bullets, False, True)
  188.         for mob in hits:
  189.             # hit.health -= WEAPONS[self.player.weapon]['damage'] * len(hits[hit])
  190.             for bullet in hits[mob]:
  191.                 mob.health -= bullet.damage
  192.             mob.vel = vec(0, 0)
  193.  
  194.     def draw_grid(self):
  195.         for x in range(0, WIDTH, TILESIZE):
  196.             pg.draw.line(self.screen, LIGHTGREY, (x, 0), (x, HEIGHT))
  197.         for y in range(0, HEIGHT, TILESIZE):
  198.             pg.draw.line(self.screen, LIGHTGREY, (0, y), (WIDTH, y))
  199.  
  200.     def draw(self):
  201.         pg.display.set_caption("{:.2f}".format(self.clock.get_fps()))
  202.         # self.screen.fill(BGCOLOR)
  203.         self.screen.blit(self.map_img, self.camera.apply(self.map))
  204.         # self.draw_grid()
  205.         for sprite in self.all_sprites:
  206.             if isinstance(sprite, Mob):
  207.                 sprite.draw_health()
  208.             self.screen.blit(sprite.image, self.camera.apply(sprite))
  209.             if self.draw_debug:
  210.                 pg.draw.rect(self.screen, CYAN, self.camera.apply_rect(sprite.hit_rect), 1)
  211.         if self.draw_debug:
  212.             for wall in self.walls:
  213.                 pg.draw.rect(self.screen, CYAN, self.camera.apply_rect(wall.rect), 1)
  214.  
  215.         # pg.draw.rect(self.screen, WHITE, self.player.hit_rect, 2)
  216.         # HUD functions
  217.         draw_player_health(self.screen, 10, 10, self.player.health / PLAYER_HEALTH)
  218.         self.draw_text('Zombies: {}'.format(len(self.mobs)), self.hud_font, 30, WHITE,
  219.                        WIDTH - 10, 10, align="ne")
  220.         if self.paused:
  221.             self.screen.blit(self.dim_screen, (0, 0))
  222.             self.draw_text("Paused", self.title_font, 105, RED, WIDTH / 2, HEIGHT / 2, align="center")
  223.         pg.display.flip()
  224.  
  225.     def events(self):
  226.         # catch all events here
  227.         for event in pg.event.get():
  228.             if event.type == pg.QUIT:
  229.                 self.quit()
  230.             if event.type == pg.KEYDOWN:
  231.                 if event.key == pg.K_ESCAPE:
  232.                     self.quit()
  233.                 if event.key == pg.K_h:
  234.                     self.draw_debug = not self.draw_debug
  235.                 if event.key == pg.K_p:
  236.                     self.paused = not self.paused
  237.  
  238.     def wait_for_key(self):
  239.         pg.event.wait()
  240.         waiting = True
  241.         while waiting:
  242.             self.clock.tick(FPS)
  243.             for event in pg.event.get():
  244.                 if event.type == pg.QUIT:
  245.                     waiting = False
  246.                     self.quit()
  247.                 if event.type == pg.KEYUP:
  248.                     waiting = False
  249.  
  250.  
  251. # create the game object
  252. g = Game()
  253. while True:
  254.     g.new()
  255.     g.run()
  256.  
RAW Paste Data