Pregunta

Im trying to create a basic pool game where one ball hits another and causes that second ball to continue in the same direction at the same speed and move the same amount of distance that the first ball moved. I've so far gotten everything to work except having that second ball continue on. Would anyone be able to help me make this work? I think my problem lies in click == 4 section of the code, but I don't understand how to fix it/add on to it.

Ball cue, billiard;
boolean fired = false;
String msg;
int click;
int steps = 20;
int difx, dify;
Boolean move = false;

void setup(){
msg = "";
size(600,300);
click = 0;
cue = new Ball(30, #FFFFFF);
billiard = new Ball(30, #000000);
}

void draw(){
background(#009900);
if(click == 0){
cue.xpos = mouseX;
cue.ypos = mouseY;
billiard.xpos = -15;
billiard.ypos = -15;
msg = "please place the cue ball";
}else if(click == 1){
billiard.xpos = mouseX;
billiard.ypos = mouseY;
msg = "click again to place billiard ball";
}else if(click ==2){
difx = cue.xpos-billiard.xpos;
dify = cue.ypos-billiard.ypos;
}else if(click == 3){
float cdistance = dist(cue.xpos,cue.ypos,billiard.xpos,billiard.ypos);
if(cdistance>billiard.ballDiam/2){
  move = true;
  cue.xpos-=difx/steps;
  cue.ypos-=dify/steps;
  msg = "You got it! Push c on your keyboard to restart";  
}else{
move = false;
cue.visible = true;
click = 4;
}
}else if(click == 4){
float cdistance = dist(cue.xpos,cue.ypos,billiard.xpos,billiard.ypos);
if(cdistance<billiard.ballDiam){
  if (dist(cue.xpos, cue.ypos, billiard.xpos, billiard.ypos) < sqrt(sq(difx)+sq(dify))) {
  move = true;
  billiard.xpos-=difx/steps;
  billiard.ypos-=difx/steps;
  }
}
}
cue.update();
billiard.update();
textSize(20);
text(msg,0,height-5);
}

void mouseClicked(){
 if(!move){
 click++;
 }
}

class Ball{
  int xpos, ypos;
  int ballDiam;
  color myColor;
  boolean visible = true;
  Ball(int tempdiam,color tempColor){
  ballDiam=tempdiam;
  myColor=tempColor;
}

void update(){
  if(visible){
  fill(myColor);
  ellipse(xpos,ypos,ballDiam,ballDiam);
  }
 }
}
¿Fue útil?

Solución 2

Here's your solution (but you have to re-design your program too):

Ball cue, billiard;
boolean fired = false;
String msg;
int click;
int steps = 20;
int difx, dify;
Boolean move = false;
Boolean continueMoving;

void setup() {
  msg = "";
  size(600, 300);
  click = 0;
  cue = new Ball(30, #FFFFFF);
  billiard = new Ball(30, #000000);
  continueMoving = false;
}

void draw() {
  background(#009900);
  if (click == 0) {
    cue.xpos = mouseX;
    cue.ypos = mouseY;
    billiard.xpos = -15;
    billiard.ypos = -15;
    msg = "please place the cue ball";
  }
  else if (click == 1) {
    billiard.xpos = mouseX;
    billiard.ypos = mouseY;
    msg = "click again to place billiard ball";
  }
  else if (click ==2) {
    difx = cue.xpos-billiard.xpos;
    dify = cue.ypos-billiard.ypos;
  }
  else if (click == 3) {
    float cdistance = dist(cue.xpos, cue.ypos, billiard.xpos, billiard.ypos);
    if (cdistance>billiard.ballDiam/2) {
      move = true;
      cue.xpos-=difx/steps;
      cue.ypos-=dify/steps;
      msg = "You got it! Push c on your keyboard to restart";
    }
    else {
      move = false;
      cue.visible = true;
      click = 4;
    }
  }
  else if (click == 4)
  {
    float cdistance = dist(cue.xpos, cue.ypos, billiard.xpos, billiard.ypos);
    if (cdistance<billiard.ballDiam)
    {
      if (dist(cue.xpos, cue.ypos, billiard.xpos, billiard.ypos) < sqrt(sq(difx)+sq(dify))) {
        move = true;
        continueMoving = true;
        billiard.xpos-=difx/steps;
        billiard.ypos-=dify/steps;
        //print(click);
      }
    }
  }

  if (continueMoving)
  {
        billiard.xpos-=difx/steps;
        billiard.ypos-=dify/steps;
  }

  cue.update();
  billiard.update();
  textSize(20);
  text(msg, 0, height-5);
  print(click);
}//draw

void mouseClicked() {
  if (!move) {
    click++;
  }
}

class Ball 
{
  int xpos, ypos;
  int ballDiam;
  color myColor;
  boolean visible = true;
  Ball(int tempdiam, color tempColor) {
    ballDiam=tempdiam;
    myColor=tempColor;
  }

  void update() {
    if (visible) {
      fill(myColor);
      ellipse(xpos, ypos, ballDiam, ballDiam);
    }
  }
}//Ball class

First, instead of using if else statements, use switch. Second, don't put all your code in the draw function. You can put your switch statements there, but shift the code within the conditions to some functions outside the draw function. Google for how other people have created snooker/billiards games, and you'll get to know other different types of logic. Mostly, they will be using a for or while loop to keep the game going. And that loop will be the same as your draw function.

If you're new to StackOverflow, you can click the arrow button pointing up on this page to give me a few points for this answer, and click the tick mark to mark this as the accepted answer.

Otros consejos

Your first stop should be the examples that come with Processing, specifically the CircleCollision example inside the Motion section. That example includes all of the logic for bouncing balls off of one another using more-or-less realistic physics.

/**
 * Circle Collision with Swapping Velocities
 * by Ira Greenberg. 
 * 
 * Based on Keith Peter's Solution in
 * Foundation Actionscript Animation: Making Things Move!
 */

Ball[] balls =  { 
  new Ball(100, 400, 20), 
  new Ball(700, 400, 80) 
};

void setup() {
  size(640, 360);
}

void draw() {
  background(51);

  for (Ball b : balls) {
    b.update();
    b.display();
    b.checkBoundaryCollision();
  }

  balls[0].checkCollision(balls[1]);
}

class Ball {
  PVector position;
  PVector velocity;

  float r, m;

  Ball(float x, float y, float r_) {
    position = new PVector(x, y);
    velocity = PVector.random2D();
    velocity.mult(3);
    r = r_;
    m = r*.1;
  }

  void update() {
    position.add(velocity);
  }

  void checkBoundaryCollision() {
    if (position.x > width-r) {
      position.x = width-r;
      velocity.x *= -1;
    } 
    else if (position.x < r) {
      position.x = r;
      velocity.x *= -1;
    } 
    else if (position.y > height-r) {
      position.y = height-r;
      velocity.y *= -1;
    } 
    else if (position.y < r) {
      position.y = r;
      velocity.y *= -1;
    }
  }

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


  void display() {
    noStroke();
    fill(204);
    ellipse(position.x, position.y, r*2, r*2);
  }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top