2016-04-14 40 views
0

我正在爲我的Java課設計一個檯球遊戲。我遇到檯球碰撞問題。球撞到對方,偶爾滑入對方,卡住了。我似乎無法確定這個錯誤的原因。我希望有人能幫助我找出問題的原因。我的代碼如下。謝謝。檯球撞到彼此

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; 
     } 
    } 
+1

請提供重現問題的驅動程序以及適用的跟蹤輸出在有問題的對象上。在這裏至少應該有一些打印語句來查明發生了什麼,如果不是確切地說是怎麼出錯的話。 – Prune

+0

@Prune雖然我同意這是一個太多的代碼,但請注意,這是[tag:processing],而不是Java。此類是驅動程序,因爲Processing會自動爲您調用某些功能。它沒有像Java那樣的'main()'方法。 –

回答

1

那麼,問題出在你的碰撞代碼中。你有很多魔術硬編碼的數字,而零註釋描述他們的用途。這會使調試非常困難,這很難幫助你。跳轉出來給我

但有一件事是,你分開運動處理衝突。這可能是正確的,但你怎麼做,你可以讓自己在這種情況下:

  • 想象一下球的球B和C.球
  • 球之間被移動到右側。
  • 您檢查球A的碰撞,並與球B碰撞。現在您告訴球A開始向左移動。
  • 你再移動球到左側,但你不檢查是否將導致碰撞。所以現在球A和球C相撞。
  • 球C正在向右移動,但是然後你檢查它的碰撞。果然,它與A球碰撞,所以你告訴它開始向左移動。
  • 現在球A和球C都移動到左側,即使它們正在碰撞。

您可能想要完成並添加註釋,直到您完全明白您的代碼在做什麼爲止。但說實話,這不是一個簡單的問題。您可能會更好地從一張空白的草圖開始,並從簡單的事情開始。嘗試將問題縮小至MCVE。不要張貼您的整個草圖,只需將它縮小到特定情況下,使用硬編碼值而不是用戶輸入的兩個圓碰撞。

你可能也想看看自帶的編輯處理的CircleCollision例子。只需進入文件 - >示例 - >主題 - >動作 - > CircleCollision,您將看到一個草圖,顯示處理圓形碰撞的示例。

下面是從例如碰撞代碼:

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的版本: