Collision detection: Transformation

Introduction

stay Collision Detection : Triangle The collision detection of triangles is considered from another idea. So far, the introduction is static detection, and then let's take a look at dynamic collision detection.

The following examples are not checked for compatibility. It is recommended to view them in the latest Chrome browser.

Transformation

This is Sample page.

Based on canvas translate, rotate, scale The animation formed by three transformations to see how to carry out dynamic collision detection.

The animation principle based on canvas is to redraw every other period of time, so the static collision detection is actually carried out at a specific time, so the methods previously introduced are also applicable, which are used uniformly here Polygon/Polygon Methods in. With the detection method, the next step is to obtain the dynamically changing coordinates of the relevant points in the screen. The following describes the situation.

translate

When painting on canvas, the positioning is based on the coordinate system. The upper left corner of the canvas is the origin of the coordinate system, the horizontal right is the positive direction of X axis, and the vertical down is the positive direction of Y axis. Draw a rectangle rect(20, 20, 40, 40) in the coordinate system as follows:

If you want to move 60 pixels horizontally to the right and 80 pixels vertically downward, you can add the coordinates directly: rect(20 + 60, 20 + 80, 40, 40).

But there is another, more interesting way: to move the entire axis. If you move the entire coordinate axis horizontally to the right by 60 pixels and vertically downward by 80 pixels, it is exactly the same visually. The translate method uses this method.

It can be seen from the above figure that this method does not consider the coordinate change of the rectangle, and it will be much more convenient when dealing with complex graphics.

It should be noted that after translating, you need to reset the coordinate axis, because there may be other graphics, and the original coordinate axis is still used as a reference. Reset axis usage setTransform method:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx.translate(50, 50);
ctx.fillRect(0,0,100,100);

// Reset
ctx.setTransform(1, 0, 0, 1, 0, 0);

// Other treatment

For the changed coordinates, add and subtract the translated pixels directly.

/**
 * Suppose point A(x,y) reaches B(m,n) after translating (x1, Y1)
 */
 const m = x + x1;
 const n = y + y1;

rotate

The rotate method is similar to the translate method by rotating the coordinate axis.

For the changed coordinates, some calculations are needed.

/**
 *
 * The center coordinate O (0, 0), assuming that point A(x,y) forms an angle with the X axis of α
 * Clockwise rotation angle β  After reaching point B(m,n), let's deduce the coordinates of point B
 *
 * A Distance to the center of the circle: dist1 = | OA | = Y / sin( α)= x/cos( α)
 * B Distance to the center of the circle: dist2 = | ob | = n / sin( α-β)= m/cos( α-β)
 *
 * Only rotation, so dist1 = dist2, the radius of construction rotation is r:
 * r = y/sin(α)=x/cos(α)=n/sin(α-β)=m/cons(α-β)
 * y = r * sin(α)  x = r * cos(α)
 *
 * According to the trigonometric function formula:
 * sin(α+β)=sin(α)cos(β)+cos(α)sin(β)
 * sin(α-β)=sin(α)cos(β)-cos(α)sin(β)
 * cos(α+β)=cos(α)cos(β)-sin(α)sin(β)
 * cos(α-β)=cos(α)cos(β)+sin(α)sin(β)
 *
 * Substitute the following formula:
 * m = r*cos(α-β) = r * cos(α)cos(β) + r * sin(α)sin(β) =  x * cos(β) + y * sin(β)
 * n = r*sin(α-β) = r * sin(α)cos(β) - r * cos(α)sin(β) =  y * cos(β) - x * sin(β)
 *
 * Counterclockwise is the opposite:
 * m =  x * cos(β) - y * sin(β)
 * n =  y * cos(β) + x * sin(β)
 *
 */

scale

The scale method is similar to the translate method, which is realized by scaling the coordinate axis.

For the changed coordinates, directly multiply by the corresponding scaling multiple.

/**
 * Suppose point A(x,y) reaches B(m,n) after scale(num1,num2)
 */
const m = x * num1;
const n = y * num2;

Transformation Order

When several different transformations are carried out continuously, the order is different, and the results may be different. This is Examples.

This is because the continuous transformation is based on the state after the last transformation. When calculating, we need to consider many aspects. be based on transform It will be more convenient to calculate the parameter format in. The effects of translate, rotate and scale can be converted into the form of transform.

/**
 * canvas.transform(sx, ry, rx, sy, tx, ty)
 * sx-Horizontal zoom, ry vertical tilt, rx horizontal tilt, sy vertical zoom, tx horizontal move, ty vertical move
 *
 */
function Transform() {
  this.reset();
}

Transform.prototype.reset = function() {
  this.transformData = [1,0,0,1,0,0];
};

Transform.prototype.translate = function(x, y) {
  let [sx,ry,rx,sy,tx,ty] = this.transformData;
  const newTX = sx * x + rx * y;
  const newTY = ry * x + sy * y;
  this.transformData = [sx,ry,rx,sy,newTX,newTY];
};

Transform.prototype.rotate = function(angle) {
  let c = Math.cos(angle);
  let s = Math.sin(angle);
  let [sx,ry,rx,sy,tx,ty] = this.transformData;
  let newSX = sx * c + rx * s;
  let newRY = ry * c + sy * s;
  let newRX = sx * -s + rx * c;
  let newSY = ry * -s + sy * c;
  this.transformData = [newSX,newRY,newRX,newSY,tx,ty];
};

Transform.prototype.scale = function(x, y) {
  let [sx,ry,rx,sy,tx,ty] = this.transformData;
  let newSX = sx * x;
  let newRY = ry * x;
  let newRX = rx * y;
  let newSY = sy * y;
  this.transformData = [newSX,newRY,newRX,newSY,tx,ty];
};

Transform.prototype.getCoordinate = function(x, y) {
  let [sx,ry,rx,sy,tx,ty] = this.transformData;
  const px = x * sx + y*rx + tx;
  const py = x * ry + y*sy + ty;
  return [px,py];
};

reference material

Tags: Javascript canvas

Posted by JankaZ on Fri, 13 May 2022 16:33:57 +0300