class GS_Game(GameState): def __init__(self, kernel, gsm): GameState.__init__(self, "Game", kernel, gsm) self.mLevelName = "" self.mLevel = None self.mGroundLevel = 570 self.mHighScores = {} self.mScrollSpeed = 2 self.mPaused = 0 self.mHouse = None self.mCurrentLevel = 1 self.mLevelComplete = False self.mSoundState = 1 self.mMusic = self.mKernel.SoundManager().LoadSound("BGmusic_flyaway.wav") self.mGameOverImage, self.mGameOverRect = self.mKernel.ImageManager().LoadImage("gameover.bmp") self.mLevelCompleteImage, self.mLevelCompleteRect = self.mKernel.ImageManager().LoadImage("levelcomplete.bmp") self.mMainMenuImage, self.mMainMenuRect = self.mKernel.ImageManager().LoadImage("mainmenu_small.bmp") self.mNextLevelImage, self.mNextLevelRect = self.mKernel.ImageManager().LoadImage("nextlevel.bmp") self.mHighScoreImage, self.mHighScoreRect = self.mKernel.ImageManager().LoadImage("highscore_alert.bmp") self.mGameOverRect.topleft = (400 - self.mGameOverRect.width / 2, 150) self.mLevelCompleteRect.topleft = (400 - self.mLevelCompleteRect.width / 2, 50) self.mHighScoreRect.topleft = (400 - self.mHighScoreRect.width / 2, 225) self.mNextLevelRect.topleft = (600 - self.mMainMenuRect.width / 2, 350) self.mMainMenuRect.topleft = (400 - self.mMainMenuRect.width / 2, 350) self.mFont = pygame.font.SysFont("Helvetica", 16, True) self.mPreviousPop = False self.mPreviousDead = 0 self.mCurrentLevel = 1 self.mNextLevelName = "" def Initialize(self, levelName = ""): self.mHighScores = {} self.mScore = 0 self.mPaused = 0 if (levelName): self.LoadLevel(levelName) if (levelName[5].isdigit()): self.mCurrentLevel = int(levelName[5]) else: self.mCurrentLevel = -1 elif (self.mNextLevelName): self.LoadLevel(self.mNextLevelName) else: self.LoadLevel("Level1") self.LoadScores() self.mLevelComplete = False for entity in self.mLevel.mEntities: entity.mSoundState = self.mSoundState self.mBalloon.mSoundState = self.mSoundState self.mPerson.mSoundState = self.mSoundState self.mMusic.set_volume(.3 * self.mSoundState) self.mMusic.stop() self.mMusic.play(-1) fullLevelName = os.path.join("data", "levels", "Level" + str(self.mCurrentLevel + 1) + ".lvl") if os.path.isfile(fullLevelName): self.mNextLevelName = "Level" + str(self.mCurrentLevel + 1) self.mMainMenuRect.topleft = (200 - self.mMainMenuRect.width / 2, 350) else: self.mNextLevelName = "" self.mMainMenuRect.topleft = (400 - self.mMainMenuRect.width / 2, 350) return GameState.Initialize(self) def LoadLevel(self, levelName): self.mLevelName = levelName + ".lvl" self.mLevel = Level(self.mKernel, 800) self.mLevel.LoadLevel(self.mLevelName) self.mLevel.mScrollSpeed = self.mScrollSpeed self.mCordImage, self.mCordRect = self.mKernel.ImageManager().LoadImage("cord.bmp") self.mCordRect.bottomleft = (0, self.mGroundLevel) self.mPerson = Person(self.mKernel, self.mLevel) self.mPerson.SetPosition([128, self.mGroundLevel]) self.mPerson.mScreenOffset = 128 self.mPerson.SetGroundLevel(self.mGroundLevel) self.mPerson.SyncCollisionRect() self.mHouse = House(self.mKernel, self.mLevel) self.mHouse.SetPosition([ self.mLevel.mLevelLength - 512, self.mGroundLevel - 480 ]) self.mHouse.SyncCollisionRect() self.SpawnBalloon() def SpawnBalloon(self): self.mBalloon = Balloon(self.mKernel, self.mLevel) self.mBalloon.SetPosition([ self.mLevel.mCameraX + self.mPerson.mScreenOffset + 128, self.mGroundLevel - self.mBalloon.Rect().height - 128 ]) self.mBalloon.mGroundLevel = 500 def Destroy(self): self.mMusic.stop() self.mNextLevelName = "" self.mCurrentLevel = 1 return GameState.Destroy(self) def Pause(self): self.mMusic.stop() return GameState.Pause(self) def Unpause(self): self.mMusic.play(-1) return GameState.Unpause(self) def HandleEvent(self, event): if (event.type == QUIT): pygame.quit() sys.exit() elif (event.type == KEYDOWN): if (event.key == K_UP): self.mPerson.Jump() elif (event.key == K_DOWN): self.mPerson.Duck() elif (event.key == K_SPACE): self.mBalloon.mBlown = 1 elif (event.key == K_p): self.mPaused = (self.mPaused + 1) % 2 elif (event.key == K_ESCAPE): self.mGameStateManager.SwitchState('MainMenu') elif (event.key == K_m): for entity in self.mLevel.mEntities: entity.mSoundState = (entity.mSoundState +1) % 2 self.mBalloon.mSoundState = (self.mBalloon.mSoundState +1) % 2 self.mPerson.mSoundState = (self.mBalloon.mSoundState + 1) % 2 self.mSoundState = (self.mSoundState +1) % 2 self.mMusic.set_volume(.3*self.mSoundState) elif(event.type == KEYUP): if (event.key == K_SPACE): self.mBalloon.mBlown = 0 elif (event.key == K_DOWN): self.mPerson.Run() elif (event.type == MOUSEBUTTONDOWN): if (self.mMainMenuRect.collidepoint(event.pos)): self.Destroy() self.mGameStateManager.SwitchState("MainMenu") elif (self.mNextLevelRect.collidepoint(event.pos)): self.mCurrentLevel += 1 self.Initialize() return GameState.HandleEvent(self, event) def Update(self, delta): if (not self.mLevelComplete): if self.mPerson.CheckCollision(self.mHouse): self.mLevelComplete = True self.SaveScore() self.mPerson.Done() if self.mLevel.mCameraX > (self.mLevel.mLevelLength - 1500): self.mBalloon.mBlown = 0 if not self.mLevelComplete and self.mPaused == 0: if (self.mPerson.mDead == 0 and self.mPerson.mLives > 0): self.mLevel.Scroll(self.mScrollSpeed) self.mLevel.Update(delta) if (self.mPerson.mLives > 0): self.mPerson.Update(delta) if (self.mPerson.mDead == 0):# and self.mPerson.mLives > 0): self.mBalloon.Update(delta) if (self.mPerson.CheckCollision(self.mBalloon) and self.mBalloon.CheckCollision(self.mPerson)): self.mPerson.OnCollision(self.mBalloon) self.mBalloon.OnCollision(self.mPerson) self.mLevel.CheckCollisions(self.mPerson) self.mLevel.CheckCollisions(self.mBalloon) if (self.mBalloon.mPopped): if (not self.mPreviousPop): self.mPerson.mLives -= 1 if (self.mBalloon.mPosition[0] < self.mLevel.mCameraX): if (self.mPerson.mLives > 0): self.SpawnBalloon() if (self.mPerson.mResetting): self.SpawnBalloon() self.mPerson.mResetting = False self.mLevel.Draw() self.mHouse.DrawBack() self.mCordRect.bottomright = self.mPerson.Rect().bottomleft self.mLevel.DisplaySurface().blit(self.mCordImage, self.mCordRect) self.mPerson.Draw() self.mHouse.Draw() self.mBalloon.Draw() self.mLevel.Blit() textSurface = self.mFont.render( str(self.mLevelName)[0:-4], True, Colors.WHITE) self.mKernel.DisplaySurface().blit(textSurface, (30, 580, textSurface.get_rect().width, textSurface.get_rect().height)) textSurface = self.mFont.render("Score: " + str(self.mPerson.mScore), True, Colors.WHITE) self.mKernel.DisplaySurface().blit(textSurface, (150, 580, textSurface.get_rect().width, textSurface.get_rect().height)) textSurface = self.mFont.render("Lives: " + str(self.mPerson.mLives), True, Colors.WHITE) self.mKernel.DisplaySurface().blit(textSurface, (270, 580, textSurface.get_rect().width, textSurface.get_rect().height)) textSurface = self.mFont.render("In Basket: " + str(self.mBalloon.mValue), True, Colors.WHITE) self.mKernel.DisplaySurface().blit(textSurface, (390, 580, textSurface.get_rect().width, textSurface.get_rect().height)) textSurface = self.mFont.render("Points Possible: " + str(self.mLevel.mMaxScore), True, Colors.WHITE) self.mKernel.DisplaySurface().blit(textSurface, (540, 580, textSurface.get_rect().width, textSurface.get_rect().height)) if (self.mPerson.mLives == 0): self.mKernel.DisplaySurface().blit(self.mGameOverImage, self.mGameOverRect) self.mMainMenuRect.topleft = (400 - self.mMainMenuRect.width / 2, 350) self.mKernel.DisplaySurface().blit(self.mMainMenuImage, self.mMainMenuRect) if (self.mLevelComplete): self.mKernel.DisplaySurface().blit(self.mLevelCompleteImage, self.mLevelCompleteRect) self.mKernel.DisplaySurface().blit(self.mMainMenuImage, self.mMainMenuRect) if (self.mHighScores[self.mLevelName] == self.mPerson.mScore): self.mKernel.DisplaySurface().blit(self.mHighScoreImage, self.mHighScoreRect) if (self.mNextLevelName != ""): self.mKernel.DisplaySurface().blit(self.mNextLevelImage, self.mNextLevelRect) self.mPreviousDead = self.mPerson.mDead self.mPreviousPop = self.mBalloon.mPopped return GameState.Update(self, delta) def SaveScore(self): if self.mLevelName in self.mHighScores: if self.mPerson.mScore > self.mHighScores[self.mLevelName]: self.mHighScores[self.mLevelName] = self.mPerson.mScore else: self.mHighScores[self.mLevelName] = self.mPerson.mScore with open(os.path.join("data", "highscores.txt"), 'w') as file: for level in self.mHighScores: file.write(level + " " + str(self.mHighScores[level]) + "\n") def LoadScores(self): HighScoreFile = os.path.join("data", "highscores.txt") if (os.path.isfile(HighScoreFile)): with open(HighScoreFile) as highscores: scoreList = highscores.read().splitlines() for i in range(0, len(scoreList)): parts = scoreList[i].split() self.mHighScores[parts[0]] = int(parts[1])
class MainGameState(GameState): def __init__(self): GameState.__init__(self) self.resetGame() def resetGame(self): self.player = Player((Globals.window.screen_size[0] / 2, Globals.window.screen_size[1])) self.level = Level(self) self.score = 0 self.smooth_score = 0 self.all_sprites = pygame.sprite.Group() self.all_sprites.add(self.player) self.enemies = pygame.sprite.Group() self.background = pygame.sprite.Group() self.foreground = pygame.sprite.Group() self.effects = pygame.sprite.Group() self.powerups = pygame.sprite.Group() self.enemy_bullets = pygame.sprite.Group() self.player_bullets = pygame.sprite.Group() # GUI self.gui = pygame.sprite.Group() self.hp_bar = GuiBar(pygame.Rect(5, 5, 128, 16)) self.score_text = GuiText(position=(5, 16+5+5), font_size=16) self.gui.add(self.hp_bar) self.gui.add(self.score_text) self.level.Start() def addEnemy(self, new_enemy): self.enemies.add(new_enemy) self.all_sprites.add(new_enemy) def spawnExplosion(self, position): new_explosion = Animation(Globals.resourceManager.get_sprite_sheet("explosion.png"), center=position, loop=False, frames_per_frame=5) self.effects.add(new_explosion) def addBackground(self, image) -> Background: new_background = Background(image) self.background.add(new_background) return new_background def addForeground(self, image) -> Background: new_foreground = Background(image) self.foreground.add(new_foreground) return new_foreground def addBullet(self, bullet, player=True): if player: self.player_bullets.add(bullet) else: self.enemy_bullets.add(bullet) self.all_sprites.add(bullet) @staticmethod def pixel_perfect_collision(s1, s2): # First check rect collision then check mask collision return s1.rect.colliderect(s2) and pygame.sprite.collide_mask(s1, s2) def check_collisions(self): for powerup in self.powerups: # Check if player picked up a powerup if self.player.rect.colliderect(powerup.rect): powerup.on_pickup(self.player) powerup.kill() Globals.resourceManager.get_sound("powerup.wav").play() for enemy in self.enemies: # Check if enemy is hit by a bullet for bullet in self.player_bullets: if self.pixel_perfect_collision(bullet, enemy): enemy.damage(bullet.get_dmg()) bullet.kill() Globals.resourceManager.get_sound("hit.wav").play() Globals.window.shakeCamera(1) # Check if enemy is hit by the player if self.player.is_alive() and not self.player.is_invincible() and self.pixel_perfect_collision(self.player, enemy): self.player.damage(50) enemy.damage(50) Globals.resourceManager.get_sound("hit.wav").play() Globals.window.shakeCamera(5) if self.player.is_alive() and not self.player.is_invincible(): for enemy_bullet in self.enemy_bullets: if self.pixel_perfect_collision(self.player, enemy_bullet): self.player.damage(enemy_bullet.get_dmg()) enemy_bullet.kill() Globals.resourceManager.get_sound("hit.wav").play() Globals.window.shakeCamera(5) def start(self): self.level.Start() def end(self): pass def update(self): screen_rect = Globals.window.fake_screen.get_rect() if Globals.window.game_state is self: move = self.level.Update() # update player pressed_keys = pygame.key.get_pressed() self.player.update(screen_rect, pressed_keys) else: move = self.level.Update(game_not_paused=False) # and his bullets self.player_bullets.update(screen_rect) # update enemies and their bullets self.enemies.update(screen_rect) self.enemy_bullets.update(screen_rect) # move backgrounds self.background.update(move, screen_rect) # move foreground self.foreground.update(move * 2, screen_rect) self.effects.update(move * 2, screen_rect) self.powerups.update(move * 2, screen_rect) self.check_collisions() def draw(self, screen): # draw background for entity in self.background: entity.draw(screen) # draw foreground clouds etc. for entity in self.foreground: entity.draw(screen) # draw effects explosions etc. for entity in self.effects: entity.draw(screen) # draw powerups for entity in self.powerups: entity.draw(screen) # draw all generic sprites enemies, player, etc. for entity in self.all_sprites: entity.draw(screen) # sync and draw gui if self.smooth_score < self.score: diff = self.score - self.smooth_score if diff > 60: self.smooth_score += int(diff/3) else: self.smooth_score += 1 self.score_text.set_text("SCORE: " + str(self.smooth_score)) self.hp_bar.set_progress(self.player.hp / self.player.max_hp) for entity in self.gui: entity.draw(screen)