この記事は横浜医療情報専門学校プログラミングクラブのAdvent Calendar 12月18日分の記事です。というか、忘れてたので急いで書いてます。
adventar.org
最近は訳あってプログラミング言語として Pythonばかり使ってるんですが、プログラミング言語の教育やら啓蒙(大げさ)のためには、「上辺と底辺の2つの値を入力して台形の面積を計算するプログラム」とか興味の湧かない計算をネタに学ぶのではなく、「なんか知らんけどカーソルキーで絵が動く」とか面白っぽいネタが必要と考えています。(ちなみに前者は昔に某高校の非常勤講師を受けた時に高校の先生がやっていた内容です。それを全否定してカリキュラム作り直しちゃいましたけど...)
という訳で、PythonでもGUIアプリを作る方法を調べたのですが、最初に調べた限りではどこのサイトでもどの書籍でも tkinter というライブラリを使う方法が紹介されていたんですよね。
そこで tkinter を使う方法を試行錯誤して、作品としてアクションゲーム(っぽいやつ)を作ってみたのですが、たくさんの敵キャラを動かしてみたところそれはもうカクカクで実用的ではない。その時に出した結論は『Pythonってアクションゲーム作りには向かない」でした。
しかし、ひょんなことから日経ソフトウェアのバックナンバーを見る機会があってその中で書かれていた記事が「pygameライブラリを使ってPythonでゲームを作る」ってやつだったので試したところこれがかなりイケルやつでした。まあ pygameライブラリって10年以上前からあるらしいんですが、出会いってそういうものですよね。出会ってなければ間違った結論のままだったわけで、そういうことって多いんだろうなと改めて実感。
とりあえず作りかけのアクションゲーム(っぽいもの)を以下に置いておきます。あくまで作りかけなので悪しからず。こなれたコードになってないことも悪しからず。
import pygame
import random
SCREEN_WIDTH = 452
SCREEN_HEIGHT = 352
COLOR_BLACK = (0,0,0)
COLOR_RED =(255,0,0)
DX = [-1, 0, 1, 0]
DY = [0, -1, 0, 1]
stageNumber = 1
bombKazu = 1
bombLength = 1
mapAll = open("./mapdata.txt", "r").readlines()
class MyChar(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.muki = 0
self.jyoutai = 0
self.images = []
for i in range(4):
self.images.append(pygame.image.load("./img/my" + str(i) + ".png"))
self.image = self.images[self.muki]
colorkey = self.image.get_at((0,0))
print(colorkey)
self.image.set_colorkey(colorkey)
self.rect = self.image.get_rect()
def changeImage(self):
self.image = self.images[self.muki]
class TekiChar(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.muki = 0
self.jyoutai = 0
self.images = []
for i in range(3):
self.images.append(pygame.image.load("./img/teki" + str(i) + ".png"))
self.image = self.images[self.muki]
self.rect = self.image.get_rect()
def update(self):
if self.jyoutai <= 0:
self.muki = random.randrange(4)
self.jyoutai = 32
xnext = (self.rect.x - 100) // 32 + DX[self.muki]
ynext = (self.rect.y ) // 32 + DY[self.muki]
if maps[ynext][xnext] != "0":
self.jyoutai = 0
else:
self.image = self.images[(self.rect.x + self.rect.y) % 3]
self.rect.x += DX[self.muki]
self.rect.y += DY[self.muki]
self.jyoutai -= 1
class Bomb(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.jyoutai = 0
def gamenByouga():
screen.fill(COLOR_BLACK)
for y in range(11):
for x in range(11):
if maps[y][x] == "8":
screen.blit(imgBlock, (x * 32 + 100, y * 32))
elif maps[y][x] == "9":
screen.blit(imgWall, (x * 32 + 100, y * 32))
elif maps[y][x] == "G":
screen.blit(imgDoor, (x * 32 + 100, y * 32))
else:
screen.blit(imgFloor, (x * 32 + 100, y * 32))
def mapsSetup():
global tekiCharGroup
tekiCharGroup = pygame.sprite.Group()
global maps
maps = []
for y in range(11):
maps.append(list(mapAll[(stageNumber - 1) * 12 + y]))
for x in range(11):
if maps[y][x] == "M":
myChar.rect.x = 32 * x + 100
myChar.rect.y = 32 * y
maps[y][x] = "0"
elif maps[y][x] == "E":
tekiChar = TekiChar()
tekiChar.rect.x = 32 * x + 100
tekiChar.rect.y = 32 * y
tekiCharGroup.add(tekiChar)
maps[y][x] = "0"
print(maps)
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
gameclock = pygame.time.Clock()
myCharGroup = pygame.sprite.Group()
myChar = MyChar()
myCharGroup.add(myChar)
tekiCharGroup = pygame.sprite.Group()
tekiChar = TekiChar()
tekiCharGroup.add(tekiChar)
imgFloor = pygame.image.load("./img/tileFloor.png").convert()
imgBlock = pygame.image.load("./img/tileBlock.png").convert()
imgWall = pygame.image.load("./img/tileWall.png").convert()
imgDoor = pygame.image.load("./img/tileDoor.png").convert()
mapsSetup()
for sprite in myCharGroup.sprites():
print(sprite)
for sprite in tekiCharGroup.sprites():
print(sprite)
endflag = 0
while endflag == 0:
for event in pygame.event.get():
if event.type == pygame.QUIT:
endflag = 1
keypress = pygame.key.get_pressed()
if myChar.jyoutai == 0:
if (keypress[pygame.K_LEFT]):
myChar.muki = 0
myChar.jyoutai = 8
elif (keypress[pygame.K_UP]):
myChar.muki = 1
myChar.jyoutai = 8
elif (keypress[pygame.K_RIGHT]):
myChar.muki = 2
myChar.jyoutai = 8
elif (keypress[pygame.K_DOWN]):
myChar.muki = 3
myChar.jyoutai = 8
myChar.changeImage()
else:
myChar.rect.x += (DX[myChar.muki] * 4)
myChar.rect.y += (DY[myChar.muki] * 4)
myChar.jyoutai -= 1
gamenByouga()
tekiCharGroup.update()
tekiCharGroup.draw(screen)
myCharGroup.draw(screen)
gameclock.tick(30)
pygame.display.flip()
pygame.quit()
うん、pygameいいよ皆さん始めましょう。というか、やっつけな記事でごめんなー。
明日の記事は、みんなのアイドル 五段パイセンによる『在学生向けポエム「横浜医療情報専門学校を卒業したあと学校と在校生に対して思うこと」』です。お楽しみに〜〜!