基本池游戏问题

时间:2014-04-22 03:11:56

标签: processing

我试图创建一个基本的游泳池游戏,其中一个球击中另一个球并使第二个球以相同的速度在相同的方向上继续并移动与第一个球移动相同的距离。到目前为止,除了让第二球继续下去之外,我已经完成了所有工作。有人能帮我做这个工作吗?我认为我的问题在于代码的click == 4部分,但我不明白如何解决它/添加它。

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

2 个答案:

答案 0 :(得分:0)

您的第一站应该是Processing附带的示例,特别是Motion部分内的CircleCollision示例。这个例子包括使用或多或少逼真的物理学将球弹射出来的所有逻辑。

/**
 * 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);
  }
}

答案 1 :(得分:-1)

这是您的解决方案(但您也必须重新设计您的计划):

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

首先,使用if else而不是switch语句。其次,不要将所有代码放在draw函数中。您可以将switch语句放在那里,但是将条件中的代码转移到draw函数之外的某些函数。 Google了解其他人如何制作斯诺克/台球游戏,并且您将了解其他不同类型的逻辑。大多数情况下,他们将使用forwhile循环来保持游戏的进行。该循环与您的draw函数相同。

如果您是StackOverflow的新用户,可以点击此页面上的箭头按钮,为我的答案提供几点,然后点击勾选标记将其标记为已接受的答案。