2016-04-14 4 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. Этот класс является драйвером, так как обработка автоматически вызывает определенные функции для вас. У него нет метода 'main()', такого как Java. –

ответ

1

Ну, проблема в вашем коллизионном коде. У вас много магических жестко закодированных номеров и нулевые комментарии, описывающие, для чего они нужны. Это очень сложно отладить, что затрудняет вам помощь.

Но одна вещь, которая подскакивает мне, заключается в том, что вы управляете столкновением отдельно от движения. Это может быть хорошо, но с тем, как вы делаете это, вы можете получить в этой ситуации:

  • Представьте Болл быть между Болл B и C. Шаровой
  • шарика A движется вправо.
  • Вы проверяете столкновение Ball A, и оно сталкивается с Ball B. Теперь вы говорите Ball A, чтобы начать движение влево.
  • Затем вы перемещаете Ball A влево, , но вы не проверяете, приведет ли это к столкновению. Итак, теперь Ball A и Ball C сталкиваются.
  • Ball C двигался вправо, но затем вы проверяли его столкновение. Конечно же, он сталкивается с Ball 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; 
    } 
    } 

Вы можете также просмотреть веб-версии приведенного выше примера:

Смежные вопросы