为什么游戏在实际撞到砖头之前就检测到碰撞?

发布于 2025-02-05 07:04:54 字数 6959 浏览 2 评论 0原文

我试图为个人项目创建一个砖砌游戏。我正在为不同的砖块使用阵列,并用砖的图像叠加砖块。我能够检测到碰撞,但是由于某种原因,球在撞到实际砖之前略微检测到碰撞。当球撞到砖块时,我也有一个疑问。感谢任何帮助。

代码:

color black = color(0,0,0);
color red = color(255,0,0);
color white = color(255,255,255);

float ballx = 412.5, bally = 500, balld = 20, ballr = balld/2, paddleX = 362.5, paddleY = 650;
float paddleW = 100, paddleH = 15;
float ballspdX, ballspdY;

boolean ball_drop = true;

float direction_choice;

float [] brickX = new float [50];
float [] brickY = new float [50];

int brickW = 50, brickH = 25;
int ball_lives = 5; 
PFont font1;
PFont font2;
PImage brickimg;

boolean gameover_sign = false;
boolean  Game_Over_mode = false;
boolean right = false;
boolean left = false;

void brickformation(){
  brickX[0] = 50;
  brickX[1] = 125; 
  brickX[2] = 200; 
  brickX[3] = 275;
  brickX[4] = 350;
  brickX[5] = 425;
  brickX[6] = 500; 
  brickX[7] = 575;
  brickX[8] = 650; 
  brickX[9] = 725; 
  brickX[10] = 50;
  brickX[11] = 125; 
  brickX[12] = 200; 
  brickX[13] = 275;
  brickX[14] = 350;
  brickX[15] = 425;
  brickX[16] = 500; 
  brickX[17] = 575;
  brickX[18] = 650; 
  brickX[19] = 725; 
  brickX[20] = 50;
  brickX[21] = 125; 
  brickX[22] = 200; 
  brickX[23] = 275;
  brickX[24] = 350;
  brickX[25] = 425;
  brickX[26] = 500; 
  brickX[27] = 575;
  brickX[28] = 650; 
  brickX[29] = 725; 
  brickX[30] = 50;
  brickX[31] = 125; 
  brickX[32] = 200; 
  brickX[33] = 275;
  brickX[34] = 350;
  brickX[35] = 425;
  brickX[36] = 500; 
  brickX[37] = 575;
  brickX[38] = 650; 
  brickX[39] = 725; 
  brickX[40] = 50;
  brickX[41] = 125; 
  brickX[42] = 200; 
  brickX[43] = 275;
  brickX[44] = 350;
  brickX[45] = 425;
  brickX[46] = 500; 
  brickX[47] = 575;
  brickX[48] = 650; 
  brickX[49] = 725; 

  brickY[0] = 50;
  brickY[1] = 50; 
  brickY[2] = 50; 
  brickY[3] = 50;
  brickY[4] = 50;
  brickY[5] = 50;
  brickY[6] = 50; 
  brickY[7] = 50;
  brickY[8] = 50; 
  brickY[9] = 50; 
  brickY[10] = 125;
  brickY[11] = 125; 
  brickY[12] = 125; 
  brickY[13] = 125;
  brickY[14] = 125;
  brickY[15] = 125;
  brickY[16] = 125; 
  brickY[17] = 125;
  brickY[18] = 125; 
  brickY[19] = 125; 
  brickY[20] = 200;
  brickY[21] = 200; 
  brickY[22] = 200; 
  brickY[23] = 200;
  brickY[24] = 200;
  brickY[25] = 200;
  brickY[26] = 200; 
  brickY[27] = 200;
  brickY[28] = 200; 
  brickY[29] = 200; 
  brickY[30] = 275;
  brickY[31] = 275; 
  brickY[32] = 275; 
  brickY[33] = 275;
  brickY[34] = 275;
  brickY[35] = 275;
  brickY[36] = 275; 
  brickY[37] = 275;
  brickY[38] = 275; 
  brickY[39] = 275; 
  brickY[40] = 350;
  brickY[41] = 350; 
  brickY[42] = 350; 
  brickY[43] = 350;
  brickY[44] = 350;
  brickY[45] = 350;
  brickY[46] = 350; 
  brickY[47] = 350;
  brickY[48] = 350; 
  brickY[49] = 350; 
}


void setup(){
  size(825,800);
  surface.setTitle("Brick breaker");
  font1 = createFont("04B_19", 150);
  font2 = createFont("04B_19", 35);
  brickimg = loadImage("brick.jpeg");
  noCursor();
  smooth();
  brickformation();
}

void paddle(){
  noStroke();
  fill(white);
  rect(paddleX, paddleY, paddleW, paddleH);
}
void ball(){
  noStroke();
  fill(red);
  circle(ballx, bally, balld);
}

void gameover(){
  ///////////////////////the sign that displays game over.
  stroke(black);
  fill(white);
  rect(0,135, 825, 240);
  fill(red);
  textFont(font1);
  text("GAME OVER", 20, 275);
  textFont(font2);
  text("Press r to restart", 225, 335);
  Game_Over_mode = true;
}

void reset(){

  ball_lives = 5;
  ballx = 412.5;
  bally = 600;
  gameover_sign = false;
  ball_drop = true;

}

void draw(){
  background(black);
  paddle();
  ball();
  for (int i = 0; i < brickX.length; i++){
    brickimg.resize(brickW, brickH);
    fill(white);
    image(brickimg, brickX[i], brickY[i]);
    rect(brickX[i], brickY[i], brickW, brickH); 
    //hits bottom of brick   
    }
 
  fill(white);
  textFont(font2);
  text("Lives = " + str(ball_lives), 35, 775);
  
  //uses different collision for paddle to make the ball go different directions based on how they hit the paddle.
  //collision for left side of paddle
  if (collideLineCircle(paddleX, paddleY, paddleX + (paddleW/2), paddleY, ballx, bally, ballr)){
    ball_drop = false;
    ballspdY = -1;
    ballspdX = 4;
  }
  //collision for right side of paddle.
  if (collideLineCircle(paddleX + (paddleW/2), paddleY, paddleX + paddleW, paddleY, ballx, bally, ballr)){
    ball_drop = false;
    ballspdY = -1;
    ballspdX = -4;
  }

  //colisions for bricks
  for (int i = 0; i < brickX.length; i ++){
    //bottom
    if (collideLineCircle(brickX[i], brickY[i] + brickH, brickX[i] + brickW, brickY[i] + brickH, ballx, bally, ballr)){
      ballspdY = -ballspdY;
      brickX[i] = -400;
    }
    //top
    else if (collideLineCircle(brickX[i], brickY[i], brickX[i] + brickW, brickY[i], ballx, bally, ballr)){
      ballspdY = -ballspdY;
      brickX[i] = -400;
    }
    else if (collideLineCircle(brickX[i], brickY[i], brickX[i], brickY[i] + brickW, ballx, bally, ballr)){
    ballspdX = -ballspdX;
    brickX[i] = -400;
    }
    else if (collideLineCircle(brickX[i] + brickW, brickY[i], brickX[i] + brickW, brickY[i] + brickH, ballx, bally, ballr)){
    ballspdX = -ballspdX;
    brickX[i] = -400;
    }
  }
  ////collisions for different walls of the screeen.
  if (ballx + ballr > width || ballx - ballr < 0){
    ballspdX = -ballspdX;
  }
  
  if (bally - ballr < 0){
    ballspdY = 1;
  }

  if (ball_drop){
    ballspdX = 0;
    ballspdY = 1;
  }
 

  

  if (ball_lives >= 1){  
   if (bally >= 800){
     ball_lives = ball_lives - 1;
     bally = 600;
     ballx = 412.5;
     ball_drop = true;
   } 
  }
  
  if (ball_lives == 0 && bally > 800){
    gameover_sign = true;
  }
  
  if (gameover_sign){
    gameover();
  }
  
  if (right){
    if(paddleX > 0){
      paddleX -= 4;
    }
  }
  if (left){
    if (paddleX + paddleW < width){
      paddleX += 4;
    }
  }
  
 
  bally += ballspdY/2;
  ballx += ballspdX/2;
  
}
  boolean collideLineCircle(float x1, float y1, float x2, float y2, float cx, float cy, float cr){
    float A = y2 - y1, B = x1 - x2, C = x2*y1 - x1+y2;
    float denom = A+A + B*B;
    if (denom == 0){
    
      return dist(x1,y1, cx, cy) < cr;
    
    }
    
    float Ix = (B*B*cx-A*B*cy - A*C)/denom, Iy = (A*A*cy-A*B*cx - B*C)/denom;
    
    if (Ix >= min(x1,x2) && Ix <= max(x1,x2) & Iy >= min(y1,y2) && Iy <= max(y1,y2)) {
      return abs (A*cx + B*cy + C)/sqrt(denom) < cr;
    }
    
    float d1 = dist(x1,y1,cx,cy), d2 = dist(x2,y2,cx,cy);
    return min(d1,d2) < cr;
    
  }
  
void keyPressed(KeyEvent evt){
  if (key == 'r'){
    if (Game_Over_mode){
      reset();
      Game_Over_mode = false;
    }
  }
  if (key == 'a'){
    if(paddleX > 0){
      right = true;
    }
  }
  else{right = false;}
  
  if (key == 'd'){
    if(paddleX + paddleW < width){
      left = true;
    }
  }
  else{left = false;}
}

Im trying to create a brick breaker game for a personal project. I am using a array for the different bricks and overlaying the bricks with an image of a brick. I was able to detect the collisions but for some reason the ball is detecting the collisions slightly before it hits the actual brick. I also have a question on what way should the ball go when it hits the brick. I appreciate any help.

code:

color black = color(0,0,0);
color red = color(255,0,0);
color white = color(255,255,255);

float ballx = 412.5, bally = 500, balld = 20, ballr = balld/2, paddleX = 362.5, paddleY = 650;
float paddleW = 100, paddleH = 15;
float ballspdX, ballspdY;

boolean ball_drop = true;

float direction_choice;

float [] brickX = new float [50];
float [] brickY = new float [50];

int brickW = 50, brickH = 25;
int ball_lives = 5; 
PFont font1;
PFont font2;
PImage brickimg;

boolean gameover_sign = false;
boolean  Game_Over_mode = false;
boolean right = false;
boolean left = false;

void brickformation(){
  brickX[0] = 50;
  brickX[1] = 125; 
  brickX[2] = 200; 
  brickX[3] = 275;
  brickX[4] = 350;
  brickX[5] = 425;
  brickX[6] = 500; 
  brickX[7] = 575;
  brickX[8] = 650; 
  brickX[9] = 725; 
  brickX[10] = 50;
  brickX[11] = 125; 
  brickX[12] = 200; 
  brickX[13] = 275;
  brickX[14] = 350;
  brickX[15] = 425;
  brickX[16] = 500; 
  brickX[17] = 575;
  brickX[18] = 650; 
  brickX[19] = 725; 
  brickX[20] = 50;
  brickX[21] = 125; 
  brickX[22] = 200; 
  brickX[23] = 275;
  brickX[24] = 350;
  brickX[25] = 425;
  brickX[26] = 500; 
  brickX[27] = 575;
  brickX[28] = 650; 
  brickX[29] = 725; 
  brickX[30] = 50;
  brickX[31] = 125; 
  brickX[32] = 200; 
  brickX[33] = 275;
  brickX[34] = 350;
  brickX[35] = 425;
  brickX[36] = 500; 
  brickX[37] = 575;
  brickX[38] = 650; 
  brickX[39] = 725; 
  brickX[40] = 50;
  brickX[41] = 125; 
  brickX[42] = 200; 
  brickX[43] = 275;
  brickX[44] = 350;
  brickX[45] = 425;
  brickX[46] = 500; 
  brickX[47] = 575;
  brickX[48] = 650; 
  brickX[49] = 725; 

  brickY[0] = 50;
  brickY[1] = 50; 
  brickY[2] = 50; 
  brickY[3] = 50;
  brickY[4] = 50;
  brickY[5] = 50;
  brickY[6] = 50; 
  brickY[7] = 50;
  brickY[8] = 50; 
  brickY[9] = 50; 
  brickY[10] = 125;
  brickY[11] = 125; 
  brickY[12] = 125; 
  brickY[13] = 125;
  brickY[14] = 125;
  brickY[15] = 125;
  brickY[16] = 125; 
  brickY[17] = 125;
  brickY[18] = 125; 
  brickY[19] = 125; 
  brickY[20] = 200;
  brickY[21] = 200; 
  brickY[22] = 200; 
  brickY[23] = 200;
  brickY[24] = 200;
  brickY[25] = 200;
  brickY[26] = 200; 
  brickY[27] = 200;
  brickY[28] = 200; 
  brickY[29] = 200; 
  brickY[30] = 275;
  brickY[31] = 275; 
  brickY[32] = 275; 
  brickY[33] = 275;
  brickY[34] = 275;
  brickY[35] = 275;
  brickY[36] = 275; 
  brickY[37] = 275;
  brickY[38] = 275; 
  brickY[39] = 275; 
  brickY[40] = 350;
  brickY[41] = 350; 
  brickY[42] = 350; 
  brickY[43] = 350;
  brickY[44] = 350;
  brickY[45] = 350;
  brickY[46] = 350; 
  brickY[47] = 350;
  brickY[48] = 350; 
  brickY[49] = 350; 
}


void setup(){
  size(825,800);
  surface.setTitle("Brick breaker");
  font1 = createFont("04B_19", 150);
  font2 = createFont("04B_19", 35);
  brickimg = loadImage("brick.jpeg");
  noCursor();
  smooth();
  brickformation();
}

void paddle(){
  noStroke();
  fill(white);
  rect(paddleX, paddleY, paddleW, paddleH);
}
void ball(){
  noStroke();
  fill(red);
  circle(ballx, bally, balld);
}

void gameover(){
  ///////////////////////the sign that displays game over.
  stroke(black);
  fill(white);
  rect(0,135, 825, 240);
  fill(red);
  textFont(font1);
  text("GAME OVER", 20, 275);
  textFont(font2);
  text("Press r to restart", 225, 335);
  Game_Over_mode = true;
}

void reset(){

  ball_lives = 5;
  ballx = 412.5;
  bally = 600;
  gameover_sign = false;
  ball_drop = true;

}

void draw(){
  background(black);
  paddle();
  ball();
  for (int i = 0; i < brickX.length; i++){
    brickimg.resize(brickW, brickH);
    fill(white);
    image(brickimg, brickX[i], brickY[i]);
    rect(brickX[i], brickY[i], brickW, brickH); 
    //hits bottom of brick   
    }
 
  fill(white);
  textFont(font2);
  text("Lives = " + str(ball_lives), 35, 775);
  
  //uses different collision for paddle to make the ball go different directions based on how they hit the paddle.
  //collision for left side of paddle
  if (collideLineCircle(paddleX, paddleY, paddleX + (paddleW/2), paddleY, ballx, bally, ballr)){
    ball_drop = false;
    ballspdY = -1;
    ballspdX = 4;
  }
  //collision for right side of paddle.
  if (collideLineCircle(paddleX + (paddleW/2), paddleY, paddleX + paddleW, paddleY, ballx, bally, ballr)){
    ball_drop = false;
    ballspdY = -1;
    ballspdX = -4;
  }

  //colisions for bricks
  for (int i = 0; i < brickX.length; i ++){
    //bottom
    if (collideLineCircle(brickX[i], brickY[i] + brickH, brickX[i] + brickW, brickY[i] + brickH, ballx, bally, ballr)){
      ballspdY = -ballspdY;
      brickX[i] = -400;
    }
    //top
    else if (collideLineCircle(brickX[i], brickY[i], brickX[i] + brickW, brickY[i], ballx, bally, ballr)){
      ballspdY = -ballspdY;
      brickX[i] = -400;
    }
    else if (collideLineCircle(brickX[i], brickY[i], brickX[i], brickY[i] + brickW, ballx, bally, ballr)){
    ballspdX = -ballspdX;
    brickX[i] = -400;
    }
    else if (collideLineCircle(brickX[i] + brickW, brickY[i], brickX[i] + brickW, brickY[i] + brickH, ballx, bally, ballr)){
    ballspdX = -ballspdX;
    brickX[i] = -400;
    }
  }
  ////collisions for different walls of the screeen.
  if (ballx + ballr > width || ballx - ballr < 0){
    ballspdX = -ballspdX;
  }
  
  if (bally - ballr < 0){
    ballspdY = 1;
  }

  if (ball_drop){
    ballspdX = 0;
    ballspdY = 1;
  }
 

  

  if (ball_lives >= 1){  
   if (bally >= 800){
     ball_lives = ball_lives - 1;
     bally = 600;
     ballx = 412.5;
     ball_drop = true;
   } 
  }
  
  if (ball_lives == 0 && bally > 800){
    gameover_sign = true;
  }
  
  if (gameover_sign){
    gameover();
  }
  
  if (right){
    if(paddleX > 0){
      paddleX -= 4;
    }
  }
  if (left){
    if (paddleX + paddleW < width){
      paddleX += 4;
    }
  }
  
 
  bally += ballspdY/2;
  ballx += ballspdX/2;
  
}
  boolean collideLineCircle(float x1, float y1, float x2, float y2, float cx, float cy, float cr){
    float A = y2 - y1, B = x1 - x2, C = x2*y1 - x1+y2;
    float denom = A+A + B*B;
    if (denom == 0){
    
      return dist(x1,y1, cx, cy) < cr;
    
    }
    
    float Ix = (B*B*cx-A*B*cy - A*C)/denom, Iy = (A*A*cy-A*B*cx - B*C)/denom;
    
    if (Ix >= min(x1,x2) && Ix <= max(x1,x2) & Iy >= min(y1,y2) && Iy <= max(y1,y2)) {
      return abs (A*cx + B*cy + C)/sqrt(denom) < cr;
    }
    
    float d1 = dist(x1,y1,cx,cy), d2 = dist(x2,y2,cx,cy);
    return min(d1,d2) < cr;
    
  }
  
void keyPressed(KeyEvent evt){
  if (key == 'r'){
    if (Game_Over_mode){
      reset();
      Game_Over_mode = false;
    }
  }
  if (key == 'a'){
    if(paddleX > 0){
      right = true;
    }
  }
  else{right = false;}
  
  if (key == 'd'){
    if(paddleX + paddleW < width){
      left = true;
    }
  }
  else{left = false;}
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文