ブロックとボールの当たり判定を実装します。
当たり判定のアルゴリズムは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