前回の記事ではパックマンを動かせるようにしました。
今回は、移動する方向に応じてパックマンの向きが変わるようにしていきます。
グラフィックスの反転
bit関数の第4、第5引数それぞれに負の値を渡すことで、グラフィックスを水平、垂直方向に反転させることができます。
blt(x, y, img, u, v, w, h, [colkey])
イメージバンクimg
(0-2) の (u
,v
) からサイズ (w
,h
) の領域を (x
,y
) にコピーする。w
、h
それぞれに負の値を設定すると水平、垂直方向に反転する。colkey
に色を指定すると透明色として扱われる
要するに、反転させたい場合は-1で乗算すればよいですね。
左右にしか移動しないのであれば、以下のようなコードを書けばよいでしょう。
def move(self): if pyxel.btn(self.left): self.x -= self.speed self.left_right = 1 self.rotation = 0 if pyxel.btn(self.right): self.x += self.speed self.left_right = -1 self.rotation = 0 def draw(self): pyxel.blt(self.x, self.y, 0, self.u * 16, self.h * 16, char_W * self.left_right, char_H, 0)
グラフィックスの回転
横を向いているパックマンを上下に向けるには、90°か270°回転させる必要がありますが、pyxelでは反転はできても回転させる方法は用意されていないようです。
プログラムでどうにかするよりも、上を向いているキャラチップを用意した方が簡単でしょう。
上下に移動しているときは、キャラチップの読み込み位置を下に64ドットずらすようにします。
def move(self): if pyxel.btn(self.up): self.y -= self.speed self.up_down = 1 self.rotation = 64 if pyxel.btn(self.down): self.y += self.speed self.up_down = -1 self.rotation = 64 if pyxel.btn(self.left): self.x -= self.speed self.left_right = 1 self.rotation = 0 if pyxel.btn(self.right): self.x += self.speed self.left_right = -1 self.rotation = 0 def draw(self): pyxel.blt(self.x, self.y, 0, self.u * 16, self.h * 16 + self.rotation, char_W * self.left_right, char_H * self.up_down, 0)
下へ移動する際は、水平方向に反転させます。
ソースコード
今回のソースコードは以下になります。
前回からの主な変更点
- キャラチップの追加
- move関数とdraw関数に向きを変更するためのコードを追加
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.up_down = 1 self.left_right = 1 self.rotation = 0 # 画像切り替えの折返し判断 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 self.up_down = 1 self.rotation = 64 if pyxel.btn(self.down): self.y += self.speed self.up_down = -1 self.rotation = 64 if pyxel.btn(self.left): self.x -= self.speed self.left_right = 1 self.rotation = 0 if pyxel.btn(self.right): self.x += self.speed self.left_right = -1 self.rotation = 0 def draw(self): pyxel.blt(self.x, self.y, 0, self.u * 16, self.h * 16 + self.rotation, char_W * self.left_right, char_H * self.up_down, 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加算する変数 # [TODO] fpsを揃えること 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()
実行結果
パックマンが進み続ける処理は、マップを作ってから考えるよ。
キャラクターの操作はある程度完成しました。
次回はマップを制作していきます。