def allocate_platform(self, x, y, p_type): # get new platform from unused list if there is one if len(self.platformsNotInUse) > 0: newPlatform = self.platformsNotInUse.pop() newPlatform.init(x, y, p_type) self.platformsInUse.append(newPlatform) # create new platform and add it to the used list if there is no unused platforms. elif len(self.platformsInUse) < self.POOL_SIZE: newPlatform = Platform(self.game) newPlatform.init(x, y, p_type) self.platformsInUse.append(newPlatform) # pool is full so no platforms to allocate else: return None
def randomPlatform(self, top=True): x = randint(0, screen_width - platform_width) bad_y = [] for spr in self.allsprites: bad_y.append((spr.y - platform_y_padding, spr.y + platform_y_padding + spr.rect.height)) good = 0 while not good: if top: y = randint(-100, 50) else: y = randint(0, screen_height) good = 1 for bad_y_item in bad_y: if bad_y_item[0] <= y <= bad_y_item[1]: good = 0 break dig = randint(0, 100) if dig < 35: return MovingPlatform(x, y) elif dig >= 35 and dig < 50: return CrashingPlatform(x, y) else: return Platform(x, y)
def test_player_lands_on_platform_in_reverse(self): self.game.stage.player.movement.reverse = True plat = Platform(400, 380, 600, 15) self.game.stage.platforms.add(plat) self.game.stage.all_sprites.add(plat) self.game.run(15) self.assertTrue(self.game.stage.player.movement.ability)
def new(self): """Start a new game. """ # keeping track of missions self.vaccines_collected = 0 self.enemies_killed = 0 self.n_bullets = 20 # initial number of bullets for the player self.failed = False # used for checking if player completed game self.platforms_crossed = 0 # initialize sprite groups self.all_sprites = pygame.sprite.LayeredUpdates() self.platforms = pygame.sprite.Group() self.powerups = pygame.sprite.Group() self.enemies = pygame.sprite.Group() self.viruses = pygame.sprite.Group() self.bullets = pygame.sprite.Group() self.clouds = pygame.sprite.Group() # load bg image self.bg_image = BackGround(self) if self.level > 1: # needed for scrolling background self.bg_image_2 = BackGround(self) self.bg_image_2.rect.left = self.bg_image.rect.right # create new instance of player self.player = Player(self) # timer for spawning enemies self.slime_timer = 0 self.bat_timer = 0 # creating base self.bases = [] base = Base(self, 0) self.bases.append(base) while base.rect.right < s.WIDTH: base = Base(self, base.rect.right) self.bases.append(base) # creating starting platforms for plat in s.PLATFORM_START_LIST: Platform(self, *plat) # create clouds/other images if self.level == 1: for i in range(5): c = Cloud(self) c.rect.x -= random.randrange(200, 400, 50) # load music pygame.mixer.music.load(os.path.join(self.sound_dir, "background.ogg")) self.run()
def test_scrolling_moves_platforms(self): self.game.scrolling = True self.game.set_stage(FIRST, BUTTS) plat = Platform(100, 100, 100, 100) self.game.stage.platforms.add(plat) pos_x = plat.pos.x self.game.run(5) self.assertTrue(pos_x > plat.pos.x)
def add_new_platform(self, y): if len(self.platforms) < 6: w = random.choice([60, 80, 100]) h = 20 x = random.randrange(20, WIDTH - w - 20) y = y color = random.choice([BLUE, RED, GREEN]) Platform(self, color, x, y, w, h)
def test_left_movement_platform_collision(self): self.game.add_event( pygame.event.Event(pygame.KEYDOWN, key=pygame.K_LEFT)) plat = Platform(300, 400, 100, 100) self.game.stage.platforms.add(plat) self.game.stage.all_sprites.add(plat) self.game.run(20) self.assertTrue(self.game.stage.player.pos.x == plat.rect.right + PLAYER_WIDTH / 2)
def new(self, level): # start a new game if level == 5: self.playing = False g.show_go_screen() self.score = 0 self.all_sprites = pg.sprite.LayeredUpdates() self.platforms = pg.sprite.Group() self.powerups = pg.sprite.Group() self.mobs = pg.sprite.Group() self.clouds = pg.sprite.Group() self.portal = pg.sprite.Group() self.shortcut = pg.sprite.Group() self.player = Player(self) pg.mixer.music.load(path.join(self.snd_dir, 'gameplay.mp3')) pg.mixer.music.set_volume(.3) pg.mixer.music.play(loops=-1) if level == 1: for plat in PLATFORM_LIST_1: Platform(self, *plat) if level == 2: for plat in PLATFORM_LIST_2: Platform(self, *plat) if level == 3: for plat in PLATFORM_LIST_3: Platform(self, *plat) Portal(self) Shortcut(self) self.mob_timer = 0 for i in range(8): c = Cloud(self) c.rect.y += 500 self.run(level)
def __init__(self, level, character): self.effects = Effects() self.score = 1 self.all_sprites = pygame.sprite.Group() self.platforms = pygame.sprite.Group() self.baddies = pygame.sprite.Group() self.powerups = pygame.sprite.Group() self.player = Player(character) self.all_sprites.add(self.player) for platform in level: plat = Platform(platform[0], platform[1], platform[2], platform[3]) self.all_sprites.add(plat) self.platforms.add(plat)
def update(self): #check platform collsion hits = pygame.sprite.spritecollide(self, self.game.platforms, False) if self.animation: self._animate() if self.spike and not self.animation: #Display the platform beneath the spike if self.run_once: Platform(self.starting_x_position, self.starting_y_position + SPIKE_HEIGHT, self.game) #grass platform change x, y self.run_once = False if self.stone: self.rect.y += 2 if hits: if self.run_once: self.game.boulder_roll_sound.play() self.run_once = False self.rect.y -= 2 #stop the ball's y position else: self.game.boulder_roll_sound.stop() if self.rect.x + 100 <= 0: self.kill() if self.axe: self.rect.y += 3 if hits: self.rect.y -= 3 self.rect.x += 3 if hits[0].snow: if self.run_once: self.rect.y += hits[0].get_size(False) // 2 self.game.axe_hit_sound.play() self.run_once = False else: if self.run_once: self.game.axe_hit_sound.play() self.run_once = False self.image = self.stop_axe_image_list[self.random_num]
def generate(self): """Generates new platforms, baddies and powerups""" while len(self.platforms) < 7: _pos_x = randint(WIDTH + 50, WIDTH + 300) _pos_y = randint(50, 450) _width = randint(80, 130) _height = randint(20, 45) _new_plat = Platform(_pos_x, _pos_y, _width, _height) self.check_overlap(_new_plat, self.platforms, 150, 100) while len(self.baddies) < int((self.score + 2200) / 3000): _pos_x = randint(WIDTH + 50, WIDTH + 500) _pos_y = randint(-30, HEIGHT + 30) _new_baddie = Baddie(_pos_x, _pos_y) self.check_overlap(_new_baddie, self.baddies, 50, 50) if int(self.score % 3000) == 0: _pos_x = randint(WIDTH + 50, WIDTH + 200) _pos_y = randint(30, HEIGHT - 30) _powerup = Powerup(_pos_x, _pos_y) self.all_sprites.add(_powerup) self.powerups.add(_powerup)
def _animate(self): time_now = pygame.time.get_ticks() time_now_2 = pygame.time.get_ticks() if self.spike: #Spawn once a platform underneath the spike if self.run_once: Platform(self.starting_x_position, self.starting_y_position, self.game) #grass platform self.run_once = False #Make the spikes go up and down 300, 200, 400, 100 ms per frame if time_now - self.last_update_time > random.choice( [300, 200, 400, 100]): self.last_update_time = time_now if self.spike_go_up: self.rect.y -= 5 if self.spike_go_down: self.rect.y += 5 if self.rect.y <= self.starting_y_position - SPIKE_HEIGHT: self.spike_go_up = False self.spike_go_down = True elif self.rect.y >= self.starting_y_position + 1: #when the spikes go behind the platform, hide the spikes behind the platform in 6 sec self.rect.y -= 5 if time_now_2 - self.spike_update_time_2 > random.choice([ 4000, 3000, 5000 ]): #Hide behind the platform for 4, 3 or 5 sec self.spike_update_time_2 = time_now_2 self.spike_go_up = True self.spike_go_down = False if self.stone or self.axe: #Rotate the stone or axe image 90 degrees every 150 ms millisecs = 150 if self.stone else 70 if time_now - self.last_update_time > millisecs: self.last_update_time = time_now self.update_frame_index = (self.update_frame_index + 1) % len( self.image_rotation_list) self.image = self.image_rotation_list[self.update_frame_index] self.rect.x -= 3
def new_game(self): # Начать новую игру self.score = 0 self.death = False self.bg_count = 0 self.gravity = PLAYER_GRAVITY self.gravity_on_off = True self.gravity_count = 0 self.enemy_count = 0 self.all_sprites = pg.sprite.Group() self.platforms = pg.sprite.Group() self.powerups = pg.sprite.Group() self.enemies = pg.sprite.Group() self.background1 = Background(self, 0, -HEIGHT) self.background2 = Background(self, 0, 0) self.player = Player(self) for i in START_MAP: Platform(self, *i) self.run()
def update(self): """Updates attributes of objects. Main logic of the game. """ # update all sprites self.all_sprites.update() now = pygame.time.get_ticks() # prevent the player from going towards the left if self.player.rect.left <= 0: self.player.rect.right = self.player.rect.width + 10 # spawn Slime at level 1, 2, and 3 every 5 secs. if now - self.slime_timer > 5000 + random.choice( [-1000, -500, 0, 500, 1000]): if not self.paused: self.slime_timer = now Slime(self, self.level >= 3) # spawn bat at level 2 and above every 30 secs. if self.level == 2: bat_freq = 30000 elif self.level >= 3: bat_freq = 10000 # spawn bats only after level 1 if self.level > 1: if now - self.bat_timer > bat_freq + random.choice( [-1000, -500, 0, 500, 1000]): if not self.paused: self.bat_timer = now Bat(self, self.level == 4) # create new bases as player moves last_base = self.bases[-1] if last_base.rect.right <= s.WIDTH: new_base = Base(self, last_base.rect.right, s.HEIGHT - s.BASE_HEIGHT) self.bases.append(new_base) self.bases.pop(0) # player - enemy collision check temp_enemy_hits = pygame.sprite.spritecollide(self.player, self.enemies, False) if temp_enemy_hits: enemy_hits = pygame.sprite.spritecollide( self.player, self.enemies, True, pygame.sprite.collide_mask) try: if enemy_hits: self.dead_sound.play() # reduce player lives self.player.lives -= 1 # is player dead? if self.player.lives == 0: self.failed = True self.show_failed_screen() except Exception: pass # player - virus collision check temp_virus_hits = pygame.sprite.spritecollide(self.player, self.viruses, False) if temp_virus_hits: virus_hits = pygame.sprite.spritecollide( self.player, self.viruses, True, pygame.sprite.collide_mask) try: if virus_hits: self.dead_sound.play() self.failed = True self.show_failed_screen() except Exception: pass # bullet - virus collision check if self.level == 4: bv_hits = pygame.sprite.groupcollide(self.bullets, self.viruses, True, True) if bv_hits: self.dead_sound.play() self.score += 20 # bullet - enemy collision check be_hits = pygame.sprite.groupcollide(self.enemies, self.bullets, True, True) if be_hits: self.dead_sound.play() self.score += 20 self.enemies_killed += 1 # bullet - platform collision check, if so, bullet sprite will be killed pygame.sprite.groupcollide(self.bullets, self.platforms, True, False) # player - base collision check base_hits = pygame.sprite.spritecollide(self.player, self.bases, False) if base_hits: lowest = base_hits[0] # if player below base, make him rest on base if self.player.pos.y > lowest.rect.top: self.player.pos.y = lowest.rect.top + 5 self.player.vel.y = 0 self.player.jumping = False # player - powerup collision check pow_hits = pygame.sprite.spritecollide(self.player, self.powerups, True) for powerUp in pow_hits: self.powerup_sound.play() # add points to score self.score += 10 if powerUp.type == 'vaccine': self.vaccines_collected += 1 elif powerUp.type == 'health': self.player.lives += 1 elif powerUp.type == 'ammo': self.n_bullets += 1 # player - platform collision check temp_plat_hits = pygame.sprite.spritecollide(self.player, self.platforms, False) # BB check if temp_plat_hits: # mask check plat_hits = pygame.sprite.spritecollide(self.player, self.platforms, False, pygame.sprite.collide_mask) try: if plat_hits: plat = plat_hits[0] for hit in plat_hits: if hit.rect.left > plat.rect.left: plat = hit # if player is within the platforms's width if self.player.pos.x - self.player.rect.width / 2 < plat.rect.right and \ self.player.pos.x + self.player.rect.width / 2 > plat.rect.left: # if player is above platform, make him rest on platform if self.player.pos.y < plat.rect.centery: self.player.pos.y = plat.rect.top + 5 # to compensate for extra space below in image self.player.vel.y = 0 self.player.jumping = False # if player is below the platform, and was going/jumping up, restrict his jump if self.player.pos.y > plat.rect.bottom and self.player.vel.y < 0: self.player.pos.y = plat.rect.bottom + self.player.rect.height self.player.vel.y = 0 self.player.jumping = False except Exception: pass # moving screen towards right if self.player.rect.right >= s.WIDTH * 0.45: # creating new clouds if self.level == 1: if random.randrange(100) < s.CLOUD_FREQ: Cloud(self) if self.player.vel.x > 0: # updating player self.player.pos.x -= max(self.player.vel.x, 3) # updating previous clouds for cloud in self.clouds: cloud.rect.x -= max(self.player.vel.x / 6, 1) # updating platforms for plat in self.platforms: plat.rect.x -= max(self.player.vel.x, 3) if plat.rect.right <= 0: plat.kill() self.score += 1 self.platforms_crossed += 1 # updating enemies for enemy in self.enemies: enemy.rect.x -= max(self.player.vel.x, 3) # updating viruses for virus in self.viruses: virus.rect.x -= max(self.player.vel.x, 3) # background if self.level >= 2: self.bg_image.rect.x -= max(self.player.vel.x / 6, 1) # scrolling background if self.level >= 2: self.bg_image_2.rect.left = self.bg_image.rect.right if self.bg_image.rect.right < 0: self.bg_image.rect.left = 0 # spawn new platforms # calculate the right pos of previous platform max_right = 0 for plat in self.platforms: if plat.rect.right > max_right: max_right = plat.rect.right # create new platforms, max of 3 platforms available at a time. while len(self.platforms) < 3: rand_x = max_right + random.randrange(200, 400) rand_y = s.HEIGHT - 150 - s.BASE_HEIGHT - random.randrange( 0, 100, 20) Platform(self, rand_x, rand_y) # check if gameover if self.platforms_crossed >= s.PLAT_CROSS: if self.enemies_killed >= s.ENEMY_KILLS and self.vaccines_collected >= s.VAC_COLLECT: self.playing = False else: self.failed = True self.show_failed_screen()
def test_screen_edge_kills_platforms(self): plat = Platform(-100, -100, 10, 10) self.game.stage.all_sprites.add(plat) self.game.run(5) self.assertTrue(len(self.game.stage.all_sprites) == 6)
def game(): EXPLODING = 2 RUNNING = 1 QUIT = 0 state = RUNNING side = STILL assets = load_assets() all_sprites = pygame.sprite.Group() all_enemies = pygame.sprite.Group() all_bullets = pygame.sprite.Group() all_platforms = pygame.sprite.Group() groups = {} groups['all_sprites'] = all_sprites groups['all_meteors'] = all_enemies groups['all_bullets'] = all_bullets groups['all_platforms'] = all_platforms camera = Camera(assets) player = Hero(groups, assets, side) enemy = Enemy(assets) platform1 = Platform(assets, 700, 650) all_sprites.add(camera) all_sprites.add(player) all_sprites.add(platform1) score = 0 lives = 15 number_of_enemies = 2 keys_down = {} for i in range(number_of_enemies): enemy = Enemy(assets) all_sprites.add(enemy) all_enemies.add(enemy) while state != QUIT: for event in pygame.event.get(): if event.type == pygame.QUIT: state = QUIT if event.type == pygame.KEYDOWN: keys_down[event.key] = True if event.key == pygame.K_ESCAPE: pause() if event.key == pygame.K_UP or event.key == pygame.K_w: player.jump() if event.key == pygame.K_LEFT or event.key == pygame.K_a: camera.speedx += 2 enemy.speedx += 2 if camera.rect.left <= 0 or camera.rect.right >= window_width: platform1.speedx += 2 else: platform1.speed = 0 player.side = Bullet.side = LEFT if event.key == pygame.K_RIGHT or event.key == pygame.K_d: camera.speedx -= 2 enemy.speedx -= 2 if camera.rect.left <= 0 or camera.rect.right >= window_width: platform1.speedx -= 2 else: platform1.speed = 0 player.side = Bullet.side = RIGHT if event.key == pygame.K_SPACE: player.shoot() if event.type == pygame.KEYUP: if event.key in keys_down and keys_down[event.key]: if event.key == pygame.K_LEFT or event.key == pygame.K_a: camera.speedx -= 2 enemy.speedx -= 2 if camera.rect.left <= 0 or camera.rect.right >= window_width: platform1.speedx -= 2 else: platform1.speed = 0 player.side = Bullet.side = LEFT if event.key == pygame.K_RIGHT or event.key == pygame.K_d: camera.speedx += 2 enemy.speedx += 2 if camera.rect.left <= 0 or camera.rect.right >= window_width: platform1.speedx += 2 else: platform1.speed = 0 player.side = Bullet.side = RIGHT all_sprites.update() if state == RUNNING: hits = pygame.sprite.groupcollide(all_enemies, all_bullets, True, True, pygame.sprite.collide_mask) for enemy in hits: assets['destroy_sound'].play() e = Enemy(assets) all_sprites.add(e) all_enemies.add(e) explosion = Explosion(enemy.rect.center, assets) all_sprites.add(explosion) score += 100 if score % 1000 == 0: lives += 1 hits = pygame.sprite.spritecollide(player, all_enemies, True, pygame.sprite.collide_mask) if len(hits) > 0: assets['boom_sound'].play() player.kill() lives -= 1 explosion = Explosion(player.rect.center, assets) all_sprites.add(explosion) state = EXPLODING keys_down = {} explosion_tick = pygame.time.get_ticks() explosion_duration = explosion.frame_ticks * len(explosion.explosion_anim) + 50 hits = pygame.sprite.spritecollide(player, all_platforms, False, pygame.sprite.collide_mask) if hits: player.speedy = 0 player.rect.pos.y = hits[0].rect.top keys_down = {} elif state == EXPLODING: now = pygame.time.get_ticks() camera.speedx = 0 platform1.speedx = 0 keys_down = {} if now - explosion_tick > explosion_duration: if lives == 0: game_over() else: state = RUNNING player = Hero(groups, assets, side) enemy = Enemy(assets) all_sprites.add(player) all_sprites.add(enemy) all_enemies.add(enemy) all_sprites.draw(window) text_surface = assets['score_font'].render('{:08d}'.format(score), True, WHITE) text_rect = text_surface.get_rect() text_rect.midtop = (window_width / 2, 10) window.blit(text_surface, text_rect) text_surface = assets['score_font'].render(chr(9829) * lives, True, INSPER_RED) text_rect = text_surface.get_rect() text_rect.topleft = (10, 10) window.blit(text_surface, text_rect) pygame.display.update() clock.tick(FPS) pygame.quit() pygame.mixer.quit()