Pyxelで入力を簡単に検知したい
この記事の内容
Pythonでレトロゲーム制作ができるゲームエンジン、Pyxelで、入力検知用のクラスを作り、キー入力を簡単に管理・検出できるようにしてみたいと思います。
サンプルプログラムではどうなっているか
Pyxelはサンプルプログラムが充実していて、コードの基本的な実例として参考になります[1]。まずは、サンプルプログラムではどのように入力を検知しているかをみてみましょう。
pyxel.btn
やpyxel.btnr
を使う
入力の検知はキー入力とプレイヤーの移動については、サンプルプログラムの09_shooter.py
がすごくわかりやすいです。以下に抜粋してみます。
if pyxel.btn(pyxel.KEY_LEFT) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_LEFT):
self.x -= PLAYER_SPEED
if pyxel.btn(pyxel.KEY_RIGHT) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_RIGHT):
self.x += PLAYER_SPEED
if pyxel.btn(pyxel.KEY_UP) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_UP):
self.y -= PLAYER_SPEED
if pyxel.btn(pyxel.KEY_DOWN) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_DOWN):
self.y += PLAYER_SPEED
「右」であれば、pyxel.KEY_LEFT(キーボードの右)
か、pyxel.GAMEPAD1_BUTTON_DPAD_LEFT(ゲームパッドの右)
のいずれかを検知すれば、PLAYER_SPEED
の値がx
に代入される仕組みになっていますね。
ボタンが押された場合はpyxel.btn
、離された場合はpyxel.btnr
です。分かりやすい!
でも…毎回if文を書くのは嫌だ
さて、自分のゲームを作る段階に移ったとします。
キーボードの矢印キーとゲームパッドの入力に加えて、PCゲームで一般的な「WASD」にも対応したい場合はどうでしょう。途中でやっぱり「WASD」から「ESDF」に変更したくなったら…?キーボードの矢印キーはプレイヤー2に割り当て直したくなるかもしれません。また、複数のファイルのいたるところで入力を検知するコードを書いているかもしれません。
仕様を変更するたびに、毎回全てのif文
を書き換える…のは、ちょっと大変そうですね。
入力検知のためのクラスを作ってみる
そこで、入力検知用の簡易的なクラスInputDetector
を作ってみます。Godot Engineの入力周りの関数の使用感を参考にしてみました。
このクラスの役割・働きは以下のとおりです。
- 同じ役割の入力(例えば、上方向の入力→
pyxel.KEY_UP
、pyxel.KEY_W
、pyxel.GAMEPAD1_BUTTON_DPAD_UP
)を1つの配列に詰め込みます。 - 1.で定義した配列を引数として
is_pressed()
やis_released()
に渡すと、bool
を返すようにします。
コードは以下のとおりです。
import pyxel
class InputDetector():
# 上方向の入力
UP = [
pyxel.KEY_UP,
pyxel.GAMEPAD1_BUTTON_DPAD_UP,
pyxel.KEY_W,
]
# 下方向の入力
DOWN = [
pyxel.KEY_DOWN,
pyxel.GAMEPAD1_BUTTON_DPAD_DOWN,
pyxel.KEY_S,
]
# 左方向の入力
LEFT = [
pyxel.KEY_LEFT,
pyxel.GAMEPAD1_BUTTON_DPAD_LEFT,
pyxel.KEY_A,
]
# 右方向の入力
RIGHT = [
pyxel.KEY_RIGHT,
pyxel.GAMEPAD1_BUTTON_DPAD_RIGHT,
pyxel.KEY_D,
]
# 上で定義した配列を代入し、その中に該当する入力があればTrueを返す
def is_pressed(key:list[int]) -> bool:
for k in key:
if pyxel.btn(k):
return True
return False
#こちらはキーを離した場合のための関数
def is_released(key:list[int]) -> bool:
for k in key:
if pyxel.btnr(k):
return True
return False
実際に使ってみる
これをメインのクラスからimport
して、呼び出してみます。
import pyxel
from input_detector import InputDetector as Input
## __init__ などは省略
def update(self):
if Input.is_pressed(Input.UP):
print("pressed UP")
if Input.is_pressed(Input.DOWN):
print("pressed DOWN")
if Input.is_released(Input.LEFT):
print("released LEFT")
if Input.is_released(Input.RIGHT):
print("released RIGHT")
キー入力に応じてコンソールに方向が出力されました。
キーの種類が増えたり、変更が必要になった場合にも、input_detector.py
内の配列を書き換えたり追加したりすればOKです。ちょっとだけ便利になりました。
-
初学者にも分かりやすく書かれたコードで、Pythonに入門したての自分にはすごく有難いです。 ↩︎
Discussion