【pyxel 1.5】pyxelで2Dアクションを作ってみる(1)
Pythonのレトロゲームエンジン「pyxel」で2Dアクションゲームを作ってみます。
今回は手始めに「壁・床」の当たり判定の設置、ジャンプアクション、攻撃アクションの作成を行いました。コードには結構長くなってしまったので要所要所のみご紹介して、画像メインで進めたいと思います。
結構いい感じなんじゃないでしょうか?
この時点での操作は左右キーで移動、スペースキーでブースト、Vキーで攻撃です。
プレイヤーはなんとなくロボットに。ブーストを実装したかっただけで他に意味はありません。
画面は128*128のメインウィンドウの右側に情報ウィンドウをくっつけています。今は燃料ゲージとプレイヤーの座標を表示。文字色をオレンジにしたらアーマードコア3みたいで楽しくなりました。
攻撃は謎のビーム。燃料ゲージがブーストと共通なので、このあたりの管理が難しい。飛びながら撃ってるとすぐ燃料切れになります。
さて、ここからは少しコードの紹介を。
今回最も面倒くさかったのは当たり判定の実装でした。最終的には自作の外部モジュールファイルとしてまとめています。
# -*- coding: utf-8 -*-
import pyxel
def check_move(player, x, c):
"""
Player coordinates
2 pm1
(x, y).--.----------.----
| |
7.| |.8
| P |
5.| |.6
| |
---.----------.----
4 3
"""
#Position Set
px = int((player.p_x + c[0] + 2) // 8)
py = int((player.p_y + c[1]) // 8)
px2 = int((player.p_x + c[0] + 8) // 8)
py2 = int((player.p_y + c[1] + 8) // 8)
px3 = int((player.p_x + c[0] + 6) // 8)
py3 = int((player.p_y + c[1] + 6) // 8)
px4 = int((player.p_x + c[0]) // 8)
py4 = int((player.p_y + c[1] + 2) // 8)
pm1 = pyxel.tilemap(0).pget(px3, py)
pm2 = pyxel.tilemap(0).pget(px, py)
pm3 = pyxel.tilemap(0).pget(px3, py2)
pm4 = pyxel.tilemap(0).pget(px, py2)
pm5 = pyxel.tilemap(0).pget(px4, py3)
pm6 = pyxel.tilemap(0).pget(px2, py3)
pm7 = pyxel.tilemap(0).pget(px4, py4)
pm8 = pyxel.tilemap(0).pget(px2, py4)
#collision detection
#Move UP
if x == 1:
if pm1[1] > 5 and pm2[1] > 5:
return True
#Move DOWN
elif x == 3:
if pm3[1] > 5 and pm4[1] > 5:
return True
else:
return False
#Move RIGHT
elif x == 2:
if pm6[1] > 5 and pm8[1] > 5:
return True
#Move LEFT
elif x == 4:
if pm5[1] > 5 and pm7[1] > 5:
return True
else:
return False
色々書いていますが、プレイヤーの移動先のタイルマップを見て、移動可能ならTrueを、ダメならFalseを返す関数です。
そしてその判定をするためにこれまた色々と座標を取得しています。これは左右の移動と上下の移動の当たり判定を分けるためです。簡単に図示します。
このプログラムではプレイヤー本来の描画範囲(黒枠)と縦移動の当たり判定(赤枠)、横移動の当たり判定(緑枠)が別の範囲になっています。当初は黒枠のみ考え、枠の四隅を判定基準にしていたのですが、これだと壁にくっついたときに上下移動ができなくなったり、ジャンプで天井に頭が付いたときに左右に移動できなくなったりとうまく動きませんでした。
どういうことかというと…
具体的には「右に進むには2と4の点が移動可能ならいい」というルールと「上に進むには1と2の点が移動可能ならいい」というルールがありました。この状態で壁まで行くと2と4の点が進行不可になり止まります。ここまではOKです。
次にジャンプしようとすると、すでに2の点が進行不可になっているので飛べなくなってしまいました。進行方向が違うので何とかなりそうなもんなのですが、ここがどうにも直せなくて思いついた苦肉の策が今回の当たり判定になります。
※オブジェクトの中心点同士の距離をとったりするともっとスマートに解決できるらしい。ちょっと難しいので、これはまた今度。
コード全体は長くなるので、GitHubのリポジトリをご参照ください。
そんなこんなで2Dアクションの基本的な部分はできました。次は敵にも攻撃させてもっとゲームらしくしていこうと思います。
ここまで読んでいただきありがとうございました。
ここまで読んでいただきありがとうございます!