def setup_txtobjs(self): self.initials = TextObj(text="", color=(255, 255, 255), pinned_to=("center", (self.w / 2, self.h / 2))) self.congrats = TextObj( text="High Score! Enter your name, frunk destroyer.", pinned_to=("center", (self.w / 2, self.h / 10)) ) self.get_score_q.add(self.initials, self.congrats) self.add_obj(self.initials, self.congrats) [obj.hide() for obj in self.get_score_q]
def setup_textobjs(self): self.scoretxt = TextObj(text='Score:', color=(255, 255, 255), size=18) self.scorenum = TextObj(text=publish_with_results('give', 'last_score')[0], color=(255, 255, 255), size=18) self.livestxt = TextObj(text='Lives:', color=(255, 255, 255), size=18) self.livesnum = TextObj(text=publish_with_results('give', 'last_lives')[0], color=(255, 255, 255), size=18) self.leveltxt = TextObj(text='', color=(255, 255, 255), size=18) self.gameovertxt = TextObj(text=' '.join("GAME OVER"), size=36) #set locations for all objects self.scoretxt.pin_at('topleft', (15, 15)) self.scorenum.pin_at('topleft', (self.scoretxt.rect.topright[0] + 5, self.scoretxt.rect.topright[1])) self.livestxt.pin_at('topright', (self.w - (self.w / 19), 15)) self.livesnum.pin_at('topleft', (self.livestxt.rect.topright[0] + 5, self.livestxt.rect.topright[1])) self.leveltxt.pin_at('center', (self.w / 2, self.h / 20)) self.gameovertxt.pin_at('center', (self.w / 2, self.h / 2)) self.gameovertxt.hide()
class LevelScene(GameScene): def __init__(self): super(LevelScene, self).__init__() self.imgbank = self.get_images() self.lvl = 0 self.goodq = pygame.sprite.Group() self.badq = pygame.sprite.Group() self.state = 'setup' self.go_to_gameover = 90 ###lanes are used to give things new coordinates in specific ways self.west = pygame.Rect(0, 0, self.w / 4, self.h) self.east = pygame.Rect(3 * self.w / 4, 0, self.w / 4, self.h) self.north = pygame.Rect(0, 0, self.w, self.h / 4) self.south = pygame.Rect(0, 3 * self.h / 4, self.w, self.h / 4) self.setup_textobjs() self.sub_to_msgs('ship_set_score', 'ship_set_lives', 'set_lvl_txt', 'gameover_show', 'gameover_hide', 'teleported', 'player_fired', 'player_died', 'got_1up', 'enemy_died', 'enemy_fired', 'can_lock_on_ship') def get_images(self): Sheet = spritesheet('imgs/sheet.png') return { 'PlayerImg': Sheet.image_at((0, 0, 32, 32), -1), 'PlayerFiring': Sheet.image_at((32, 0, 32, 32), -1), 'RedShip': Sheet.image_at((0, 32, 32, 32), -1), 'GreenShip': Sheet.image_at((0, 64, 32, 32), -1), 'GoodShot': Sheet.image_at((64, 0, 32, 32), -1), 'BadShot': Sheet.image_at((64, 32, 32, 32), -1), 'ExplodeList': [Sheet.image_at((i * 32, 96, 32, 32), -1) for i in (0, 1, 2, 3, 2, 3, 4)] } def setup_textobjs(self): self.scoretxt = TextObj(text='Score:', color=(255, 255, 255), size=18) self.scorenum = TextObj(text=publish_with_results('give', 'last_score')[0], color=(255, 255, 255), size=18) self.livestxt = TextObj(text='Lives:', color=(255, 255, 255), size=18) self.livesnum = TextObj(text=publish_with_results('give', 'last_lives')[0], color=(255, 255, 255), size=18) self.leveltxt = TextObj(text='', color=(255, 255, 255), size=18) self.gameovertxt = TextObj(text=' '.join("GAME OVER"), size=36) #set locations for all objects self.scoretxt.pin_at('topleft', (15, 15)) self.scorenum.pin_at('topleft', (self.scoretxt.rect.topright[0] + 5, self.scoretxt.rect.topright[1])) self.livestxt.pin_at('topright', (self.w - (self.w / 19), 15)) self.livesnum.pin_at('topleft', (self.livestxt.rect.topright[0] + 5, self.livestxt.rect.topright[1])) self.leveltxt.pin_at('center', (self.w / 2, self.h / 20)) self.gameovertxt.pin_at('center', (self.w / 2, self.h / 2)) self.gameovertxt.hide() def offsides(self, obj, offset=15): """Checks to see if an object has gone so many pixels outside the screen. """ return not ((self.w + offset) > obj.x > (offset * -1) and (self.h + offset) > obj.y > (offset * -1)) def check_hits(self, one, two): return one.hit_rect.colliderect(two.hit_rect) def get_pt_in_lane(self): lane = random.choice([self.west, self.east, self.north, self.south]) return [random.randint(*p) for p in zip(lane.topleft, lane.bottomright)] def set_heading_from_lane(self, obj): lanes = { 'north': ([-1, 1], [0, 1], [1, 1]), 'south': ([-1, -1], [0, -1], [1, -1]), 'east': ([-1, -1], [-1, 0], [-1, 1]), 'west': ([1, -1], [1, 0], [1, 1]) } dirs = [] for lane in lanes: if getattr(self, lane).collidepoint(obj.pos): [dirs.append(d) for d in lanes[lane] if d not in dirs] if dirs: obj.heading = random.choice(dirs) def ship_set_score(self, score): self.scorenum.set_text(score) def ship_set_lives(self, lives): self.livesnum.set_text(lives) def can_lock_on_ship(self, asker): if self.player.respawn: asker.bound_to = None else: asker.bound_to = self.player @with_sound def player_fired(self, player, heading): self.made_like_object(player, Bullet, x=player.x, y=player.y, img=self.imgbank['GoodShot'], speed=15, heading=heading) @with_sound def enemy_fired(self, enemy): self.made_like_object(enemy, Bullet, x=enemy.x, y=enemy.y, img=self.imgbank['BadShot'], speed=8, heading=random.choice(self.directions)) @with_sound def player_died(self, player): diagonals = [d for d in self.directions if 0 not in d] degs = -90 - math.degrees(math.atan2(*player.heading[::-1])) CurrentImg = pygame.transform.rotate(player.image, degs) half_w, half_h = [i / 2 for i in CurrentImg.get_rect().size] top_x, top_y = player.hit_rect.topleft pieces = [(x, y) for x in (0, half_w) for y in (0, half_h)] for index, piece in enumerate(pieces): BustedRect = pygame.Rect(piece[0], piece[1], half_w, half_h) new_x = top_x if piece[0] == 0 else top_x + half_w new_y = top_y if piece[1] == 0 else top_y + half_h self.made_object(player, ShipPiece, x=new_x, y=new_y, img=CurrentImg.subsurface(BustedRect), heading=diagonals[index]) @with_sound def enemy_died(self, enemy): self.made_object(enemy, Explosion, x=enemy.x, y=enemy.y, imgs=self.imgbank['ExplodeList'], heading=random.choice(self.directions)) self.made_object(enemy, RiseText, x=enemy.x, y=enemy.y, text=enemy.points) def got_1up(self, player): self.made_object(player, RiseText, x=player.x, y=player.y, color=(50, 200, 50), text='1UP') @with_sound def teleported(self, obj): obj.pos = self.get_pt_in_lane() self.set_heading_from_lane(obj) def __enter__(self, *args): start_x, start_y = self.w / 2, self.h / 2 pygame.mouse.set_pos([start_x, start_y]) self.player = Player(start_x, start_y, self.imgbank['PlayerImg'], KEY_VAL, 5000) PlayerSights = PlayerMouse(start_x, start_y, bound_to=self.player) self.add_obj(self.scoretxt, self.scorenum, self.livestxt, self.livesnum, self.leveltxt, self.gameovertxt, self.player, PlayerSights) self.goodq.add(self.player) return self def setup(self): world, stage = [i + 1 for i in divmod(self.lvl, 4)] self.leveltxt.set_text('Level {} - {}'.format(world, stage)) possibleAI = {1:[Scooter, Scooter], 2:[Scooter, Scooter], 3:[Sweeper, Sweeper], 4:[Sweeper, Sweeper]} kinds_of_AI = possibleAI[stage] if world >= 2: kinds_of_AI.append(Teleporter) if world >= 4: kinds_of_AI.append(Rammer) enemies = 2 + world for i in xrange(0, enemies): variance = random.randint(0, world) x, y = self.get_pt_in_lane() NewEnemy = random.choice(kinds_of_AI)( x=x, y=y, img=self.imgbank['RedShip'].copy(), heading=random.choice(KEY_VAL.values())) NewEnemy.speed = int(math.floor(NewEnemy.speed * (1.05 ** variance))) NewEnemy.points = int(math.floor(NewEnemy.points + ((NewEnemy.points / 10) * variance))) NewEnemy.add(self.badq) self.add_obj(NewEnemy) if stage % 4 == 1 and world > 1: publish('new_heading') def main(self, events): if self.state == 'gameover': if self.go_to_gameover in (90, 45): self.gameovertxt.show(45) if self.go_to_gameover in (78, 23): self.gameovertxt.hide(45) self.go_to_gameover -= 1 if self.go_to_gameover <= 0: publish('save', 'last_score', self.player.score) return False if self.state == 'setup': self.setup() self.state = 'play' if self.state == 'paused': for e in events: if e.type == pygame.KEYDOWN: if e.key == pygame.K_p: self.state = 'play' return True if self.state == 'play': for e in events: if e.type == pygame.KEYDOWN: if e.key == pygame.K_p: self.state = 'paused' else: self.player.handle_key(e.key) for goodguy in self.goodq: hit_list = pygame.sprite.spritecollide(goodguy, self.badq, False, self.check_hits) if hit_list: goodguy.got_hit() if goodguy is not self.player: for badguy in hit_list: badguy.got_hit() if badguy not in self.badq and badguy.points: self.player.score += badguy.points #maybe offset should be a class attribute [x.out_of_bounds() for x in [o for o in self.allq if self.offsides(o)]] if not self.player.lives: self.state = 'gameover' elif not self.badq: self.lvl += 1 self.state = 'setup' self.allq.update() return True
class GameOverScene(GameScene): def __init__(self): super(GameOverScene, self).__init__() self.state = "build_scores" self.player_initials = "" self.ship_score = publish_with_results("give", "last_score")[0] or 0 self.get_score_q = pygame.sprite.Group() self.show_scores_q = pygame.sprite.Group() self.setup_txtobjs() def setup_txtobjs(self): self.initials = TextObj(text="", color=(255, 255, 255), pinned_to=("center", (self.w / 2, self.h / 2))) self.congrats = TextObj( text="High Score! Enter your name, frunk destroyer.", pinned_to=("center", (self.w / 2, self.h / 10)) ) self.get_score_q.add(self.initials, self.congrats) self.add_obj(self.initials, self.congrats) [obj.hide() for obj in self.get_score_q] def __enter__(self, *args): if self.ship_score > scoreList[-1][1]: self.state = "get_score" [obj.show() for obj in self.get_score_q] pygame.mixer.music.load(path.join("sounds", "gameover.wav")) pygame.mixer.music.set_volume(0.1) pygame.mixer.music.play(-1) return self def main(self, events): """Gets initials if you earned a hi-score. Displays scores.""" if self.state == "show_scores": return False if pygame.KEYDOWN in [e.type for e in events] else True if self.state == "get_score": for e in events: if e.type == pygame.KEYDOWN: next_char = str(e.unicode) if next_char.isalnum(): # only letters/numbers self.player_initials += next_char.upper() self.initials.set_text(self.player_initials) if self.player_initials[2:]: scoreList.append([self.player_initials, self.ship_score]) scoreList.sort(key=lambda x: x[1]) scoreList.reverse() while len(scoreList) > 5: scoreList.pop() [obj.hide(30) for obj in self.get_score_q] self.state = "build_scores" if self.state == "build_scores": for i, name_num in enumerate(scoreList): x, y = (self.w / 3, ((self.h + 150) / 8) * (i + 1)) rgb = (50, 200 - (30 * i), 50) Name = TextObj(x, y, name_num[0], rgb) HiScore = TextObj(x * 2, y, name_num[1], rgb) for txtobj in (Name, HiScore): txtobj.hide() txtobj.show(30) self.show_scores_q.add(txtobj) self.add_obj(txtobj) self.state = "show_scores" self.allq.update() return True def __exit__(self, *args): pygame.mixer.music.stop() with open("scores.py", "w") as f: f.write(pickle.dumps(scoreList)) super(GameOverScene, self).__exit__(*args)