0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ゲームボーイ RGBDS 開発メモ 第10回 チュートリアルを読んでいく (Collision, Bricks)

Last updated at Posted at 2025-01-03

https://gbdev.io/gb-asm-tutorial/part2/collision.html

Collision

Ball:
    dw `00033000
    dw `00322300
    dw `03222230
    dw `03222230
    dw `00322300
    dw `00033000
    dw `00000000
    dw `00000000
BallEnd:
    ; Copy the ball tile
    ld de, Ball
    ld hl, $8010
    ld bc, BallEnd - Ball
    call Memcopy

ボールのタイルを定義します。

    ; Now initialize the ball sprite
    ld a, 100 + 16
    ld [hli], a
    ld a, 32 + 8
    ld [hli], a
    ld a, 1
    ld [hli], a
    ld a, 0
    ld [hli], a

ボールのオブジェクトも設定。

SECTION "Ball Data", WRAM0
wBallMomentumX: db
wBallMomentumY: db

ボールのX座標の増分、Y座標の増分のワークエリアです。

    ; Now initialize the ball sprite
    ld a, 100 + 16
    ld [hli], a
    ld a, 32 + 8
    ld [hli], a
    ld a, 1
    ld [hli], a
    ld a, 0
    ld [hli], a

    ; The ball starts out going up and to the right
    ld a, 1
    ld [wBallMomentumX], a
    ld a, -1
    ld [wBallMomentumY], a

ボールの座標と増分の初期化ですね。ボールの座標はOAMをそのまま利用します。

Main:
    ld a, [rLY]
    cp 144
    jp nc, Main
WaitVBlank2:
    ld a, [rLY]
    cp 144
    jp c, WaitVBlank2

    ; Add the ball's momentum to its position in OAM.
    ld a, [wBallMomentumX]
    ld b, a
    ld a, [_OAMRAM + 5]
    add a, b
    ld [_OAMRAM + 5], a

    ld a, [wBallMomentumY]
    ld b, a
    ld a, [_OAMRAM + 4]
    add a, b
    ld [_OAMRAM + 4], a

メインルーチンで、OAMにある座標をよみとって、増分を足し込んでいます。負の数を足していますが、これは
アセンブラが-1を2の補数($FF)にしてくれています。2の補数なんて、
まったく忘れていました。情報処理の資格を勉強したときでてきたような。

; Convert a pixel position to a tilemap address
; hl = $9800 + X + Y * 32
; @param b: X
; @param c: Y
; @return hl: tile address
GetTileByPixel:
    ; First, we need to divide by 8 to convert a pixel position to a tile position.
    ; After this we want to multiply the Y position by 32.
    ; These operations effectively cancel out so we only need to mask the Y value.
    ld a, c
    and a, %11111000
    ld l, a
    ld h, 0
    ; Now we have the position * 8 in hl
    add hl, hl ; position * 16
    add hl, hl ; position * 32
    ; Convert the X position to an offset.
    ld a, b
    srl a ; a / 2
    srl a ; a / 4
    srl a ; a / 8
    ; Add the two offsets together.
    add a, l
    ld l, a
    adc a, h
    sub a, l
    ld h, a
    ; Add the offset to the tilemap's base address, and we are done!
    ld bc, $9800
    add hl, bc
    ret

ボールの座標からタイルマップのアドレスを求める関数です。

x: ボールのX座標を8で割った商
y: ボールのY座標を8で割った商

としたとき、
hl = $9800 + x + y * 32

ですね。Yをタイルの横の個数である32倍して(スクロールがあるので32個あるらしい)Xを足せば、$9800 からいくずれたかを求めることができます。

y*32をもとめるのに、Y座標を8の倍数に切り捨ててからadd hl, hl を2回くりかえして4倍にしてhlに格納されます。

xをもとめるのに、X座標を右シフト3回して求めています。これがaに入ります。このaをhlに足し込みたいのですが、
aにlを足したものをlにいれて、adcでaにhとcフラグを足し込んでから、lをひくことで、hが求まります。これでできたhlに$9800を足してできあがあり。

これは難しいです(笑)adcとsubを使うのはよくあるテクニックなのでしょうか。

    ld c, a
    ld b, 0
    add hl, bc
    ld bc, $9800
    add hl, bc

ためしにこちらのコードに変えたところ動作しているようなので、うまくいってるかな。

; @param a: tile ID
; @return z: set if a is a wall.
IsWallTile:
    cp a, $00
    ret z
    cp a, $01
    ret z
    cp a, $02
    ret z
    cp a, $04
    ret z
    cp a, $05
    ret z
    cp a, $06
    ret z
    cp a, $07
    ret

これはタイルが壁かどうかの判定です。switch文ですね。ret z はゼロフラグがたっていたらreturn; です

あとは、座標からバウンドするかどうかを計算して、増分を変更するというコードでしたので、割愛します(笑)
オブジェクト同士の当たり判定は、座標から計算するしかないんですね。

Bricks

https://gbdev.io/gb-asm-tutorial/part2/bricks.html

こちらは、ボールがレンガにぶつかったとき、タイルマップのタイルIDを変えてなくすというコードでした。

チュートリアル PartII 完走!これからなにをやるか

これでチュートリアル PartIIはおしまいです。PartIIIは画面遷移などがあるようですが、こちらはさらっと読むだけにとどめておいて、Qiitaでなぞるのはやめておきます(面倒になってきた(笑))

チュートリアルを読む前よりも、なにができるのかが少しずつわかってきました。
そろそろなにかつくりたくなってきました(笑)ビットの計算のところが少し自分には難しいですが
少しずつ解決していけば、なんとかなりそう。ChatGPT先生もいますし。

なにをつくるかですが、いくつか考えてみました。

連射判定ゲームが一番簡単そうでしょうか?もう少し検討したいと思います!
あとサウンドもやってみたい!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?