概要
皆さんこんにちは。Pythonマスターブログです。
本シリーズではPythonでゲーム開発をする方法を解説してゆきます
最終的にはフリー素材でスマブラに似たゲームを作成することを目標にしてゆきます
今回の動画の内容は次の通りです
ゲーム開発用のライブラリの準備
背景画像のロード
コントローラーによるキャラクターの左右移動
の3点です
Pythonでゲーム開発をするためのライブラリで有名なものにはpygameやpanda3Dが挙げられます
pygameは二次元のゲームをpanda3Dは三次元のゲームを作成できます
実際のスマブラは三次元のゲームですが、今回は簡単にできるpygameを使用してゆきます
開発環境の構築
まずはゲーム開発のための環境を構築します
はじめにPythonをインストールします

まず、pythonのダウンロードサイトへアクセスし、pythonインストーラーをダウンロードします

インストーラーを起動し、Add python.exe to PATHにチェックをいれてInstall Nowを実行します
インストールが完了したらcloseをクリックします
これでPythonのインストールは完了です
次にpygameのインストールを行いましょう
PCに直接、pygameをインストールしてもよいのですが、
pygameをインストールする前に仮想環境を作成することにしましょう
仮想環境を作ることで、複数の開発環境を切り替えることができるようになります

まずは仮想環境の作成についてです
windows PowerShellまたはコマンドプロンプトを起動します
python -m venv <仮想環境名>と入力し実行します

画面上のパスのactivate.ps1を実行します
コマンドラインの左側に仮想環境名が表示されるようになりました
ここに現在使用している仮想環境が表示されます
次にpygameをインストールしましょう

仮想環境が適用されている状態でpip install pygameと入力し実行します
するとpygameのインストールが行われます

インストールが関したのちにpython -m pygame.examples.chimpと実行すると
チンパンジーを叩くサンプルゲームを実行できます
背景画面ロード
import pygame
pygame.init()
#################################################################################
# main関数
#################################################################################
def main():
screen = pygame.display.set_mode((1920, 1080))
bg = pygame.image.load("img\\bg_dote.jpg")
bg = pygame.transform.scale(bg, (1920, 1080))
clock = pygame.time.Clock()
done = False
while not done:
screen.blit(bg, (0, 0))
# 描画更新
pygame.display.flip()
clock.tick(60)
if __name__ == "__main__":
main()
pygame.quit()
これでPythonでゲーム開発をする準備が完了してきましたので、いよいよゲーム開発を開始します
まずは背景画面をロードするところまで解説します
最初にimport pygameでpygameをインポートし、pygame.init()でpygameを初期化します
次にpygame.display.set_modeでスクリーンのサイズを設定します
ここではできるだけ画面を使いたいので1920、1280に設定します
次にpygame.image.loadで背景画像をロードします
ロードしたデータをpygame.transform.scaleに入力することで背景画像のサイズを変更します
そしてループ処理の中にscreen.blitを記述することで画像を描画できます
そのあとにpygame.display.flipも記載しましょう
pygame.display.flipを実行することでディスプレイが更新されます。これを実行しないと背景画像が表示されません
次にフレームレートの制御を行います
ゲームで流れる映像は静止画の連続です。この静止画をフレームと呼びます
そして1秒間に何個の静止画が流れるかを示す数値をフレームレートと呼びます
本家のスマブラのフレームレートは60です。つまり1秒間に60個の静止画が流れますので
こちらで作成するゲームでもいったんフレームレートを60に設定しておきましょう
フレームレートの設定方法はclock = pygame.time.Clock()で時間管理のオブジェクトを作成し、
ループ処理の中でclock.tick(60)という処理を記述します
これで試しにpython main.pyを実行してみましょう
スクリーン一杯にこのような画像が表示されます
停止する際にはTABキー+ALTキーでPowerShellをアクティブにし、Ctrl+Cで中断できます
コントローラーの入力
import pygame
pygame.init()
class TextPrint:
def __init__(self):
self.reset()
self.font = pygame.font.Font(None, 25)
def tprint(self, screen, text):
text_bitmap = self.font.render(text, True, (0, 0, 0))
screen.blit(text_bitmap, (self.x, self.y))
self.y += self.line_height
def reset(self):
self.x = 10
self.y = 10
self.line_height = 15
def indent(self):
self.x += 10
def unindent(self):
self.x -= 10
def draw_input_info(screen, joystick, text_print):
text_print.reset()
axes = joystick.get_numaxes()
text_print.tprint(screen, f"Number of axes: {axes}")
text_print.indent()
for i in range(axes):
axis = joystick.get_axis(i)
text_print.tprint(screen, f"Axis {i} value: {axis:>6.3f}")
text_print.unindent()
buttons = joystick.get_numbuttons()
text_print.tprint(screen, f"Number of buttons: {buttons}")
text_print.indent()
for i in range(buttons):
button = joystick.get_button(i)
text_print.tprint(screen, f"Button {i:>2} value: {button}")
text_print.unindent()
#################################################################################
# main関数
#################################################################################
def main():
screen = pygame.display.set_mode((1920, 1080))
bg = pygame.image.load("img\\bg_dote.jpg")
bg = pygame.transform.scale(bg, (1920, 1080))
clock = pygame.time.Clock()
text_print = TextPrint()
joystick = pygame.joystick.Joystick(0)
done = False
while not done:
screen.blit(bg, (0, 0))
draw_input_info(screen, joystick, text_print)
pygame.event.get()
# 描画更新
pygame.display.flip()
clock.tick(30) / 1000
if __name__ == "__main__":
main()
pygame.quit()
次はコントローラーの入力を受け取って結果を表示してみましょう
コントローラーはホリクラシックコントローラーを使用します
まずTextPrintというデータを画面に出力するためのクラスを作成します
tprintでデータを表示、indentで字下げ、unindentで字下げを元に戻す、resetで表示のリセットを行います
draw_input_infoを定義してコントローラーの入力情報を出力します
コントローラーの入力情報はjoystick.get_axisやjoystick.get_buttonで出力できます
試しに動かしてみましょう。
左上にコントローラーの入力情報が表示されるようになりました。
Axis0が左スティックの左右、Axis1が左スティックの上下
AボタンがButton0、BボタンがButton1に対応していることがわかります
コントローラーでキャラクターを操作
import pygame
pygame.init()
class TextPrint:
def __init__(self):
self.reset()
self.font = pygame.font.Font(None, 25)
def tprint(self, screen, text):
text_bitmap = self.font.render(text, True, (0, 0, 0))
screen.blit(text_bitmap, (self.x, self.y))
self.y += self.line_height
def reset(self):
self.x = 10
self.y = 10
self.line_height = 15
def indent(self):
self.x += 10
def unindent(self):
self.x -= 10
def draw_input_info(screen, joystick, text_print):
text_print.reset()
axes = joystick.get_numaxes()
text_print.tprint(screen, f"Number of axes: {axes}")
text_print.indent()
for i in range(axes):
axis = joystick.get_axis(i)
text_print.tprint(screen, f"Axis {i} value: {axis:>6.3f}")
text_print.unindent()
buttons = joystick.get_numbuttons()
text_print.tprint(screen, f"Number of buttons: {buttons}")
text_print.indent()
for i in range(buttons):
button = joystick.get_button(i)
text_print.tprint(screen, f"Button {i:>2} value: {button}")
text_print.unindent()
class Player():
def __init__(self, x, y, screen, joystick):
self.img = pygame.image.load('img\\business_eigyou_man.png')
self.size = 100 * 1
self.img = pygame.transform.scale(self.img, (self.size, self.size))
self.player_pos = self.img.get_rect()
self.player_pos.x = x
self.player_pos.y = y
self.joystick = joystick
self.screen = screen
# 移動
self.direction_right = True
self.delta = 60/1000
def move_action(self):
self.player_pos.x += 900 * self.delta * self.joystick.get_axis(0)
if self.direction_right and self.joystick.get_axis(0) < 0:
self.img = pygame.transform.flip(self.img, True, False)
self.direction_right = False
elif not self.direction_right and self.joystick.get_axis(0) > 0:
self.img = pygame.transform.flip(self.img, True, False)
self.direction_right = True
def update(self):
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
self.move_action()
self.screen.blit(self.img, self.player_pos)
#################################################################################
# main関数
#################################################################################
def main():
screen = pygame.display.set_mode((1920, 1080))
bg = pygame.image.load("img\\bg_dote.jpg")
bg = pygame.transform.scale(bg, (1920, 1080))
clock = pygame.time.Clock()
text_print = TextPrint()
joystick = pygame.joystick.Joystick(0)
center = screen.get_width() / 2
ground = screen.get_height() / 4 * 3
player = Player(center-100,
ground,
screen,
joystick)
done = False
while not done:
screen.blit(bg, (0, 0))
draw_input_info(screen, joystick, text_print)
player.update()
# 描画更新
pygame.display.flip()
clock.tick(60)
if __name__ == "__main__":
main()
pygame.quit()
最後にコントローラーでキャラクターを操作できるようにします
そのために次の処理を追加します
①Playerクラスを作成し、キャラクター画像を読み込み設定等の初期化処理
②コントローラーの入力を受け取ってキャラクター画像を移動させる処理
③コントローラーの入力を受け取ってキャラクターの向きを変える処理
まずはPlayerクラスを作成します
Playerクラスではpygame.image.loadでキャラクターの画像をロードし、pygame.transform.scaleで大きさを変更します
get_rectで画像の位置情報x、yが格納されているオブジェクトを取得できます
この部分ではキャラクターの初期位置を設定しておきます
また、コントローラー、スクリーンの情報も設定しておきます
direction_rightではキャラクターの向きを記憶します
続いてmove_actionメソッドを作成します
ここで、コントローラーの入力を受け取ってキャラクター画像を移動させたり、向きを変更させます
まずはキャラクター画像を移動させる部分を記述しましょう
self.joystick.get_axis(0)でAxis0のデータを受け取ります。このデータは先ほど見た通り、コントローラーの右左に対応します
この値に適当な定数を掛けてself.player_pos.xに足し合わせます。これでキャラクターの場所情報が変更されます
この定数を大きくすればするほどキャラクターは少しの入力で大きく移動します
次にキャラクターの向きを変更する部分を作成します
実装すべき内容を解説すると、キャラクターが右を向いているときにコントローラーで左を入力すると反転する
同じくキャラクターが左を向いているときにコントローラーで右を入力すると反転するという処理です
反転したらキャラクターの向き情報を更新しておきます
このメソッドをupdateメソッドから呼び出しましょう
updateメソッドではゲームのイベントキューから情報を取得する処理
イベントタイプがQUITの場合、ゲーム画面を閉じる処理
これでタスクバーからゲームを閉じることができるようになります
先程作成したのmove_actionメソッドの実行、screen.blitによるキャラクター画像の描画を行います
ゲームを起動するとコントローラーでキャラクターを操作できるようになっていることがわかります