Как начать и остановить движение - PullRequest
3 голосов
/ 25 сентября 2019

Мой код останавливает красный квадрат, когда он касается синего квадрата, но я не хочу, чтобы красный квадрат останавливался бесконечно.Как я могу это исправить?

Я создал обнаружение столкновений, и он делает скорость = 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 Ответ

2 голосов
/ 25 сентября 2019

В 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 функцию для каждого квадрата.Но это утомительно, и наверняка должен быть лучший способ.

Есть, но это проверит ваши навыки.Мы сделаем все просто, чтобы не перегружать вас сразу, но знаем, что мы собираемся проникнуть на территорию ООП (объектно-ориентированного программирования).Если вы учитесь в школе, вы получите много пользы от понимания урока (ну, даже если вы не в школьном классе, все равно классно).

Сначала мы напишем простой урок, который мы можемиспользуйте для создания и управления прямоугольниками, которые вы используете в этой программе.Если вы используете 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 из безымянных прямоугольников, которые будут препятствиями.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;
}

Теперь вы можете добавить кучу других квадратов и прямоугольников любого размера.и цвета!Попробуй!Но, что более важно, попытайтесь понять это.Если у вас есть вопросы, помните, что я здесь, чтобы помочь.

Веселитесь!

...