Python_Pyxel 学習(3)当たり判定 - 1

上記記事の当たり判定部分以下のコードが理解できない。

import pyxel
pyxel.init(128,128,title="NINJA")
pyxel.load("ninja.pyxres")

x = 8
y = 85    # 動作確認のために位置を変更
dx = 0
dy = 0
pldir = 1

chkpoint = [(2,0),(6,0),(2,7),(6,7)]
def chkwall(cx,cy):
    c = 0
    if cx < 0 or pyxel.width -8 < cx:
        c = c + 1
    for cpx,cpy in chkpoint:
        xi = (cx + cpx)//8
        yi = (cy + cpy)//8
        if (1,0) == pyxel.tilemap(0).pget(xi,yi):
            c = c + 1
    return c

def update():
    global x,y,dx,dy,pldir

    # 操作判定
    if pyxel.btn(pyxel.KEY_LEFT):
        dx = -2
        pldir = -1
    elif pyxel.btn(pyxel.KEY_RIGHT):
        dx = 2
        pldir = 1
    else:
        dx = 0

    # 横方向の移動
    lr = pyxel.sgn(dx)
    loop = abs(dx)

    while 0 < loop :
        if chkwall( x + lr, y) != 0:
            dx = 0
            break
        x = x + lr
        loop = loop -1
    
    return

def draw():
    pyxel.cls(0)
    pyxel.bltm(0,0, 0, 0,0, pyxel.width,pyxel.height, 0)
    pyxel.blt( x, y, 0,  0, 8, pldir*8,8, 0)
    return

pyxel.run(update,draw)

まず、以下の点がどこかわからないw
chkpoint = [(2,0),(6,0),(2,7),(6,7)]

>・chkpoint = [(2,0),(6,0),(2,7),(6,7)]
 キャラクター四隅の座標をタプル型の配列で管理します。8×8ドットの四隅は「(0,0),(7,0),(07),(7,7)」ですが見た目と合わせるために少し内側の座標にしています。

この記述があるので、以下の部分がチェック用のタプル内容なんだという事が分かります。

chkpoint = [(2,0),(6,0),(2,7),(6,7)] がどこの場所か

更に、
>「(0,0),(7,0),(07),(7,7)」ですが見た目と合わせるために少し内側の座標にしています
の部分については、以下の黄色部分が一番外っ側だから、「1コ内側」とのことのようです。

どこが一番外側?

次に分からなかったのが、以下の部分。なんで8で割った商なのか?

def chkwall(cx,cy):
    c = 0
    if cx < 0 or pyxel.width -8 < cx:
        c = c + 1
    for cpx,cpy in chkpoint:
        xi = (cx + cpx)//8
        yi = (cy + cpy)//8
        if (1,0) == pyxel.tilemap(0).pget(xi,yi):
            c = c + 1
    return c

なにが、分からないのかアタマの中で整理するのに時間がかかったのですが、例えば、プレーヤーの x 座標が 60。右移動でチェックするのは、chkpoint = [(2,0),(6,0),(2,7),(6,7)] これの、(6,0) と (6,7) の部分、つまり x 座標 66(実際に Update 関数の中では「1 進んだ先の x 座標」なんで 67) 。67 // 8 = 8。「8 余り 3 だし、商のところに床ブロックないよね(手前だよね?)」という自分のこんがらがった理解がどう誤っているのか理解するまで数日。

X(旧ツイッター)でつぶやいたらブログ著者から、「8×8 を 1 つのブロックとして、一番左上は pyxel.tilemap(0).pget(xi,yi)で取り出せる座標位置は(0, 0)だから、チェック座標を 8 で割った商がそのままブロック位置」とのコメントあり、以下部分を追加していただきました。ちなみに、Discord Pyxel.jp でも、「8 で割った商がそのブロック位置と考えて問題ない」と回答あり。

タイルのタプル情報

分かりやすい!

ちょっと全体簡素化してましたが、以下、挙動確認図

サンプルコード(ほぼ)そのままだからちゃんと当たり判定機能してますの図

ややどうでもいい比較で、チェックポイントのタプルを以下に変えた場合の挙動は以下。

chkpoint = [(0,0),(7,0),(0,7),(7,7)]

腕部分がハマってないし、こちらでもいいような気が・・・。
横移動だけなら。最終的に、ジャンプする動きにすると(絵がある)角にチェックポイント持って行った方が見た目がたしかに自然かもしれないですね。

次回当たり判定内容は、以下の手前から x 座標(手前から)1 づつチェックは何?という内容です。

# 横方向の移動
    lr = pyxel.sgn(dx)
    loop = abs(dx)

    while 0 < loop :
        if chkwall( x + lr, y) != 0:
            dx = 0
            break
        x = x + lr
        loop = loop -1



この記事が気に入ったらサポートをしてみませんか?