如何开始然后停止运动

时间:2019-09-25 10:28:59

标签: java processing collision

我的代码在碰到蓝色方块时会停止红色方块,但是我不希望红色方块无限期地停止。我该如何解决?

我创建了碰撞检测,如果红色方块碰到蓝色方块,它会使速度= 0。

//r=red
float rx = 200;
float ry = 375;
float rw = 50;
float rh = 50;

//b=blue
float bx = 550;
float by = 375;
float bw = 50;
float bh = 50;

float speed = 2;
//float cspeed = 2;

void setup() {
  size(800, 800);
  noStroke();
  noSmooth();
  noCursor();
}

void draw() {
  surface.setTitle(mouseX + ", " + mouseY);
  background(50);
  collision();
  move();
  display();
}

void collision() {
  //Check if blue and red are touching
  boolean hit = rectRect(rx, ry, rw, rh, bx, by, bw, bh);
  if (hit) {
    speed = 0;
  } else {
    speed = 2;
  }
}

void display() {

  fill(0, 0, 255);  //Blue square
  rect(bx, by, bw, bh);

  fill(255, 0, 0);  //Red square
  rect(rx, ry, rw, rh);
}



void move() {
  //Red square movement
  if (keyPressed) {
    if (key == 'd' || key == 'D') {
      rx = rx + speed;
      if (rx > width) {
      }
    }
  }


  if (keyPressed) {
    if (key == 'a' || key == 'A') {
      rx = rx - speed;
      if (rx > width) {
      }
    }
  }

  if (keyPressed) {
    if (key == 'w' || key == 'W') {
      ry = ry - speed;
      if (ry > width) {
      }
    }
  }

  if (keyPressed) {
    if (key == 's' || key == 'S') {
      ry = ry + speed;
      if (ry > width) {
      }
    }
  }
}




boolean rectRect(float rx, float ry, float rw, float rh, float bx, float by, float bw, float bh) {

  //is red touching blue?

  if (rx + rw >= bx && 
    rx <= bx + bw &&   
    ry + rh >= by &&    
    ry <= by + bh) { 
    return true;
  }
  return false;
}

我不希望红色方块和蓝色方块重叠,但是如果它们确实接触,我想继续玩。现在,红场无限期地停止。

1 个答案:

答案 0 :(得分:2)

void collision()中,您设置了发生碰撞时正方形的速度将降低到0.01。

在正方形移动后检查碰撞

一旦正方形发生碰撞,它们将无法再移动,因此速度保持在0.01。永远。

有很多方法可以解决此问题。由于蓝色方块永远不会移动,因此您可以在碰撞重叠之前先检查一次碰撞,也可以在发生碰撞时“反弹”红色方块。

快速/简便的解决方法是修改此功能:

void move() {
  //Red square movement
  // You only need to check for input once, then for which input interests you
  if (keyPressed) {
    // I think this would look better in a switch statement, but we'll keep it an If for simplicity
    if (key == 'd' || key == 'D') {
      // checking if the square will collide BEFORE it does
      // notice that the square won't move if it detects that this move will be a collision
      if (!rectRect(rx + speed, ry, rw, rh, bx, by, bw, bh)) {
        rx = rx + speed;
      }
    }
    else if (key == 'a' || key == 'A') {
      if (!rectRect(rx - speed, ry, rw, rh, bx, by, bw, bh)) {
        rx = rx - speed;
      }
    }
    else if (key == 'w' || key == 'W') {
      if (!rectRect(rx, ry - speed, rw, rh, bx, by, bw, bh)) {
        ry = ry - speed;
      }
    }
    else if (key == 's' || key == 'S') {
      if (!rectRect(rx, ry + speed, rw, rh, bx, by, bw, bh)) {
        ry = ry + speed;
      }
    }

    if (ry > width) {
      // insert whatever you were planning with this condition
    }
  }
}

现在,void collision()已被void move()接管,因此您可以擦除void collision。从字面上讲,它永远不会发生,因为我们会在发生任何碰撞之前在 之前停止正方形。



现在...您想添加更多正方形。容易。

当然,您可以为每个正方形编写一个move函数。但这很累,而且肯定有更好的方法。

有,但这将测试您的技能。我们将使事情变得简单,以免您一不振,但是我们知道我们将进入OOP(面向对象编程)领域。如果您在学校里,那么从了解课堂上会受益匪浅(嗯,即使您不在学校里,这仍然很棒)。

首先,我们将编写一个简单的类,用于创建和管理您在此程序中使用的矩形形状。如果您使用的是Processing IDE,建议您创建一个“新建选项卡”,以使代码保持整洁。您不必非要这样做,因为编译器看不到区别,但是随着项目变得越来越复杂,制表符是组织代码的理想工具。

在新标签页中,输入以下代码:

class Rectangle {
  // This should be 'private', but I'm using 'protected' in case I wan to inherit those later, and 'public' to keep things simple
  public float x = 0;
  public float y = 0;
  public float w = 50;
  public float h = 50;
  protected boolean isVisible = true;
  protected color fillColor;

  // This is the constructor. It serves to initialize the class.
  public Rectangle(float xx, float yy, float ww, float hh, color cc) {
    x = xx;
    y = yy;
    w = ww;
    h = hh;
    fillColor = cc;
  }

  public void Render() {
    // I like to let my class draw themselves!
    if (isVisible) {
      fill(fillColor);
      rect(x, y, w, h);
    }
  }

  public void Move(float moveX, float moveY) {
    // This will be used to move. Since the variables are 'protected', they cannot be accessed from outside this class, so I have to create a tool to use them.
    // It is good practice to set 'public' only what's needed, and to manage class variables inside the class.
    // This is for many good reasons. Among those, remember that it's harder to debug 'why is my x position weird' when it can be accessed from anywhere.
    x += moveX;
    y += moveY;
  }

  public boolean Collision(float xx, float yy, float ww, float hh, float moveX, float moveY) {
    // Give coordinates to this function and it will tell you if there's a collision with this rectangle
    return Intersect(x + moveX, y + moveY, w, h, xx, yy, ww, hh);
  }
}

完成了吗?大!现在,您有了一个Rectangle类,它将包含矩形的坐标,颜色等内容。

现在,我们将不得不对您的代码进行一些更改。

首先,您不需要全局变量来跟踪红色和蓝色正方形的位置,因为这将由您刚创建的类处理。您可以删除它们。全局变量很有用,但通常来说,使用的越少越好,因为全局变量可能成为跟踪并导致无法预料的错误的噩梦。

然后,您需要将新类初始化为几个漂亮的矩形。为了使事情整洁,我们将有一个名为“ red”的矩形,以及一个将成为障碍的无名矩形的ArrayList。 ArrayList是一个很棒的工具,您以后可以学习使用。现在,我们只说它将在一个整洁的列表中包含所有这些障碍,我们将在需要时调用它。

move函数必须处理所有新的障碍,并且必须处理一个对象而不是一堆全局变量。

最后,必须更新rectRect函数。现在,它曾经检查红色和蓝色是否相交,但是从现在开始,它需要能够检查所有矩形。我们将使其更加中立,并以不同的方式使用它。

这些更改之后的代码是:

//red
Rectangle red;

//all other rectangles
ArrayList <Rectangle> rectList;

float speed = 2;
//float cspeed = 2;

void setup() {
  size(800, 800);
  noStroke();
  noSmooth();
  noCursor();

  // Initializing Red square
  red = new Rectangle(200, 375, 50, 50, color(255, 0, 0));
  // Initializing a bunch of rectangles
  rectList = new ArrayList <Rectangle>();
  rectList.add(new Rectangle(550, 375, 50, 50, color(0, 0, 255)));  // Red
  rectList.add(new Rectangle(300, 500, 50, 50, color(0, 255, 0)));  // Green
  // you can add as many as you want
}

void draw() {
  surface.setTitle(mouseX + ", " + mouseY);
  background(50);
  move();
  display();
}

void display() {
  red.Render();

  // this is a java 'For Each' loop. Research it, it's very useful.
  for ( Rectangle r : rectList) {
    r.Render();
  }
}

void move() {
  //Red square movement
  float moveX = 0;
  float moveY = 0;

  if (keyPressed) {
    // We're going calculate up how much we want to move the red square first
    // Then we'll check for collisions
    // Then we'll move the square (it there are no collisions)
    if (key == 'd' || key == 'D') {moveX += speed;}
    else if (key == 'a' || key == 'A') {moveX -= speed;}
    else if (key == 'w' || key == 'W') {moveY -= speed;}
    else if (key == 's' || key == 'S') {moveY += speed;}

    for (Rectangle r : rectList) {
      if (red.Collision(r.x, r.y, r.w, r.h, moveX, moveY)) {
        // If a collision is detected, we exit this function so there will be no move
        return;
      }      
    }

    red.Move(moveX, moveY);
  }
}

// INTERSECT RECTs
// The old function was nice, but it was really useful only with your specific example. You can re-use this one with any set of rectangles.
// There are many ways to write this function. I wrote this instance back when I was a student, and I still use it to this day.
boolean Intersect(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2)
{
  boolean checkX = false;
  boolean checkY = false;

  if ( (x1<=x2 && (x1+w1)>=x2) || (x1<=(x2+w2) && (x1+w1)>=x2+w2) || (x1>=x2 && (x1+w1)<=(x2+w2)) ) {checkX = true;}
  if ( (y1<=y2 && (y1+h1)>=y2) || (y1<=(y2+h2) && (y1+h1)>=y2+h2) || (y1>=y2 && (y1+h1)<=(y2+h2)) ) {checkY = true;}

  if (checkX && checkY) {return true;}

  return false;
}

现在,您可以添加其他任何大小和颜色的正方形和矩形了!尝试一下!但是,更重要的是,尝试理解它。如果您有任何疑问,请记住我在这里为您提供帮助。

玩得开心!