【簡単?】初心者がpython3とpygameでヒット&ブローゲーム作ってみる #03 画面作るよ【習作?】
前回は、テキストベースで作ったヒット&ブローゲームにpygameのガワをかぶせるべく、簡易的な状態遷移の処理を書いてみました。 今回は、画面の構成を作っていきます。

前回から
【簡単?】初心者がpython3とpygameでヒット&ブローゲーム作ってみる【習作?】 - 工学じじいの縁側日記
【簡単?】初心者がpython3とpygameでヒット&ブローゲーム作ってみる #02【習作?】 - 工学じじいの縁側日記
前回は、テキストベースで作ったヒット&ブローゲームにpygameのガワをかぶせるべく、簡易的な状態遷移の処理を書いてみました。
今回は、画面の構成を作っていきます。
画面構成
完成イメージは、こんな感じです。

左側上部に、答えの入力欄が数字4桁で、画面左側下部に0~9の数字が並んでいて、押した順に上部の入力欄に入力されます。
左側には、現在までの、解答の履歴と、その時のヒット数、ブロー数が一覧で並んでいます。
15回×4ページ分の履歴を保存できるようにします。それで答えられなかったらゲームオーバーです。
まず、入力欄から作っていきます。
画面の作成 その1 入力欄
今回使う画像の一覧(次に使うのも入ってます。。。)は、以下のようになっています。
Webのフリー素材でもいいですし、適当にofficeの作図機能で作ってもいいと思います。
githubにもあるので、僕の作ったので良ければどうぞ。

初めに読み込む画像は、数字とアスタリスクの画像 [00.png, 11.png, 22,png ~ 99.png, kome.png] です。
読み込みやすいように、連番のファイル名にしておいたので、このファイル名が並んだリストを作ります。
画像は、プロジェクトフォルダ配下の「images」フォルダに全て納めてあります。
qfilestr = [] # 画像ファイル名を生成するためのリスト
for i in range(10): # 問題の方の画像ファイルは 00.png~99.pngの名前になっている。
qfilestr.append(str(i)+str(i) + ".png") # 画像ファイル名を生成
次に、画面上での、解答欄の貼り付け位置を表す矩形(pygame.Rect型)を用意します。
数字1個当たりの画像の大きさは(幅、高さ)=(100,100)です。これを、図のように並べていきます。
margin = [100, 100] # *を表示する位置までのマージン
imagesize = [100,100] # 画像1個当たりの大きさ
qbuttonrect = [] # *を表示するための矩形を作成 *のサイズは(100,100)
for i in range(4): #marginの位置から4つ横に画像を並べるためのもの
qbuttonrect.append(Rect(margin[0] + i * imagesize[1], margin[1], *imagesize))
これらを使って、いつものpygame.image.loadで読み込んでいきます。
ここまでの部分をまとめると以下のようになります。
margin = [100, 100] # *を表示する位置までのマージン
imagesize = [100,100] # 画像1個当たりの大きさ
qfilestr = [] # 画像ファイル名を生成するためのリスト
qimagelist = [] # 出題用の画像を保存しておくリスト0~9+*の画像が収まっている。
for i in range(10): # 問題の方の画像ファイルは 00.png~99.pngの名前になっている。
qfilestr.append(str(i)+str(i) + ".png") # 画像ファイル名を生成
for i in range(10): # 画像の読み込み
qimagelist.append(pygame.image.load("./images/" + qfilestr[i]))
#[00.png, 11.png, 22.png … 99.png, kome.png]
qimagelist.append(pygame.image.load("./images/kome.png")) # *の画像の読み込み
qbuttonrect = [] # *を表示するための矩形を作成 *のサイズは(100,100)
for i in range(4): #marginの位置から4つ横に画像を並べるためのもの
qbuttonrect.append(Rect(margin[0] + i * imagesize[1], margin[1], *imagesize))
最後、連番の名前ではない、アスタリスクの画像(kome.png)を別口でロードしてリストに追加しているところに注意してください。
リストの中身は、[00.png, 11.png, 22.png … 99.png, kome.png] の順に並んでいます。(qimagelist[10] がkome.pngです)
入力欄 描画処理を書く
先ほどの読み込んだ画像のリスト(qimagelist)と、それを貼り付けるための位置を表す矩形(qbuttonrect)をつかって、ゲーム画面に画像を貼り付けます。
処理自体は、qimagelist[10]のアスタリスク画像を、qbuttonrect[0]~qbuttonrect[3]の位置に貼り付けるだけですので簡単です。
for i in range(4):
screen.blit(qimagelist[10], qbuttonrect[i])
問題はこれをどこのタイミングで描画するか、です。
前回やったシーン切り替えのことを考えると、スタートボタンが押されたら、ゲームが始まったほうがそれっぽいですよね。
ということで、
gamescene==1のとき、すなわちゲーム中の時に入力欄を表示するのが自然な気がします。
すなわち、前回のボタンを表示した部分で、以下の様に描画処理を書きます。
if gamescene == 0:
screen.blit(gamebutton[0], gamebuttonrect)
elif gamescene == 1:
for i in range(4):
screen.blit(qimagelist[10], qbuttonrect[i])
screen.blit(gamebutton[1], gamebuttonrect)
elif gamescene ==2:
screen.blit(gamebutton[2], gamebuttonrect)
else:
print("error")
これで、ゲームスタートを押すと****と、アスタリスクが4つ表示されるはずです。

入力用ボタンとなる数字画像の表示
入力用のボタンとなる数字画像(画面左側下部)を読み込んで表示します。
処理の内容は先ほどと変わらないので、コードのみ掲載しておきます。
nmargin = [50, 350] # 入力ボタンのためのマージン
filestr = [] # 画像ファイル名を収めるリスト
for i in range(10): # 読み込む画像ファイル名のリストを作る
filestr.append(str(i) + ".png")
imagelist = [] # 読み込んだ画像のリスト
for i in range(10):
imagelist.append(pygame.image.load("./images/" + filestr[i])) #ファイルの読み込み
buttonrect = [] # 画像ファイルの貼り付け位置が収められたリスト(Rect型)
for i in range(5): # 0~4の画像の位置
buttonrect.append(Rect(nmargin[0] + i * imagesize[0], nmargin[1], *imagesize))
for i in range(5, 10): # 5~9の画像の位置
buttonrect.append(Rect(nmargin[0] + (i - 5) * imagesize[0], nmargin[1]+imagesize[1], *imagesize))
入力用数字の画像を描画するコードの追加
これも同様に
gamescene==1の時に、描画されるように、追加します。
if gamescene == 0:
screen.blit(gamebutton[0], gamebuttonrect)
elif gamescene == 1:
for i in range(4): # 入力された数字を表示する領域
screen.blit(qimagelist[10], qbuttonrect[i])
for i in range(5): # 入力のためのボタンとなる画像0~4
screen.blit(imagelist[i], buttonrect[i])
for i in range(5, 10): # 入力のためのボタンとなる画像5~9
screen.blit(imagelist[i], buttonrect[i])
screen.blit(gamebutton[1], gamebuttonrect)
elif gamescene ==2:
screen.blit(gamebutton[2], gamebuttonrect)
else:
print("error")
実行してみます。
game start ボタンを押すと、以下の画面が出れば成功です。

なんとなく、どんな感じのゲームになるか見えてきましたね。
ここまでのソースコード一覧です。
from pygame.locals import *
import pygame
import sys
import random
def main():
gamescene = 0 # 0 タイトル、1 ゲーム中、2 ゲームオーバー、-1 エラー
pygame.init() # Pygameを初期化
screen = pygame.display.set_mode((900, 600)) # 画面を作成
pygame.display.set_caption("Hit & Blow game")
gamebutton = []
gamebuttonrect = Rect(200, 250, 200, 50) # 画像の表示位置を表す矩形
gamebutton.append(pygame.image.load("./images/pushstart.png"))
gamebutton.append(pygame.image.load("./images/judge.png"))
gamebutton.append(pygame.image.load("./images/gameover.png"))
margin = [100, 100] # *を表示する位置までのマージン
imagesize = [100,100] # 画像1個当たりの大きさ
qfilestr = [] # 画像ファイル名を生成するためのリスト
qimagelist = [] # 出題用の画像を保存しておくリスト0~9+*の画像が収まっている。
for i in range(10): # 問題の方の画像ファイルは 00.png~99.pngの名前になっている。
qfilestr.append(str(i)+str(i) + ".png") # 画像ファイル名を生成
for i in range(10): # 画像の読み込み
qimagelist.append(pygame.image.load("./images/" + qfilestr[i]))
qimagelist.append(pygame.image.load("./images/kome.png")) # *の画像の読み込み
#[00.png, 11.png, 22.png … 99.png, kome.png]
qbuttonrect = [] # *を表示するための矩形を作成 *のサイズは(100,100)
for i in range(4): #marginの位置から4つ横に画像を並べるためのもの
qbuttonrect.append(Rect(margin[0] + i * imagesize[1], margin[1], *imagesize))
nmargin = [50, 350] # 入力ボタンのためのマージン
filestr = [] # 画像ファイル名を収めるリスト
for i in range(10): # 読み込む画像ファイル名のリストを作る
filestr.append(str(i) + ".png")
imagelist = [] # 読み込んだ画像のリスト
for i in range(10):
imagelist.append(pygame.image.load("./images/" + filestr[i])) #ファイルの読み込み
buttonrect = [] # 画像ファイルの貼り付け位置が収められたリスト(Rect型)
for i in range(5): # 0~4の画像の位置
buttonrect.append(Rect(nmargin[0] + i * imagesize[0], nmargin[1], *imagesize))
for i in range(5, 10): # 5~9の画像の位置
buttonrect.append(Rect(nmargin[0] + (i - 5) * imagesize[0], nmargin[1]+imagesize[1], *imagesize))
running = True
# メインループ
while running:
screen.fill((100, 100, 100)) # 背景色で塗る
# この時点では、 screen.blit(gamebutton[gamescene], gamebuttonrect) で済むけど、
# とりあえずは、if文でわけておく
if gamescene == 0:
screen.blit(gamebutton[0], gamebuttonrect)
elif gamescene == 1:
for i in range(4): # 入力された数字を表示する領域
screen.blit(qimagelist[10], qbuttonrect[i])
for i in range(5): # 入力のためのボタンとなる画像0~4
screen.blit(imagelist[i], buttonrect[i])
for i in range(5, 10): # 入力のためのボタンとなる画像5~9
screen.blit(imagelist[i], buttonrect[i])
screen.blit(gamebutton[1], gamebuttonrect)
elif gamescene ==2:
screen.blit(gamebutton[2], gamebuttonrect)
else:
print("error")
for event in pygame.event.get():
if event.type == QUIT: # 終了イベント
running = False
pygame.quit() # pygameのウィンドウを閉じる
sys.exit() # システム終了
if (event.type == pygame.MOUSEBUTTONUP) and (event.button == 1):
if gamebuttonrect.collidepoint(event.pos):
if gamescene == 0:
gamescene = 1
elif gamescene == 1:
gamescene = 2
elif gamescene == 2:
gamescene = 0
else:
gamescene = -1
pygame.display.update() # 描画処理を実行
if __name__ == "__main__":
main()
次回
今回のソースコード一式はgithubにもあります。
https://github.com/gomta777/hitandblow/
のcreategamescreenが今回のものです。
次回は、入力の処理を仕上げていきたいと思います。
よかったら、ブログ村↓のクリックお願いします。