HaLake Magazine

コワーキングスペースHaLakeの技術情報発信サイト!IoT,AR,VRなど最新技術情報をお届け!

Python:お粗末でもゲームを作ってみる!【Pygame】

f:id:mischief_cat:20200719174255p:plain 今回はPythonのライブラリPygameを使ってゲームを作っていきたいと思います。 PygamePythonでゲームを作るライブラリの中で一般的ではありますが初心者の私からすると少し難しく感じました。 Python自体もそこまで自信がないので今回できたことを備忘録程度にまとめていきたいと思います。

前提条件

Pythonの開発環境が整っていること

目次

  1. ライブラリのインストール
  2. 前準備
  3. プログラム
  4. 動作確認
  5. まとめ

ライブラリのインストール

まず初めにPygameライブラリが必要なのでインストールから始めます。
以下の説明は私がPython3を使っているのでpip3コマンドを使っていきますが環境のバージョンに合わせてpipコマンドを使ってください。

pip3 install pygame

でインストールできます。そして確認は

pip3 list

コマンドで自分がインストールしたライブラリの一覧が出てきます。 画像下部のようにpygameが存在すれば完了です。 f:id:mischief_cat:20200719102100p:plain

前準備

次に今回はお粗末なゲームを作るうえで見栄えとわかりやすいように画像を使用するので少し説明していきたいと思います。

  • 注意:ネットに落ちている画像を使う場合は著作権などに注意して使ってください。

今回使う画像はこちらからダウンロードさせていただきました。

opengameart.org

まずは画像の保存場所を決めましょう。
プログラムと画像を保存したいファイルを作ります。私はわかりやすくデスクトップにファイルを作り説明していきますが、それぞれの環境に合わせて決めてください。

\Users\UserName\Desktop\test

デスクトップにtestファイルを作りここにプログラムと画像や音のファイルを追加していきます。
Pygameで使える画像のフォーマットは下記のサイトを参考にさせて頂きました。 shizenkarasuzon.hatenablog.com 要約すると身近なJPG、PNGが対応しているとのことで、GIFは静止画のみが読み込まれるようです。なるべく前者の2つを使用するのがいいと思います。

プログラム

次にプログラムの説明をしていきたいと思います。自分もあまり理解できていない点があるので浅広な内容になってしまいますがご了承ください。
単純なモグラたたきに似て非なるものを作ってみました。

import pygame
from pygame.locals import *
import sys
import random
import time

class MySprite(pygame.sprite.Sprite): #スプライトクラス
    def __init__(self, filename, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load(filename).convert_alpha()
        width = self.image.get_width()
        height = self.image.get_height()
        self.rect = Rect(x, y, width, height)

    def update(self):
        self.kill()

def main():
    pygame.init()
    (w,h) = (800,600)   # 画面サイズ
    (x,y) = (200, 200)  # プレイヤー画像の初期配置座標
    pygame.init()       # pygame初期化
    font = pygame.font.Font(None, 40)                            #フォントの初期設定
    punch_count = 0
    count = 0
    screen = pygame.display.set_mode((w, h), 0, 0)              #画面設定
    screen = pygame.display.get_surface()
    pygame.display.set_caption("Test")                           #タイトルバーに表示する
    player = pygame.image.load("hogehoge.png").convert_alpha()      #プレイヤー画像の取得
    times_x = int(player.get_width() * 1.5)                      #画像の幅の1.5倍を取得
    times_y = int(player.get_height() * 1.5)                     #画像の高さの1.5倍を取得
    player = pygame.transform.scale(player, (times_x, times_y))  #1.5倍に拡大
    bg = pygame.image.load("hogehoge.png").convert_alpha()             #背景画像の取得
    rect_bg = bg.get_rect()
    pygame.mixer.init(frequency = 44100)                         #音用の初期設定
    group = pygame.sprite.RenderUpdates()                        #スプライトグループの作成
    clock = pygame.time.Clock()
    now_count = False

    start_time = time.time()
    while True:
        if  now_count == True:
            if (time.time() - count) >= del_sec:
                group.update()
                now_count = False
        else:
            del_sec = random.uniform(0.3,1.5) #出現と消滅頻度(乱数)
            count = time.time()
            #////敵の出現場所をランダムに選ぶ(乱数生成の範囲を変えることで出現場所を変えられる)
            enemy_x = random.randint(0,700)
            enemy_y = random.randint(200,500)
            enemy_x = random.randint(0,700)
            enemy_y = random.randint(200,500)
            enemy1 = MySprite("hogehoge.png", enemy_x, enemy_y)                #敵の画像を指定
            #////
            group.add(enemy1)
            now_count = True

        clock.tick(60)                                                       # 60fps
        screen.blit(bg, rect_bg)                                             #背景
        group.draw(screen)                                                   #グループの描画
        screen.blit(player, (x, y))                                          #プレイヤー画像の描画 0,0座標から幅44px高さ66pxだけ切り抜く
        text = font.render("COUNT:" + str(punch_count), True, (255,255,255)) #テキストの描画
        screen.blit(text, [0, 0])                                      #表示位置
        pygame.display.update()                                        #描画のアップデート

        for event in pygame.event.get():
            # マウスポインタで画像も移動
            if event.type == MOUSEMOTION:
                x, y = event.pos
                x -= int(player.get_width() / 2)
                y -= int(player.get_height() / 2)
            
            # 敵上でマウスがクリックされたか判定
            if (event.type == pygame.MOUSEBUTTONDOWN) and (event.button == 1) :
                #////クリックしたときの音
                # pygame.mixer.music.load("") #引数にwaveやmp3のファイル名を指定することによって音が出せる
                # pygame.mixer.music.play(1) #引数は1or-1で一回orループ
                #////
                if enemy1.rect.collidepoint(event.pos):
                    #////敵にカーソルを合わせてクリックしたときの音
                    # pygame.mixer.music.load("") #引数にwaveやmp3のファイル名を指定することによって音が出せる
                    # pygame.mixer.music.play(1) ##引数は1or-1で一回orループ
                    #////
                    group.update()
                    now_count = False
                    print("Hit!!")
                    punch_count += 1


            # 終了用のイベント処理
            if event.type == QUIT:          #×ボタンが押されたとき
                pygame.quit()
                sys.exit()
            if event.type == KEYDOWN:       # キーを押したとき
                if event.key == K_ESCAPE:   # Escキーが押されたとき
                    pygame.quit()
                    sys.exit()
main()

動作確認もしたい方はこちらを画像が保存されているフォルダと同じ場所にプログラムを保存してください。そして以下の文を読んで書き換える作業を行ってください。
コメントで大まかな説明はしていますが強調と追加説明をしていきます。

(w,h) = (800,600)   # 画面サイズ

ここで指定するサイズは背景に使う画像を同じサイズにしておくことをお勧めします。

~
player = pygame.image.load("hogehoge.png").convert_alpha()      #プレイヤー画像の取得
~
bg = pygame.image.load("hogehoge.png").convert_alpha()             #背景画像の取得
~
enemy1 = MySprite("hogehoge.png", enemy_x, enemy_y)                #敵の画像を指定
~

上記三つの項目のhogehoge.pngの場所をそれぞれ対応する画像の名前に書き換えてください。もちろん例ではpngになっていますが拡張子も合わせて書き換えてください。

  # pygame.mixer.music.load("") #引数にwaveやmp3のファイル名を指定することによって音が出せる

そのままだと使えないので引数に画像を保存したファイルの同じ階層に置いてあるwaveまたはmp3ファイルを指定してあげることで音を鳴らすことが出来ます。 使う場合はコメント化されているので解除してから使ってください。

pygame.display.update()                                        #描画のアップデート

描画のアップデートをすることによって手前のscreen.blite()などで宣言したもの表示するのでアップデートをかけるタイミングを間違えるとうまく表示されなかったりします。

あとはスプライトのグループなんかを使ったりしていますが、出現させるものを一体に絞っているので使わなくてもいいと思います。使ってみたかったのと書き方がいまいちわからなかったので先人の知恵(サイト)を借りて採用しました。
いまいちスプライトやグループの使い方がわかっていないので遠回りしているかもしれませんがご了承ください。 参考にさせて頂いサイトはこちらです。

algorithm.joho.info

westplain.sakuraweb.com

teratail.com

aidiary.hatenablog.com

動作確認

次に動作確認をしていきます。
先ほどのプログラムを実行してみましょう。私の場合はコマンドプロンプトで保存してあるディレクトリアで移動して

cd \Uses\UserName\Desktop\test

testGame.pyで保存したので

python3 testGame.py

で実行します。そうすると f:id:mischief_cat:20200719165931p:plain こんな感じになりました。
画像は前述したサイトと背景はHaLaKeの写真を使ってみました。
画像はそれぞれで用意してもらう必要がありますので好きな画像を使って楽しんでみてください。
内容は敵の画像の上にカーソルを合わせてクリックすると左上のカウンタが増えるのでそれだけです。
f:id:mischief_cat:20200719170818p:plain 前述したように音声を付けると少しはそれなりの雰囲気にはなります。(妥協)

まとめ

Pygameは初心者にとっては少し難しいと感じました。時間をかければもっといろいろなこともできると思いますが、本格的なゲームを作る気もないのと時間もないのでここまでにします。プログラムも雑だったり間違っている部分もあるかと思いますが誰かの参考になれば幸いです。