如何开始然后停止运动

How to start then stop movement

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

我已经创建了碰撞检测,如果红色方块接触到蓝色方块,它会使速度 = 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;
}

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

void collision()中你设置了当发生碰撞时方块的速度会降低到0.01。

你在方块移动后检查碰撞

一旦你的方块发生碰撞,它们就不能再移动了,所以速度停留在0.01。永远。

有很多方法可以解决这个问题。由于蓝色方块永远不会移动,您可以在它们重叠之前先检查碰撞,或者 "bounce" 红色方块在发生碰撞时检查。

一个 fast/easy 修复方法是修改此函数:

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(面向对象编程)领域。如果你在学校,你会从理解 class 中获益良多(好吧,即使你不在学校 class 仍然很棒)。

首先,我们将编写一个简单的 class 可用于创建和管理您在此程序中使用的矩形形状。如果您使用的是 Processing IDE,我建议您创建一个 "New Tab",以便我们保持代码整洁。您不一定非要这样做,因为编译器看不出差异,但是随着您的项目变得越来越复杂,选项卡是组织代码的好工具。

在您的新标签页中,输入此代码:

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 class,它将包含矩形的坐标、颜色等内容。

现在我们必须对您的代码进行一些更改。

首先,您不需要全局变量来跟踪红色和蓝色方块的位置,因为这将由您刚刚创建的 class 处理。你可以删除那些。全局变量很有用,但作为一般规则,您使用的越少越好,因为全局变量可能成为跟踪的噩梦并导致无法预料的错误。

然后,您需要将新 class 初始化为几个漂亮的矩形。为了保持整洁,我们将有一个名为 'red' 的矩形,以及一个由无名矩形组成的 ArrayList,它们将成为障碍物。 ArrayLists 是一个很棒的工具,您可以稍后学习使用;现在我们只说它将所有这些障碍包含在一个整洁的列表中,我们会在需要时调用它。

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

现在您可以添加一堆其他任何大小和颜色的正方形和长方形!尝试一下!但是,更重要的是,试着理解它。如果您有任何疑问,请记住我是来帮忙的。

玩得开心!