ゲームのキャラクタを作るのが苦手という人のために、キャラクタを使わなくて済むゲームを考えてみます。
表示は〇や四角形などと文字の描画のみとする。これで楽になります。 ゲームらしくするため動きがあること。
その例として数字記憶ゲームを作りました。
背景は写真です。だれでも手軽に用意できますね。
S キーを押せばスタートします。
黄色の〇の中に乱数で発生させた数字が右から左に移動します。
数字の表示が終了すると、次は数字入力になります。
全部の数字を入力すると採点が表示されます。
それではソースを見ていきましょう。
import pygame
from pygame.constants import KEYDOWN
import pygame.key
import pygame.event
import pygame.display
import pygame.draw as dw
import sys
import random
IDLE=0
SHOWING=1
ANSERING=3
RESULT=4
DEGITS = 4
RADIUS=30
CICLE_COL = (255, 216, 0)
TEXT_COL = (0, 0, 255)
KEY2STR={pygame.K_0:'0', pygame.K_KP0:'0',
pygame.K_1:'1', pygame.K_KP1:'1',
pygame.K_2:'2', pygame.K_KP1:'2',
pygame.K_3:'3', pygame.K_KP3:'3',
pygame.K_4:'4', pygame.K_KP4:'4',
pygame.K_5:'5', pygame.K_KP5:'5',
pygame.K_6:'6', pygame.K_KP6:'6',
pygame.K_7:'7', pygame.K_KP7:'7',
pygame.K_8:'8', pygame.K_KP8:'8',
pygame.K_9:'9', pygame.K_KP9:'9'
}
def makeNum(degits):
min = 10**(degits - 1)
max = 10**(degits) -1
num = random.randint(min, max)
strNum = str(num)
return strNum
def getKeyCode(key):
l = len(key)
for k in range(0, l):
if key[k] == True:
return k
return None
def showNum(screen, x, question, numCount):
dw.circle(screen, CICLE_COL, [x, 200], RADIUS, 0)
font = pygame.font.Font(None, 40)
txt = font.render(question[numCount], True, TEXT_COL)
screen.blit(txt, [x - 40 / 4 , 200 - 40 / 4])
x -= 8
if x < -RADIUS * 2:
numCount += 1
x = screen.get_width()
return x, numCount
def showAnser(screen ,anser, numCount):
x = RADIUS + 10
y = 400
font = pygame.font.Font(None, 40)
for i in range(0, numCount):
dw.circle(screen, (255,255,255), [x, y], RADIUS, 0)
txt = font.render(anser[i], True, TEXT_COL)
screen.blit(txt, [x - 40 / 4 , y - 40 / 4])
x += RADIUS * 2 + 8
def showQuestion(screen ,question, numCount):
x = RADIUS + 10
y = 300
font = pygame.font.Font(None, 40)
for i in range(0, numCount):
dw.circle(screen, CICLE_COL, [x, y], RADIUS, 0)
txt = font.render(question[i], True, (0,0,0))
screen.blit(txt, [x - 40 / 4 , y - 40 / 4])
x += RADIUS * 2 + 8
def compare(screen, question, anser, numCount):
x = RADIUS + 10
y = 400
for i in range(0,numCount):
if question[i] == anser[i]:
dw.circle(screen, (255,0,0), [x, y], RADIUS, 4)
else:
dw.line(screen, (255,0,0), [x - RADIUS, y - RADIUS], [x + RADIUS, y + RADIUS], 4)
dw.line(screen, (255,0,0), [x + RADIUS, y - RADIUS], [x - RADIUS, y + RADIUS], 4)
x += RADIUS * 2 + 8
def shoResult(screen, question, anser, numCount):
showQuestion(screen ,question, numCount)
showAnser(screen ,anser, numCount)
compare(screen, question, anser, numCount)
def main():
pygame.init()
pygame.display.set_caption("Pygame 数字の記憶ゲーム")
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
img_back = pygame.image.load('back.png')
x = screen.get_width()
font = pygame.font.Font(None, 120)
mode = IDLE
numCount = 0
anser = []
while True:
key = None
ky = None
for event in pygame.event.get():
if event.type == pygame.QUIT:
# 終了ボタンで終了
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
ky = event.key
name = pygame.key.name(event.key)
screen.fill((0,0,0))
screen.blit(img_back, [0,0])
#キーの取得
key = pygame.key.get_pressed()
if mode == IDLE:
if key[pygame.K_s]:
mode = SHOWING
numCount = 0
question = makeNum(DEGITS)
x = screen.get_width()
txt = font.render('S key:Start', True, (0,255, 0))
screen.blit(txt, [100, 100])
elif mode == SHOWING:
x, numCount = showNum(screen, x, question, numCount)
if numCount >= len(question):
anser.clear()
mode = ANSERING
numCount = 0
showAnser(screen, anser, numCount)
elif mode == ANSERING:
txt = font.render('Input Number', True, (0,255,0))
screen.blit(txt, [60, 100])
if ky != None:
strNum = KEY2STR.get(ky)
if strNum != None:
#数字が入力された
anser.insert(numCount, strNum)
numCount += 1
showAnser(screen, anser, numCount)
if numCount >= len(question):
mode = RESULT
elif mode == RESULT:
if key[pygame.K_s]:
mode = SHOWING
numCount = 0
question = makeNum(DEGITS)
x = screen.get_width()
txt = font.render('S key:Start', True, (0,255,0))
screen.blit(txt, [100, 100])
shoResult(screen, question, anser, numCount)
pygame.display.update()
clock.tick(10)#1秒間のフレーム数 100msec
if __name__ == '__main__':
main()
まず問題の作成です。
makeNum(degits)
degitsは桁数です。4桁の数字なら最少が1000、最大が9999です。10の4乗が1000、10の5乗からマイナス1すると9999です。
この結果で乱数を発生させます。そして採点をしやすいようにstrに変換しています。
次にキー入力です。
これは面倒です。何故ならpygame.key.get_pressed()で取得した数値データは
文字に関連付けされていません。 pygame.K_1 1のキー pygame.K_KP1:'テンキーの1 これを関連付けするため辞書KEY2STRを使います。
ここで問題なのはpygame.key.get_pressed()を使うと1回5と押したのに何回も5が入力されてしまいます。
これはゲームの特性上こうでなければなりません。これを回避するにはイベントで pygame.KEYDOWNがあります。
これを使って問題を回避しました。
pygame.KEYDOWを使うともっと簡単にできそうなのでやってみました。
import pygame
from pygame.constants import KEYDOWN
import pygame.key
import pygame.event
import pygame.display
import pygame.draw as dw
import sys
import random
IDLE=0
SHOWING=1
ANSERING=3
RESULT=4
DEGITS = 7 #問題の桁数
RADIUS=30
CICLE_COL = (255, 216, 0)
TEXT_COL = (0, 0, 255)
def makeNum(degits):
min = 10**(degits - 1)
max = 10**(degits) -1
num = random.randint(min, max)
strNum = str(num)
return strNum
def showNum(screen, x, question, numCount):
dw.circle(screen, CICLE_COL, [x, 200], RADIUS, 0)
font = pygame.font.Font(None, 40)
txt = font.render(question[numCount], True, TEXT_COL)
screen.blit(txt, [x - 40 / 4 , 200 - 40 / 4])
x -= 8
if x < -RADIUS * 2:
numCount += 1
x = screen.get_width()
return x, numCount
def showAnser(screen ,anser, numCount):
x = RADIUS + 10
y = 400
font = pygame.font.Font(None, 40)
for i in range(0, numCount):
dw.circle(screen, (255,255,255), [x, y], RADIUS, 0)
txt = font.render(anser[i], True, TEXT_COL)
screen.blit(txt, [x - 40 / 4 , y - 40 / 4])
x += RADIUS * 2 + 8
def showQuestion(screen ,question, numCount):
x = RADIUS + 10
y = 300
font = pygame.font.Font(None, 40)
for i in range(0, numCount):
dw.circle(screen, CICLE_COL, [x, y], RADIUS, 0)
txt = font.render(question[i], True, (0,0,0))
screen.blit(txt, [x - 40 / 4 , y - 40 / 4])
x += RADIUS * 2 + 8
def compare(screen, question, anser, numCount):
x = RADIUS + 10
y = 400
for i in range(0,numCount):
if question[i] == anser[i]:
dw.circle(screen, (255,0,0), [x, y], RADIUS, 4)
else:
dw.line(screen, (255,0,0), [x - RADIUS, y - RADIUS], [x + RADIUS, y + RADIUS], 4)
dw.line(screen, (255,0,0), [x + RADIUS, y - RADIUS], [x - RADIUS, y + RADIUS], 4)
x += RADIUS * 2 + 8
def shoResult(screen, question, anser, numCount):
showQuestion(screen ,question, numCount)
showAnser(screen ,anser, numCount)
compare(screen, question, anser, numCount)
def main():
pygame.init()
pygame.display.set_caption("Pygame 数字の記憶ゲーム")
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
img_back = pygame.image.load('back.png')
x = screen.get_width()
font = pygame.font.Font(None, 120)
mode = IDLE
numCount = 0
anser = []
while True:
keyName = ''
for event in pygame.event.get():
if event.type == pygame.QUIT:
# 終了ボタンで終了
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
keyName = pygame.key.name(event.key)
keyName = keyName.replace('[', '')
keyName = keyName.replace(']', '')
screen.fill((0,0,0))
screen.blit(img_back, [0,0])
if mode == IDLE:
if keyName == 's':
mode = SHOWING
numCount = 0
question = makeNum(DEGITS)
x = screen.get_width()
txt = font.render('S key:Start', True, (0,255, 0))
screen.blit(txt, [100, 100])
elif mode == SHOWING:
x, numCount = showNum(screen, x, question, numCount)
if numCount >= len(question):
anser.clear()
mode = ANSERING
numCount = 0
showAnser(screen, anser, numCount)
elif mode == ANSERING:
txt = font.render('Input Number', True, (0,255,0))
screen.blit(txt, [60, 100])
if keyName >= '0' and keyName <= '9':
#数字が入力された
anser.insert(numCount, keyName)
numCount += 1
showAnser(screen, anser, numCount)
if numCount >= len(question):
mode = RESULT
elif mode == RESULT:
if keyName == 's':
mode = SHOWING
numCount = 0
question = makeNum(DEGITS)
x = screen.get_width()
txt = font.render('S key:Start', True, (0,255,0))
screen.blit(txt, [100, 100])
shoResult(screen, question, anser, numCount)
pygame.display.update()
clock.tick(10)#1秒間のフレーム数 100msec
if __name__ == '__main__':
main()
またまた、テンキーは曲者です。例えばテンキーの2は[2]という名前になります。[]を削除しなければなりません。
if event.type == pygame.KEYDOWN:
keyName = pygame.key.name(event.key)
keyName = keyName.replace('[', '')
keyName = keyName.replace(']', '')
これでソースがスッキリしました。
|