前回の記事ではパックマンを画面に表示するプログラムを作成しました。
今回は、キー入力に応じてキャラクターを移動できるようにしていきます。
キー入力の受付
キーが押されたときに命令を実行するには、以下のようなコードを書けばよいです。
if pyxel.btn(self.up):
self.y -= self.speed上記のサンプルコードでは、上矢印キーが押されると、変数yから変数speedの値が減算されます。
矢印キーでキャラクターを操作可能にする
前回作成したPlayerクラスに以下のような関数を作成して、毎フレーム呼び出すことでキャラクターを操作できるようになります。
def move(self):
if pyxel.btn(pyxel.KEY_UP):
self.y -= self.speed
if pyxel.btn(pyxel.KEY_DOWN):
self.y += self.speed
if pyxel.btn(pyxel.KEY_LEFT):
self.x -= self.speed
if pyxel.btn(pyxel.KEY_RIGHT):
self.x += self.speed
今後、アイテムの取得などで移動速度を変更できるようにしたいので、移動速度用の変数も追加しました。
各キーの定義はキー定義一覧から確認できます。
しかし、この方法だと、全キャラが矢印キーと連動して動いてしまいます。
キャラクターごとにキーをバインドする
キャラクターごとに別のキーをバインドできるよう、インスタンス生成時に対応させるキーを変数に保存することにしました。
# キーバインド
if h == 0: #プレイヤー1の設定
self.up = pyxel.KEY_UP
self.down = pyxel.KEY_DOWN
self.left = pyxel.KEY_LEFT
self.right = pyxel.KEY_RIGHT
if h == 1: #プレイヤー2の設定
self.up = pyxel.KEY_W
self.down = pyxel.KEY_S
self.left = pyxel.KEY_A
self.right = pyxel.KEY_D
if h == 2: #プレイヤー3の設定
pass
if h == 3: #プレイヤー4の設定
pass後々ゲームパッドに対応させる予定ですが、とりあえず2キャラだけキーを割り当てました。
最初に書いたmove関数を以下のように修正します。
def move(self):
if pyxel.btn(self.up):
self.y -= self.speed
if pyxel.btn(self.down):
self.y += self.speed
if pyxel.btn(self.left):
self.x -= self.speed
if pyxel.btn(self.right):
self.x += self.speed ソースコード
今回のソースコードは以下になります。
前回からの主な変更点
- Playerクラスの__init__関数にキーバインドの設定を追加
- Playerクラスにmove関数を追加
- Playerクラスのインスタンスをリストで管理することにした
import pyxel
WINDOW_H = 256
WINDOW_W = 256
char_H = 16
char_W = 16
# キャラクターのクラスを作成
class Player:
def __init__(self, x, y, h):
# 表示位置の座標を示す変数
self.x = x
self.y = y
# 画像の座標を示す変数
self.u = 0
self.h = h # プレイヤーの判別にも使用
# 画像切り替えの折返し判断
self.sw = 0
# 移動速度
self.speed = 4
# キーバインド
if h == 0: #プレイヤー1の設定
self.up = pyxel.KEY_UP
self.down = pyxel.KEY_DOWN
self.left = pyxel.KEY_LEFT
self.right = pyxel.KEY_RIGHT
if h == 1: #プレイヤー2の設定
self.up = pyxel.KEY_W
self.down = pyxel.KEY_S
self.left = pyxel.KEY_A
self.right = pyxel.KEY_D
if h == 2: #プレイヤー3の設定
pass
if h == 3: #プレイヤー4の設定
pass
# キャラグラフィック変更
def update(self):
if self.sw == 0:
self.u += 1
if self.u == 2:
self.sw = 1
else:
self.u -= 1
if self.u == 0:
self.sw = 0
## キャラクター移動
def move(self):
if pyxel.btn(self.up):
self.y -= self.speed
if pyxel.btn(self.down):
self.y += self.speed
if pyxel.btn(self.left):
self.x -= self.speed
if pyxel.btn(self.right):
self.x += self.speed
def draw(self):
pyxel.blt(self.x, self.y, 0, self.u*16, self.h*16, char_W, char_H, 0)
class App:
def __init__(self):
pyxel.init(WINDOW_W, WINDOW_H, caption="Hello Pyxel")
pyxel.image(0).load(0, 0, "img/img.png")
# フレーム更新時に1加算する変数
self.frame = 0
# Playerクラスのインスタンスを生成、初期位置の座標を引数に渡す
self.players = {}
self.player_1 = Player(16, 16, 0)
self.player_2 = Player(16, 64, 1)
self.player_3 = Player(16, 112, 2)
self.player_4 = Player(16, 160, 3)
# 参加するプレイヤーを登録
# [TODO] プレイ人数に応じて変更
self.players = [self.player_1, self.player_2]
pyxel.run(self.update, self.draw)
def update(self):
self.frame += 1
# 3フレームごとにキャラグラフィックを更新
if self.frame % 3 == 0:
for player in self.players:
player.update()
# キャラクターの座標を更新
for player in self.players:
player.move()
if pyxel.btnp(pyxel.KEY_Q):
pyxel.quit()
def draw(self):
pyxel.cls(0)
# キャラクターを描画
for player in self.players:
player.draw()
App()インスタンスをリストで管理
インスタンスが増えると、関数の呼び出しが冗長になっていきます。
def draw(self):
self.player_1.draw()
self.player_2.draw()
self.player_3.draw()
self.player_4.draw()それを回避するために、生成したインスタンスをリストに追加して、各関数をfor文でまとめて実行できるようにしました。
for player in self.players:
player.draw()今回作成したmove関数も、フレームごとに呼び出されるようにしましょう。
キーバインドを設定していない3pと4pを出すとエラーを吐いてしまうので、とりあえず1pと2pのインスタンスをリストに追加して、各種関数を実行させています。
実行結果










キー入力でキャラクターを動かせるようになりました。
次回は入力した方向に応じてキャラクターの向きが変更されるようにしていきます。