ブロック崩し(3) ブロックの衝突判定

ボールとブロックの衝突判定を記述します。前回書いたBlockクラスを以下のように修正します。

class Block{
  int n, x, y;
  Block(){
    n = 1;
  }
  void display(){
    if (n == 1){
      fill(255);
      rect(x, y, bw, bh);
      if (((x <= ball.x) && (ball.x <= x+bw) && (ball.y+ball.hr >= y) && (ball.y+ball.hr <= y+5)) || // top
          ((x <= ball.x) && (ball.x <= x+bw) && (ball.y-ball.hr >= y+5) && (ball.y-ball.hr <= y+bh))){ //down
          ball.yDir *= -1;
          n = 0;
      }
      if (((ball.x+ball.hr <= x+5) && (x <= ball.x+ball.hr) && (ball.y >= y) && (ball.y <= y + bh)) || // left
          ((ball.x+ball.hr <= x+bw) && (x+bw-5 <= ball.x-ball.hr) && (ball.y >= y) && (ball.y <= y + bh))){ //right
          ball.xDir *= -1;
          n = 0;
      }
    }
  }
}

top の部分はブロックの上部分、downは下、left は左、right は右にボールが当たったときの処理を表しています。
if (n == 1) の部分は、「もしブロックがあれば」ということです。
bw はブロックの幅(40)、bh はブロックの高さ(10)です。これらを新たなグローバル変数としてはじめに宣言し、setup()の中で初期化しておきます。bw と bh は Block クラスの中に入れても良かったのですが、Blockクラスの中に入れてしまうと、2次元配列のそれぞれの要素(10×10=100)に2つの変数が加わるため、100× 2 =200 の中身が同じ変数が生成されてしまいます。bw,bhは一定であるため、グローバル変数として設定しました。

はじめ、draw()とdisplay()メソッドの中の両方に2重のforループを作成してしまいました。

<draw()内>
for (int i = 0; i < 10; i ++){
  for (int j = 0; j < 10; j ++)
    block[i][j].display();
}
<Blockクラス display()内>
void display(){
  for (int i = 0; i < 10; i++){
    for (int j = 0; j < 10; j++){
      ~ 省略 ~
  }
}

このように書いてしまうと、2重ループの中に2重ループがあることになり、10の4乗=10000回の計算が1度に必要になります。実行してみたところ、重くてスムースに動きません。

これで一応、ボールがブロックとぶつかるとはね返り、ブロックが消えるようになりました。
今後、ラケットの当たる位置によってボールのはね返りの角度を変えたいですね。

今日のコードです。

Ball ball;
Block[][] block;
Player player;
int bw, bh;


class Ball{
  float x, y, r, hr, xDir, yDir;
  Ball(){
    x = width/2;
    y = height/3 * 2;
    r = 10;
    xDir = random(-1, 1);
    yDir = random(2, 4);
    hr = r/2;
  }
  void move(){
    if ((x+hr > width) || (x-hr < 0)) 
      xDir *= -1;
    if ((y-hr<=0) || ((y+hr >= player.y) && (y+hr <= player.y + 5) && (x >= player.x) && (x <= player.x+50))) 
      yDir *= -1; 
    if (y > height) {
      player.score --;
      xDir = random(-1, 1);
      yDir = random(2, 4);
      x = width/2;
      y = height/3 * 2;
    }
    
    x += xDir; 
    y += yDir;
    fill(255);
    ellipse(x, y, r, r);
  }   
}

class Block{
  int n, x, y;
  Block(){
    n = 1;
  }
  void display(){
    if (n == 1){
      fill(255);
      rect(x, y, bw, bh);
      if (((x <= ball.x) && (ball.x <= x+bw) && (ball.y+ball.hr >= y) && (ball.y+ball.hr <= y+5)) || // top
          ((x <= ball.x) && (ball.x <= x+bw) && (ball.y-ball.hr >= y+5) && (ball.y-ball.hr <= y+bh))){ //down
          ball.yDir *= -1;
          n = 0;
      }
      if (((ball.x+ball.hr <= x+5) && (x <= ball.x+ball.hr) && (ball.y >= y) && (ball.y <= y + bh)) || // left
          ((ball.x+ball.hr <= x+bw) && (x+bw-5 <= ball.x-ball.hr) && (ball.y >= y) && (ball.y <= y + bh))){ //right
          ball.xDir *= -1;
          n = 0;
      }
    }
  }
}

class Player{
  float x, y, easing, targetX;
  int score;

  Player(){
    x = width/2-13;
    y = 470;
    easing = 0.1;
    score = 10;
  }
  void move(){
    targetX = mouseX-25; 
    x += (targetX - x) * easing; 
    rect(x, y, 50, 10);
  }
}

void setup(){
  size(600, 500);
  ball = new Ball();
  player = new Player();
  block = new Block[10][10];
  bw = 40;
  bh = 10;
  for (int i = 0; i < 10; i++){
    for(int j = 0; j < 10; j++){
      block[i][j] = new Block();
      block[i][j].x = i + 50 + i * 50;
      block[i][j].y = j + 45 + j * 20;
      //block[i][j].n = 1;
    }
  }
}

void draw(){
  background(0);
  ball.move();
  player.move();
  //player.x = constrain(x, 0, width-50);
  for (int i = 0; i < 10; i ++){
    for (int j = 0; j < 10; j ++)
      block[i][j].display();
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *