HSP3 ゲームのプログラミング
 ブロック・ゲーム制作 前へ 目次へ 次へ 

(3) ボールとブロックの衝突判定

 ボールとラケットの衝突判定の場合、ボールはラケットの上側にしか当たらないが、ボールとブロックの場合はブロックの4辺すべてに当たることになる。
 ボールとブロックは図のときに衝突したと判定する。ラケットのときと違うが、隣同士のブロックがつながることも考えてこのようにした。
 ボールのサイズは2×2であり、ブロックは4×2である。ボールサイズの半分ずれている状態で当たりと判定する。

 x方向
  bx-1 ≦ x0 ≦ bx+4-1 →  bx-1 ≦ x0 ≦ bx+3 → bx-1 -1 ≦ x0 -1 ≦ bx+3 -1 → bx - 2 ≦ x0 - 1 ≦ bx + 2 より
x0 - 1 ≧ bx - 2 → x0 - bx - 1 ≧ -2
x0 - 1 ≦ bx + 2 → x0 - bx - 1 ≦ 2
 → abs(x0 - bx - 1) <= 2  & y0 + 2 = by  上辺衝突
 & y0 = by + 2  下辺衝突
 y方向
  by-1 ≦ y0 ≦ by+2-1 → by-1 ≦ y0 ≦ by+1 より
y0 ≧ by - 1 → y0 - by ≧ -1
y0 ≦ by + 1 → y0 - by ≦ 1
 → abs(y0 - by) <= 1  & x0 + 2 = bx  左辺衝突
 & x0 = bx + 4  右辺衝突

さらに、ボールの進行方向の条件が加わる。

上辺衝突 : 
下辺衝突 : 
左辺衝突 : 
右辺衝突 : 
ボールが上から下へ移動中のみ
  〃  下から上へ  〃
  〃  左から右へ  〃
  〃  右から左へ  〃
 … dy = 正(dy > 0)
 … dy = 負(dy < 0)
 … dx = 正(dx > 0)
 … dx = 負(dx < 0)

 ボールとブロックの衝突判定をプログラムすると次のようになる。bx, by, bfは配列である。

foreach bf
    if bf(cnt) = 1 {
        if abs(x0 - bx(cnt) - 1) <= 2 & y0 + 2 = by(cnt) & dy0 > 0 {  ;上辺衝突
            dy0 = -dy0      ;ボール方向反転
            bf(cnt) = 0     ;ブロックなし
            tokuten = tokuten + 10    ;得点加算
            gosub *joho     ;情報領域表示
        }
        if abs(x0 - bx(cnt) - 1) <= 2 & y0 = by(cnt) + 2 & dy0 < 0 {  ;下辺衝突
            << 省略 >>
        }
        if abs(y0 - by(cnt)) <= 1 & x0 + 2 = bx(cnt) & dx0 > 0 {      ;左辺衝突
            << 省略 >>
        }
        if abs(y0 - by(cnt)) <= 1 & x0 = bx(cnt) + 4 & dx0 < 0 {      ;右辺衝突
            << 省略 >>
        }
    }
loop



課題(racket62.hsp)
 ボールとブロック衝突判定の処理を追加する。ブロック1つにつき得点を10点加算する。

ヒント
・ボールの初期座標をブロックよりしたになるよう変更する。
   y0 = (rnd(10) + 1) * 2 → y0 = (rnd(5) + 12) * 2
・ボールとラケットが衝突したときの得点加算を削除する。
・ブロックがすべて消えても再描画はされないが、そのままでよい。(次に追加する。)


(リスト)新しいウィンドウで開く
※ゲームを進めていくと状況によって衝突判定に不具合もあるが、このまま進めていくことにする。



(4) ブロック全消去時

 ブロックがすべて消されたら、新たにブロックを表示する必要がある。すべて消されたかどうかを判定する処理を考える。
 消されたブロックは配列bfが0なので、配列の内容がすべて0であればすべて消去されたと判定できる。判定の方法として、(a)ブロックの数を記憶しておき、消去されるごとに減算して0になれば全消去、(b)配列bfの値をすべて加算して、合計が0であれば全消去、などが考えられる。

 ここでは、ブロック描画で配列bfを判定しているので、この部分に処理を追加することにする。
 全消去かどうかを示すフラグ変数bffを用意して0(無)で初期化する。ループ内の判定で1つでもブロックが描画されたらbffが1になるようにする。

;ブロック描画
bff = 0    ;ブロック有(1)無(0)
foreach bf
    if bf(cnt) = 1 {
        pos bx(cnt) * mm, by(cnt) * mm
        gcopy 1, 0, 16, 32, 16
        bff = 1    ;ブロック有(1)
    }
loop

 ブロック描画後、変数bffが0ならばブロック全消去である。全消去の時、ブロックを初期設定して、ゲームを再開する。

if bff = 0 {       ;ブロック全消去
    ブロック初期設定  →  gosub *block_init
    break
}

 break命令で「ボール減」と同じようにゲームのメインとなるループを抜ければ、ボールの残りがあるのでゲームが再開されることになる。
 「ブロック初期設定」の処理5行をこの部分に追加すればよいのだが、ブロックの配置を変えるなど、すべての初期設定がこの部分に追加されることになるので、ブロック初期設定をサブルーチンにする。

*block_init
    ;ブロック初期設定
    foreach bf
        bx(cnt) = (cnt \ 12) * 4 + 6    ;ブロックx座標
        by(cnt) = cnt / 12 * 2 + 4      ;ブロックy座標
        bf(cnt) = 1    ;1:あり/0:なし
    loop
    return



課題(racket63.hsp)
 ブロック全消去時の処理を追加する。


(リスト)新しいウィンドウで開く


 ブロック・ゲーム制作 前へ 目次へ 次へ 
2007 © Hiroshi Masuda

 

 

inserted by FC2 system