ブロックの当たり判定

ブロックとボールの当たり判定を実装します。
当たり判定のアルゴリズムはJavaを使ったゲームプログラミングサイト「Javaでゲーム作りますが何か?」に大変参考になる解説があるのでそれを使わせてもらう事にします。

ブロックとボールの当たり判定で問題になるのは、ボールの反射方向です。
ボールがどの方向からブロックに当たったかで反射方向を変えなければいけません。

反射方向

詳しい方法は上記のサイトの「ブロックを壊す」で詳しく解説されているのでそちらをご覧ください。

点と矩形の当たり判定にユーザー定義関数を用いました。

chkhit double x, double y, int bx, int by, int b_width, int b_height

x,yは点の座標です。整数ではなく実数である事に注意してください。
bx,byはブロックの左上の頂点の座標です。b_width、b_heightはブロックの幅と高さです。
点が矩形内部にあれば 1 を、そうでなければ 0 を返り値とします。

#module
//点と矩形の当たり判定関数
#defcfunc chkhit double x, double y, int bx, int by, int b_width, int b_height
if (x >= bx) & (x <= bx + b_width) & (y >= by) & (y <= by + b_height) :return 1 :else : return 0
#global

//画面の大きさ
#define wx 360
#define wy 400
//ボールの位置
x = 40.0
y = 200.0
//ボールの速度
vx = 5.0
vy = 3.0
racketsize = 60 //ラケットの大きさ
ballsize = 8 //ボールの大きさ
row = 10 //ブロックの行数
col = 6  //ブロックの列数
b_width = 30 //ブロックの幅
b_height = 15 //ブロックの高さ

dim block,row,col
dim bx,row,col
dim by,row,col
repeat row
	i = cnt
	repeat col
		j = cnt
		block(i,j) = 1
		bx(i,j) = b_width*(i+1)
		by(i,j) = b_height*(j+1)
	loop
loop

randomize
screen 0,wx,wy

repeat
	rx = mousex - racketsize/2
	x += vx
	y += vy
	if x < 0 | x > (wx-ballsize) : vx = vx * -1
	if y < 0 : vy = vy * -1
	//ラケットの中央で打ち返す
	if (y >= wy-ballsize) & (x+ballsize > rx+20) & (x < rx+racketsize-20):vy = vy * -1
	//ラケットの左側で打ち返す
	if (y >= wy-ballsize) & (x+ballsize > rx) & (x+ballsize <= rx+20) {
		v = vx*vx + vy*vy //ボールの速度を求める
		rad = (5236.0 + rnd(5237)) / 10000 //ボールを打ち返す角度を決め
		vx = sqrt(v) * cos(rad) * -1
		vy = sqrt(v) * sin(rad) * -1
	}
	//ラケットの右側で打ち返す
	if (y >= wy-ballsize) & (x >= rx+racketsize-20) & (x < rx+racketsize) {
		v = vx*vx + vy*vy
		rad = (5236.0 + rnd(5237)) / 10000
		vx = sqrt(v) * cos(rad)
		vy = sqrt(v) * sin(rad) * -1
	}
	if y > wy :y = 0
	
	color 0,0,0
	boxf //背景をクリア
	color 255,0,0
	boxf rx,wy-5,rx+racketsize,wy //ラケットを描画
	
	color 0,0,255
	broke = 0
	repeat col
		j = cnt
		repeat row
			i = cnt
			//ブロックの当たり判定
			if (x+ballsize > bx(i,j)) & (x < bx(i,j)+b_width) & (y+ballsize > by(i,j)) & (y < by(i,j)+b_height) & (block(i,j) = 1) & (broke = 0){
				block(i,j) = 0 //ブロックを消滅させる
				upleft = 0
				upright = 0
				lowleft = 0
				lowright = 0
				if chkhit(x,y,bx(i,j),by(i,j),b_width,b_height): upleft = 1
				if chkhit(x+ballsize,y,bx(i,j),by(i,j),b_width,b_height): upright = 1
				if chkhit(x,y+ballsize,bx(i,j),by(i,j),b_width,b_height): lowleft = 1
				if chkhit(x+ballsize,y+ballsize,bx(i,j),by(i,j),b_width,b_height): lowright = 1
				if upleft = 0 & upright = 1 & lowleft = 0 & lowright = 1: vx = vx * -1 //ブロックの左
				if upleft = 0 & upright = 0 & lowleft = 1 & lowright = 1: vy = vy * -1 //ブロックの上
				if upleft = 1 & upright = 0 & lowleft = 1 & lowright = 0: vx = vx * -1 //ブロックの右
				if upleft = 1 & upright = 1 & lowleft = 0 & lowright = 0: vy = vy * -1 //ブロックの下
				if upleft = 0 & upright = 1 & lowleft = 0 & lowright = 0: vx = vx * -1 :vy = vy * -1 //ブロックの左下
				if upleft = 0 & upright = 0 & lowleft = 0 & lowright = 1: vx = vx * -1 :vy = vy * -1 //ブロックの左上
				if upleft = 0 & upright = 0 & lowleft = 1 & lowright = 0: vx = vx * -1 :vy = vy * -1 //ブロックの右上
				if upleft = 1 & upright = 0 & lowleft = 0 & lowright = 0: vx = vx * -1 :vy = vy * -1 //ブロックの右下
				broke = 1
			}
			if block(i,j) = 1:boxf bx(i,j)+1,by(i,j)+1,bx(i,j)+b_width-1,by(i,j)+b_height-1 //ブロックの描画
		loop
	loop
	//ボールを描画
	color 255,255,0 
	circle x,y,x+ballsize,y+ballsize
	
	redraw 1
	wait 1
	redraw 0
loop