シューティングゲームにゲームクリア画面を付ける
半年前にシューティングを作成しようという話があがりました
ただただ普通のシューティングゲームを作成しても面白みがないので、
何かオリジナリティあるもの を探していました。
いつものようにtwitterを眺めていると気づきました、みんなこれが大好きだと。
ガチャ
ガチャを回して出てきたキャラクターを機体としてクリアするシューティングゲーム!
無料で何度でもガチャが回せるのできっと人気がでます。
そんなコンセプトで半年前に身内用にシューティングゲームを作成しました。
なんとか遊べる程度には無理やり作成できましたが、
ゲームのクリア画面がなかったので今回はあの頃に戻り、ゲームクリア画面を実装したいと思います。
こちらの記事を参考に初めは作成しました。
Pythonでゲームを作ろうと思うと必ずお世話になるのではないでしょうか?
こちらのインベーダー部分を基にごちゃっととりあえず動くものを作成しました。
確か画面遷移はこんな感じです
ステージは5つあり、次のステージに進むためのステージクリア画面は用意してありますが、
全てのステージをクリアしたときにもステージクリア画面へ移行してしまいます。
次のステージがないならゲームクリアと判断し、リザルトを表示するゲームクリア画面を作成します
ここから先は今の実装を見ないとわからないと思うので個人的なメモみたいになりますm__m
クリアタイムの保存
ゲームクリア時に各ステージのクリアタイムとそれを合計したものを表示する 現状のソースコードを見ると、ゲームスタート時に測定を開始し、それからずっとストップすることない目印みたいなものになっている
if self.gameState == PLAY: # 残機とか体力とかスコアとか. # プレイ時間. self.result = time.time() - self.stime result = int(self.result * 100) text = getText("{:.2f}".format(result/100), 30, WHITE) self.screen.blit(text, (self.scr_rect.width - text.get_width() - 5, self.scr_rect.height - text.get_height() - 5)) # 体力 text = getText(str(self.player.hp), 30, WHITE) self.screen.blit(text, (150, self.scr_rect.height - text.get_height() - 5)) pygame.draw.rect(self.screen, YELLOW, Rect(30, self.scr_rect.height - text.get_height() - 5, 100 * self.player.hp / self.player.hp_max, 30)) elif self.gameState == GAMECLEAR: titleText = getText("CLEAR", 75, YELLOW) self.screen.blit(titleText, (self.scr_rect.width//2 - titleText.get_width()//2, self.scr_rect.height//4)) self.updateButtonView()
self.result
に今の時間が入ってそう。。
100倍してIntにキャストして、100で割っているのは小数点第二桁より下を切り捨てするためっぽい
その値を保存し、クリア時に表示させたいので一旦以下のように変更
if self.gameState == PLAY: # 残機とか体力とかスコアとか. # プレイ時間. playTime = time.time() - self.stime time_buf = int(playTime * 100) self.clearTime = "{:.2f}".format(time_buf/100) text = getText(self.clearTime, 30, WHITE) self.screen.blit(text, (self.scr_rect.width - text.get_width() - 5, self.scr_rect.height - text.get_height() - 5)) # 体力 text = getText(str(self.player.hp), 30, WHITE) self.screen.blit(text, (150, self.scr_rect.height - text.get_height() - 5)) pygame.draw.rect(self.screen, YELLOW, Rect(30, self.scr_rect.height - text.get_height() - 5, 100 * self.player.hp / self.player.hp_max, 30)) elif self.gameState == GAMECLEAR: titleText = getText("CLEAR", 75, YELLOW) self.screen.blit(titleText, (self.scr_rect.width//2 - titleText.get_width()//2, self.scr_rect.height//4)) clearText = "clear time: " + self.clearTime text = getText(clearText, 30, WHITE) self.screen.blit(text, (self.scr_rect.width//2 - text.get_width()//2, self.scr_rect.height//4 + 150)) self.updateButtonView()
クリア時に時間が表示されるようになった。
あととこの時間を保存していたいのでNEXTを押したときに保存するように関数をたたく
if self.chooing_buton == NEXT_BUTTON: + self.stime = time.time() + self.gameManager.setClearTime(self.clearTime) self.returnStatus = GameState.Pass self.gameManager.stageNumber += 1 self.gameManager.createStage() self.gameState = PLAY
gameManagerにセット関数を用意し、stimeを現在地で初期化。
これで次のステージはまた0秒からカウントアップをする
ゲームクリア画面への遷移
最終ステージをクリアしても、特別な画面へ遷移することがないのでとりあえず側だけ作る
基本はgameOver画面をコピーしてgameClear画面を作成。
GameStateにGameclearを追加。
def createStage(self): if self.stageNumber == 1: self.stage = Stage1() elif self.stageNumber == 2: self.stage = Stage2() elif self.stageNumber == 3: self.stage = Stage3() elif self.stageNumber == 4: self.stage = Stage4() elif self.stageNumber == 5: self.stage = Stage5() else: self.state = GAMECLEAR return self.state = PLAY
あまりよくない実装っぽいけど次のステージがない場合はstateをGAMECLEARにする
GAMECLEARならGameclearを返す(なんだこの実装は・・・)
self.key_handler() if self.gameManager.state == GAMECLEAR: self.clearTimes = self.gameManager.getClearTimes(); self.returnStatus = GameState.Gameclear elif self.gameState == PLAY: self.gameState = self.gameManager.update() elif self.gameState == GAMEOVER: self.returnStatus = GameState.Gameover return self.returnStatus
GAMECLEARならGameClear画面を呼び出す
while True: clock.tick(60) event = view.main() pygame.display.update() if(event == GameState.Title): view = TitleView() elif(event == GameState.Gacha): view = GachaView() elif(event == GameState.Wait): view = WaitView(view.player) elif(event == GameState.Play): view = PlayView(view.player) elif(event == GameState.Gameover): view = GameoverView(view.player) elif(event == GameState.Gameclear): view = GameClearView(view.player) elif(event == GameState.Quit): pygame.quit() sys.exit() break elif(event == GameState.Pass): pass
これで画面遷移するように
あとはGameClearViewのメンテナンス
とりあえずGameClearView作成時に各ステージのクリアタイムを渡す
view = GameoverView(view.player) elif(event == GameState.Gameclear): - view = GameClearView(view.player) + view = GameClearView(view.player, view.clearTimes) elif(event == GameState.Quit):
あとは結果を張り付けるだけ!
def updateResultView(self): stageCount = len(self.clearTimes) stageNum = 1 totalTime = 0.0 for clearTime in self.clearTimes: clearTimeText = getText("Stage" + str(stageNum) + " : " + str(self.clearTimes[stageNum-1]), 30, WHITE) self.screen.blit(clearTimeText, (self.scr_rect.width//2 - 100, self.scr_rect.height//4 + (30 * stageNum))) totalTime += float(self.clearTimes[stageNum-1]) stageNum += 1 time = int(totalTime * 100) totalTime = time/100 clearTimeText = getText("TotalClearTime : "+ str(totalTime), 40, WHITE) self.screen.blit(clearTimeText, (self.scr_rect.width//8, self.scr_rect.height//4*3))
関数名が hogeView
なのが気に食わない・・・今はこれで。。
いい感じ
あとはどのキャラクターでクリアしたのかも表示したいので、ちょこっと修正
def updatePlayerView(self): text = getText("Player : " + self.player.NAME, 30, BLUE) self.screen.blit(text, (self.scr_rect.width//8 * 2 + 30, self.scr_rect.height//5*3 + 80)) image = pygame.transform.scale(self.player.image, (160, 160)) self.screen.blit(image, (self.scr_rect.width//4 * 3 , self.scr_rect.height//5*3 - 20))
マジックナンバーだらけ。
もう仕様変更不可\(^o^)/
完成。
あとはバランスを少し調整しておわり!! stage4と5は難しいので省略した
配布用にpyinstallerを使用
$pyinstaller [src.main.py] --clean --noconsole --onefile
exeの完成!!
暇だったら遊んでやってください(-"-)