首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >台球互相卡在一起

台球互相卡在一起
EN

Stack Overflow用户
提问于 2016-04-15 02:03:19
回答 1查看 141关注 0票数 0

我正在为我的Java类设计一个台球游戏。我对台球碰撞有意见。球相互碰撞,偶尔滑入对方,变得卡住。我似乎找不出这个错误的原因。我希望有人能帮我找出问题的原因。我的代码如下。谢谢。

代码语言:javascript
复制
    float cueX = 200;
    float cueY = 225;
    float cueDeltaX;
    float cueDeltaY;
    float ballWidth = 25;
    float score = 0;

    Billiards[] billiards = new Billiards[3];

    void setup()
    {
      size (850, 450);
      background(0);
      fill(#29B748);
      rect(0, 0, 599, 599);
      billiards[0] = new Billiards(600, 225, 0, 0, false, "", 0);
      billiards[1] = new Billiards(625, 211, 0, 0, false, "", 1);
      billiards[2] = new Billiards(625, 239, 0, 0, false, "", 2);
      //billiards[3] = new Billiards(625, 250, 0, 0, false, "", 2);
    }

    void draw()
    { 
      background(0);
      fill(#FFFFFF);
      stroke(#A6A7A6);
      text("DeltaX: " + cueDeltaX + "  Delta Y: " + cueDeltaY, 20, 20);
      text(score, 500, 20);
      fill(#29B748);
      rect(25, 25, 799, 399);
      poolCueLines();
      drawCue();
      moveCue();
      cueBounce();
      cueFriction();

      drawBilliards();
      billiards[0].collision();
      billiards[0].moveBall();
      billiards[0].billiardBounce();
      billiards[0].billiardFriction();

      billiards[1].collision();
      billiards[1].moveBall();
      billiards[1].billiardBounce();
      billiards[1].billiardFriction();

      billiards[2].collision();
      billiards[2].moveBall();
      billiards[2].billiardBounce();
      billiards[2].billiardFriction();
    }

    void poolCueLines() {
      if (mousePressed)
      {
        stroke(#FFFFFF);
        line(cueX, cueY, mouseX, mouseY);
      }
    }

    void mouseReleased()
    {
      cueDeltaX = (cueX - mouseX)/50;
      cueDeltaY = (cueY - mouseY)/50;
    }

    void drawCue() {
      noStroke();
      fill(0);
      fill(#FFFFFF);
      stroke(#A6A7A6);
      ellipse(cueX, cueY, ballWidth, ballWidth);
      noFill();
    }

    void moveCue() {
      cueX += cueDeltaX;
      cueY += cueDeltaY;
    }

    void cueBounce() {
      if (cueX > width-25-ballWidth/2 || cueX < 25 + ballWidth/ 2) {
        cueDeltaX = -cueDeltaX;
        cueDeltaX = cueDeltaX * 0.6;
        if (cueX < 25+ ballWidth/2) {
          cueX = 26 + ballWidth/2;
        } else {
          cueX = width-26-ballWidth/2;
        }
      }

      if (cueY > height-25-ballWidth/2 || cueY < 25 + ballWidth/ 2) {
        cueDeltaY = -cueDeltaY;
        cueDeltaY = cueDeltaY * 0.6;
        if (cueY < 25+ ballWidth/2) {
          cueY = 26 + ballWidth/2;
        } else {
          cueY = height-26-ballWidth/2;
        }
      }
    }

    void drawBilliards() {

      //Yellow Ball 1
      fill(#ffff00);
      stroke(#A6A7A6);
      ellipse(billiards[0].ballXpos, billiards[0].ballYpos, ballWidth, ballWidth);

      //Blue 2
      fill(#000099);
      stroke(#A6A7A6);
      ellipse(billiards[1].ballXpos, billiards[1].ballYpos, ballWidth, ballWidth);

      //Red 3
      fill(#ff0000);
      stroke(#A6A7A6);
      ellipse(billiards[2].ballXpos, billiards[2].ballYpos, ballWidth, ballWidth);
    }

    void cueFriction() {
      cueDeltaX = cueDeltaX * 0.995;
      cueDeltaY = cueDeltaY * 0.995;
    }

    class Billiards
    {
      float ballXpos;
      float ballYpos;
      float deltaXball;
      float deltaYball;
      int billiardsNum;

      Billiards(float tempXpos, float tempYpos, float deltaXbill, float deltaYbill, boolean stripe, String stripeColor, int billiardNum) {
        ballXpos = tempXpos;
        ballYpos = tempYpos;
        deltaXball = deltaXbill;
        deltaYball = deltaYbill;
        billiardsNum = billiardNum;
      }

      void collision() {
        if (cueX > ballXpos-ballWidth && cueX < ballXpos+ballWidth) {
          if (cueY < ballYpos+ballWidth && cueY > ballYpos-ballWidth) {
            cueDeltaX = -cueDeltaX * 0.8;
            deltaXball = -cueDeltaX * 0.6;
            cueDeltaY = -cueDeltaY * 0.8;
            deltaYball = -cueDeltaY * 0.6;
          }
        }

        int ballNum = 0;
        for (int i=0; i < 3; i++) {
          if (billiards[ballNum].ballXpos > ballXpos-ballWidth && billiards[ballNum].ballXpos < ballXpos+ballWidth) {
            if (billiards[ballNum].ballYpos < ballYpos+ballWidth && billiards[ballNum].ballYpos > ballYpos-ballWidth) {
              if (billiardsNum == ballNum) {
              } else {
                //if (billiards[ballNum].deltaXball < 0.2 || billiards[ballNum].deltaYball < 0.2) {
                  if (deltaXball > 0){
                   billiards[ballNum].ballXpos += -3;
                  }else if (deltaXball < 0){
                   billiards[ballNum].ballXpos += 3;
                  }

                  if (deltaYball > 0){
                   billiards[ballNum].ballXpos += -3;
                  }else if (deltaYball < 0){
                   billiards[ballNum].ballXpos += 3;
                  }
                  billiards[ballNum].deltaXball = -billiards[ballNum].deltaXball * 0.8;
                  deltaXball = -billiards[ballNum].deltaXball * 0.6;
                  billiards[ballNum].deltaYball = -billiards[ballNum].deltaYball * 0.8;
                  deltaYball = -billiards[ballNum].deltaYball * 0.6;
                //}
                //} else {
                //  billiards[ballNum].deltaXball = -billiards[ballNum].deltaXball * 0.8;
                //  deltaXball = -billiards[ballNum].deltaXball * 0.6;
                //  billiards[ballNum].deltaYball = -billiards[ballNum].deltaYball * 0.8;
                //  deltaYball = -billiards[ballNum].deltaYball * 0.6;
                //}
              }
            }
          }
          ballNum += 1;
        }
      }

      void moveBall() {
        ballXpos += deltaXball;
        ballYpos += deltaYball;
      }

      void billiardBounce() {
        if (ballXpos > width-25-ballWidth/2 || ballXpos < 25 + ballWidth/ 2) {
          deltaXball = -deltaXball;
          deltaXball = deltaXball * 0.6;
          if (ballXpos < 25+ ballWidth/2) {
            ballXpos = 26 + ballWidth/2;
          } else {
            ballXpos = width-26-ballWidth/2;
          }
        }

        if (ballYpos > height-25-ballWidth/2 || ballYpos < 25 + ballWidth/ 2) {
          deltaYball = -deltaYball;
          deltaYball = deltaYball * 0.6;
          if (ballYpos < 25+ ballWidth/2) {
            ballYpos = 26 + ballWidth/2;
          } else {
            ballYpos = height-26-ballWidth/2;
          }
        }
      }

      void billiardFriction() {
        deltaXball = deltaXball * 0.995;
        deltaYball = deltaYball * 0.995;
      }
    }
EN

回答 1

Stack Overflow用户

发布于 2016-04-15 02:14:04

嗯,问题出在你的碰撞代码上。这里有很多神奇的硬编码数字,并且没有任何注释来描述它们的用途。这将使调试变得非常困难,这使得它很难帮助您。

但我突然想到的一件事是,你在处理碰撞和运动是分开的。这可能是可以的,但根据您的操作方式,您可以让自己处于这种情况:

  • 假想球A在球B和球C之间。
  • A正在向右移动。
  • 你检查球A的碰撞,它与球B发生碰撞。现在你告诉球A开始向左移动。
  • 你然后将球A向左移动,,但你不检查这是否会导致碰撞。<
  • >E29>现在球A和球C是向右移动的,然后检查它的碰撞。<
  • >E29>果然,它正在与球A相撞,所以你告诉它开始向左移动。
  • 现在球A和球C都在向左移动,尽管它们正在碰撞。

您可能希望通读并添加注释,直到您确切了解代码正在做什么为止。但老实说,这并不是一个简单的问题。你最好从一个空白的草图开始,从更简单的东西开始。尝试将您的问题范围缩小到MCVE。而不是发布整个草图,只需将其缩小到使用硬编码值而不是用户输入的两个圆圈碰撞的特定情况。

您可能还想看看处理编辑器附带的CircleCollision示例。只需转到文件运动示例->主题-> CircleCollision,您将看到一个草图,其中显示了处理圆碰撞的示例。

下面是该示例中的冲突代码:

代码语言:javascript
复制
void checkCollision(Ball other) {

    // get distances between the balls components
    PVector bVect = PVector.sub(other.position, position);

    // calculate magnitude of the vector separating the balls
    float bVectMag = bVect.mag();

    if (bVectMag < r + other.r) {
      // get angle of bVect
      float theta  = bVect.heading();
      // precalculate trig values
      float sine = sin(theta);
      float cosine = cos(theta);

      /* bTemp will hold rotated ball positions. You 
       just need to worry about bTemp[1] position*/
      PVector[] bTemp = {
        new PVector(), new PVector()
        };

        /* this ball's position is relative to the other
         so you can use the vector between them (bVect) as the 
         reference point in the rotation expressions.
         bTemp[0].position.x and bTemp[0].position.y will initialize
         automatically to 0.0, which is what you want
         since b[1] will rotate around b[0] */
        bTemp[1].x  = cosine * bVect.x + sine * bVect.y;
      bTemp[1].y  = cosine * bVect.y - sine * bVect.x;

      // rotate Temporary velocities
      PVector[] vTemp = {
        new PVector(), new PVector()
        };

        vTemp[0].x  = cosine * velocity.x + sine * velocity.y;
      vTemp[0].y  = cosine * velocity.y - sine * velocity.x;
      vTemp[1].x  = cosine * other.velocity.x + sine * other.velocity.y;
      vTemp[1].y  = cosine * other.velocity.y - sine * other.velocity.x;

      /* Now that velocities are rotated, you can use 1D
       conservation of momentum equations to calculate 
       the final velocity along the x-axis. */
      PVector[] vFinal = {  
        new PVector(), new PVector()
        };

      // final rotated velocity for b[0]
      vFinal[0].x = ((m - other.m) * vTemp[0].x + 2 * other.m * vTemp[1].x) / (m + other.m);
      vFinal[0].y = vTemp[0].y;

      // final rotated velocity for b[0]
      vFinal[1].x = ((other.m - m) * vTemp[1].x + 2 * m * vTemp[0].x) / (m + other.m);
      vFinal[1].y = vTemp[1].y;

      // hack to avoid clumping
      bTemp[0].x += vFinal[0].x;
      bTemp[1].x += vFinal[1].x;

      /* Rotate ball positions and velocities back
       Reverse signs in trig expressions to rotate 
       in the opposite direction */
      // rotate balls
      PVector[] bFinal = { 
        new PVector(), new PVector()
        };

      bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
      bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
      bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
      bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;

      // update balls to screen position
      other.position.x = position.x + bFinal[1].x;
      other.position.y = position.y + bFinal[1].y;

      position.add(bFinal[0]);

      // update velocities
      velocity.x = cosine * vFinal[0].x - sine * vFinal[0].y;
      velocity.y = cosine * vFinal[0].y + sine * vFinal[0].x;
      other.velocity.x = cosine * vFinal[1].x - sine * vFinal[1].y;
      other.velocity.y = cosine * vFinal[1].y + sine * vFinal[1].x;
    }
  }

您还可以查看上述示例的web版本:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36630681

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档