【Pygame】放置ゲームのプロトタイプを作ってみた
Pygameで放置ゲームのプロトタイプ的なプログラムを作ってみました。
超絶シンプルな仕様
- 円をクリックするとリソース+1。
- オートマトンの部分をクリックすると、リソースが足りていた時のみレベルが上がってプロデュースが増加。
- プログラムを終了後再起動すると経過時間に応じてリソースがもらえる。
各部分の英単語は適当です。
ソースコード
#インポート
import pygame
import time
from pygame.locals import *
import sys
#クラス
class App:
#コンストラクタ
def __init__(self):
#初期化
self.running=True
self.fps=15
self.resouce=0
self.produce=0
self.level=0
self.clock=pygame.time.Clock()
self.res=None
self.t=None
#ウインドウの設定
self.screen=pygame.display.set_mode((600,600))
pygame.display.set_caption("Producing & Developing")
#セーブデータ読み込み
try:
with open("data.txt") as f:
self.t=int(time.time())
t_b=None
l=[s.rstrip() for s in f.readlines()]
if len(l)==3:
for i in range(len(l)):
l[i]=int(l[i])
t_b=l[0]
self.resouce=l[1]
self.level=l[2]
self.t-=t_b
self.produce=self.level
for i in range(self.level//10):
self.produce*=2
self.res=self.produce*self.t
self.resouce+=self.res
except:pass
#フォントの設定
self.font=pygame.font.SysFont("Menlo",30)
self.f_b=pygame.font.SysFont("Menlo",15)
#一秒間隔でタイマーを設定
pygame.time.set_timer(1,1000)
#更新処理
self.run()
#更新関数
def run(self):
#ループ
while self.running:
#fpsを設定
self.clock.tick(self.fps)
#イベント取得
for event in pygame.event.get():
#終了処理
if event.type==QUIT:
self.running=False
s=int(time.time())
#セーブ
with open("data.txt",mode="w") as f:
f.write("\n".join([str(s),str(self.resouce),str(self.level)]))
#プログラムを終了
pygame.mixer.stop()
pygame.quit()
sys.exit()
#マウスクリック
elif event.type==MOUSEBUTTONDOWN:
btn=event.button
x,y=event.pos
if btn==1 and x>=150 and x<=300 and y>=225 and y<=375:
self.resouce+=1
elif x>=150 and y<=495 and y>=450 and x<=385:
if self.resouce>=(self.level+1)*10+200*(self.level//10)**2:
self.resouce-=(self.level+1)*10+200*(self.level//10)**2
self.level+=1
#タイマーに対してリソースの所持数を更新
elif event.type==1:
self.resouce+=self.produce
#エスケープキーで画面遷移
elif event.type==KEYDOWN:
if event.key==K_ESCAPE:
self.res=None
self.screen.fill((0,0,0))
#毎秒生産量を計算
self.produce=self.level
for i in range(self.level//10):
self.produce*=1.5
#描画処理
#描画の順番:円->通常テキスト->放置テキスト
self.txt=[self.font.render("Resouce:%5g"%(self.resouce),True,(255,255,255),(0,0,0)),
self.font.render("Produce:%3g/s"%(self.produce),True,(255,255,255),(0,0,0)),
self.font.render("AutomatonLv:%d"%(self.level),True,(0,0,0),(255,255,255)),
self.f_b.render("Necessary:%3d"%((self.level+1)*10+200*(self.level//10)**2),True,(255,255,255),(0,0,0))]
#放置情報
if self.res!=None:
self.spec=self.f_b.render("Game was frozen for %d seconds"%(self.t),True,(255,0,0),(0,0,0))
self.spec_b=self.f_b.render("Resouce + %d"%(self.res),True,(255,0,0),(0,0,0))
self.end=self.f_b.render("Plese press to ESC",True,(255,255,255),(0,0,0))
self.screen.blit(self.spec,(50,300))
self.screen.blit(self.spec_b,(50,340))
self.screen.blit(self.end,(50,380))
self.screen.blit(self.txt[1],(150,55))
self.screen.blit(self.txt[0],(150,15))
self.screen.blit(self.txt[2],(150,450))
self.screen.blit(self.txt[3],(150,485))
#アップデート
pygame.display.update()
#サークルの描画
pygame.draw.circle(self.screen,(255,255,255),(225,300),75)
#メイン
if __name__=="__main__":
#pygame初期化
pygame.init()
pygame.mixer.init()
#インスタンス生成
main=App()
解説
といっても、そこまで解説することはありません。
インターフェース部分は「クリックに反応してリソースを加算する」ということと、「規定のリソースを消費してプロデュースを加算する」というシンプルな構成です。更新処理も一秒ごとにプロデュースの値分リソースを増加させるということをやるだけ。放置ゲームは意外と単純なロジックで実装できます。
肝は開始時のロード処理と終了時のセーブ処理です。終了時、このプログラムはセーブファイルにtime.time()
の値とリソースの値、オートマトンのレベルを書き込みます。次回起動時は初めにその三つを読み込むわけです。リソースの値はそのままリソースに、オートマトンのレベルはオートマトンのレベルに反映したのち、プロデュースの値の計算に使います。time.time()
の値は前回の終了時刻を示すため、それとは別に今回の開始時刻をtime.time()
を計算し差を取ることで経過時間を計算します。その経過時間とプロデュースをかけた値が「放置報酬」として通知、加算される仕組みです。
pygameを触っていて思ったこと
普段はドット絵ばかり扱っているため、描画関係を考えるのが大変でした。もう少し更新だとか描画の上下関係とか画面遷移とか、その辺を楽に管理できるといいんですが。
描画の内容を簡潔に表現できるライブラリがあればいいなあ。