[30 minutes] completion canvas animation | game basis (4): Boundary and Collision

Foreword

Several objects often appear in this series ran out of canvas case herein, this is to solve this problem.
Read this before you are asked to lay in front of the base.
They have limited ability to welcome people to discuss cattle, criticism.

Cross-border detection

It assumed that the object is circular, i.e., its center coordinates of x-axis in FIG object and a y-axis coordinates.
Cross-border scenarios are common, generally have two cross-border scenarios: First, the entire object out of the area, and second object touches the border area. We discuss the canvas boundaries, for example, example rectangular boundary that is:

let top = 0;
let bottom = canvas.height;
let left = 0;
let right = canvas.width;

boundary

Out of the entire area of ​​the object

To be considered departing from the scope bounds the entire object, bounds can be obtained under the following conditions, to any of the following is true determination of range.

// 右侧越界
object.x - object.width/2 > right
// 左侧越界
object.x + object.width/2 < left
// 上部越界
object.y + object.height/2 < top
// 下部越界
object.y - object.height/2 > bottom

Object touches the border region

Even if the object is in contact boundary region bounds, bounds can be obtained under the following conditions, to any of the following is true determination of range.

// 右侧越界
object.x + object.width/2 > right
// 左侧越界
object.x - object.width/2 < left
// 上部越界
object.y - object.height/2 < top
// 下部越界
object.y + object.height/2 > bottom

How to do cross-border

After thoroughly understand cross-border conditions, discussed next, after the cross-border approach, usually about four.

The object is removed

This is the simplest way to handle the situation belongs to the whole body out of the area considered out of bounds.
The following example will first batch create ball, balls stored in the array, each animation cycle will traverse the array, followed by input draw () function, change the position of the ball and detect whether cross-border. The following describes only () function code draw.
Complete example: Clear bounds round

function draw(ball, pos) {
  // 依据球的速度改变球的位置
  ball.x += ball.vx;
  ball.y += ball.vy;
  // 检查是否越界
  if (ball.x - ball.radius > canvas.width || ball.x + ball.radius < 0 || ball.y - ball.radius > canvas.height || ball.y + ball.radius < 0) {
    // 在数组中清除越界的球
    balls.splice(pos, 1);
    // 打印提示
    if (balls.length > 0) {
      log.value += `Removed ${ball.id}\n`;
      log.scrollTop = log.scrollHeight;
    } else {
      log.value += 'All gone!\n';
    }
  }
  // 画球
  ball.draw(context);
}

It is set back within the boundaries of the object

It belongs to the region where the object is considered out of bounds.
The following are examples of the balls in the ball save the created array, the initial position of the ball is in the middle of the lower portion of the canvas, with a ball out of range if the detected position of the ball is reset. The following describes only () function code draw.
Complete example: Color fountain

function draw(ball) {
  // 依据球的速度改变球的位置,这里包含了伪重力
  ball.vy += gravity;
  ball.x += ball.vx;
  ball.y += ball.vy;
  // 检测是否越界
  if (ball.x - ball.radius > canvas.width || ball.x + ball.radius < 0 || ball.y - ball.radius > canvas.height || ball.y + ball.radius < 0) {
    // 重置ball的位置
    ball.x = canvas.width / 2;
    ball.y = canvas.height;
    // 重置ball的速度
    ball.vx = Math.random() * 6 - 3;
    ball.vy = Math.random() * -10 - 10;
    // 打印提示
    log.value = `Reset ${ball.id}\n`;
  }
  // 画球
  ball.draw(context);
}

Screen surround

It belongs to the region where the object is considered out of bounds.
Around the screen it is to make an object appear the same in another location within the boundary, if an object is removed from the left side of the screen, it will appear again in the right of the screen, and vice versa, is the same reason the vertical.
Here is somewhat more complicated than the previous jump judgment object side is bounded, pseudo-code as follows:

if(object.x - object.width/2 > right){
    object.x = left - object.widht/2;
}else if(object.x + object.width/2 < left){
    object.x = right + object.width/2;
}
if(object.y - object.height/2 > bottom){
    object.y = top - object.height/2;
}else if(object.y + object.height/2 < top){
    obejct.y = bottom + object.height/2;
}

Rebound (rough version)

This is a more complex case, the object belongs to the boundary even if the contact area where the cross-border. The basic idea:

  1. If the object is across arbitrary boundaries;
  2. If cross-border, immediately set back to the object boundary;
  3. Reversing the direction of the velocity vector of the object.

The following example is a ball moving in the canvas, it hit the boundary bounce in the core code is as follows.
Complete example: bouncing ball (rough version)

if (ball.x + ball.radius > right) {
  ball.x = right - ball.radius;
  vx *= -1;
} else if (ball.x - ball.radius < left) {
  ball.x = left + ball.radius;
  vx *= -1;
}
if (ball.y + ball.radius > bottom) {
  ball.y = bottom - ball.radius;
  vy *= -1;
} else if (ball.y - ball.radius < top) {
  ball.y = top + ball.radius;
  vy *= -1;
}

Rebound (perfect version)

Glance, seem good results, but think about it, we practice like this will set back the boundaries of the object is accurate it?
The answer is no, the ideal and the actual rebound rally is different, as shown below:

Ideal and actual bounce bounce

From the figure we can clear know, ball actually is not likely to rebound in an ideal rally point, because if the speed is too large, the calculation of the position of ball has crossed the "ideal bounce point" to reach the "real bounce point", and we If only the x coordinate of the ball on the boundary to move simple and crude, it still can not be "ideal bounce point", that this rebound was not conducted.
So, perfect bounce ideas clearly, we need to find the "ideal bounce point", and the ball is set to that point. If the left side is out of range, then calculates the "bounce over point" and "point of the actual rebound" from the y-axis; if the upper and lower bounds, then calculates the "bounce over point" and the "actual bounce point" on the x-axis distance. As shown, the left and right sides of the idea to cross-border as an example:

Seeking the ideal point rally

  1. It can be obtained from the velocity direction of the object arc angle;
  2. Calculating "real rally point" and "over the bounce" distance in the x-axis;
  3. Based tangent seeking "real rally point" and "over the bounce" from the y-axis;
  4. "Over the bounce" that is the y-coordinate "real rally point" plus this distance.

After transformation, the core code is as follows, as there is no need to do so much calculation, it is necessary to weigh the performance and precision.
Complete example: bouncing ball (perfect version)

if (ball.x + ball.radius > right) {
  const dx = ball.x - (right - ball.radius);
  const dy = Math.tan(angle) * dx;
  ball.x = right - ball.radius;
  ball.y += dy;
  vx *= bounce;
} else if (ball.x - ball.radius < left) {
  const dx = ball.x - (left + ball.radius);
  const dy = Math.tan(angle) * dx;
  ball.x = left + ball.radius;
  ball.y += dy;
  vx *= bounce;
}
if (ball.y + ball.radius > bottom) {
  const dy = ball.y - (bottom - ball.radius);
  const dx = dy / Math.tan(angle);
  ball.y = bottom - ball.radius;
  ball.x += dx;
  vy *= bounce;
} else if (ball.y - ball.radius < top) {
  const dy = ball.y - (top + ball.radius);
  const dx = dy / Math.tan(angle);
  ball.y = top + ball.radius;
  ball.x += dx;
  vy *= bounce;
}

Impact checking

And bounds checking like, we extend to collision detection between two objects, commonly used in the following two ways.

Geometry based collision detection

Is generally used in collision detection rectangular , is to determine whether a principle object and another object overlap.
The following two utility functions are given directly detected. Complete example:

// 两个矩形碰撞检测
function intersects(rectA, rectB) {
  return !(rectA.x + rectA.width < rectB.x ||
    rectB.x + rectB.width < rectA.x ||
    rectA.y + rectA.height < rectB.y ||
    rectB.y + rectB.height < rectA.y);
};
// 矩形与点碰撞检测
function containsPoint(rect, x, y) {
  return !(x < rect.x || x > rect.x + rect.width || y < rect.y || y > rect.y + rect.height);
};

Collision detection based on distance

Is generally used in the detection circular collision , the principle is to determine whether two objects close enough to collide.
For the round, as long as two center distance is less than the radius of the circle and two, we can determine that a collision. Center distance by the Pythagorean theorem is obtained. The core code is as follows:
Complete example: two round distance-based collision demo

const dx = ballB.x - ballA.x;
const dy = ballB.y - ballA.y;
const dist = Math.sqrt(dx ** 2 + dy ** 2);

if (dist < ballA.radius + ballB.radius) {
  log.value = 'Hit!';
} else {
  log.value = '';
}

Guess you like

Origin www.cnblogs.com/baimeishaoxia/p/11962552.html