HSP3 ゲームのプログラミング | |
ブロック・ゲーム制作 |
(3) ボールとブロックの衝突判定
ボールとラケットの衝突判定の場合、ボールはラケットの上側にしか当たらないが、ボールとブロックの場合はブロックの4辺すべてに当たることになる。
ボールとブロックは図のときに衝突したと判定する。ラケットのときと違うが、隣同士のブロックがつながることも考えてこのようにした。
ボールのサイズは2×2であり、ブロックは4×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 下辺衝突 |
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 |