引子

在 Collision Detection :Triangle 中对三角形的碰撞检测从另外一种思路进行思考,到目前为止介绍的都是动态的检测,接着来看一下动静的碰撞检测。

以下示例未做兼容性查看,倡议在最新的 Chrome 浏览器中查看。

  • Origin
  • My GitHub

Transformation

这是示例页面。

基于 canvas 的 translate、 rotate、 scale 三种转换造成的动画,看看如何进行动静的碰撞检测。

基于 canvas 的动画原理是每隔一段时间进行重绘,所以在检测的时候,实际上是在特定的时刻,进行动态的碰撞检测,所以之前介绍的办法同样实用,这里对立应用 Polygon/Polygon 中的办法。 检测办法有了,接着就是获取在屏幕中相干点动态变化的坐标。上面分状况进行阐明。

translate

在 canvas 上进行绘制时,都是基于坐标系进行定位,画布左上角为坐标系原点,程度向右为 X 轴正方向,垂直向下为 Y 轴正方向。绘制一个矩形 rect(20, 20, 40, 40) ,在坐标系上是这样的:

如果想要程度向右挪动 60 像素,垂直向下挪动 80 像素,能够间接进行坐标相加:rect(20 + 60, 20 + 80, 40, 40)

但还有另外一种更乏味的形式:挪动整个坐标轴。如果把整个坐标轴程度向右挪动 60 像素,垂直向下挪动 80 像素,在视觉上是齐全一样的。 translate 办法就是应用这种形式。

从上图能够发现,这种形式不必思考矩形的坐标变动,在解决比较复杂的图形时,会不便很多。

须要留神的是,在进行了 translate 后,须要重置坐标轴,因为可能还有其它图形存在,而且还是以原来的坐标轴作为参考。重置坐标轴应用 setTransform 办法:

var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");ctx.translate(50, 50);ctx.fillRect(0,0,100,100);// 重置ctx.setTransform(1, 0, 0, 1, 0, 0);// 其它解决

对于变动后的坐标,间接对平移的像素进行加减。

/** * 假如点 A(x,y),通过 translate(x1,y1) 后达到 B(m,n) */ const m = x + x1; const n = y + y1;

rotate

rotate 办法与 translate 办法相似,通过旋转坐标轴实现。

对于变动后的坐标,须要进行一些计算。

/** * * 圆心坐标 O(0,0),假如点 A(x,y) ,与 X 轴造成的角度为  * 顺时针旋转角度  后达到点 B(m,n),上面来推导一下 B 点坐标 * * A 到圆心的间隔: dist1 = |OA| = y/sin()=x/cos() * B 到圆心的间隔: dist2 = |OB| = n/sin(-)=m/cos(-) * * 只是旋转 所以 dist1 = dist2,建设旋转的半径为 r : * r = y/sin()=x/cos()=n/sin(-)=m/cons(-) * y = r * sin()  x = r * cos() * * 依据三角函数公式: * sin(+)=sin()cos()+cos()sin() * sin(-)=sin()cos()-cos()sin() * cos(+)=cos()cos()-sin()sin() * cos(-)=cos()cos()+sin()sin() * * 代入上面公式: * 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() * * 逆时针则相同: * m =  x * cos() - y * sin() * n =  y * cos() + x * sin() * */

scale

scale 办法 translate 办法相似,通过缩放坐标轴实现。

对于变动后的坐标,间接乘以对应缩放的倍数。

/** * 假如点 A(x,y),通过 scale(num1,num2) 后达到 B(m,n) */const m = x * num1;const n = y * num2;

Transformation Order

当间断进行屡次不同变换时,程序不同,后果可能会不一样。这是示例。

这是因为间断进行变换时,都是基于上一次变换后的状态,再次进行变换。在进行计算的时候,须要多方面思考。基于 transform 中的参数格局,进行计算会比拟不便一些,translaterotatescale 的成果都能够转换为 transform 的模式。

/** * canvas.transform(sx, ry, rx, sy, tx, ty) * sx-程度缩放,ry-垂直歪斜,rx-程度歪斜,sy-垂直缩放,tx-程度挪动,ty-垂直挪动 * */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];};

参考资料

  • DEALING WITH MATRIX TRANS­FORMATIONS
  • 2D Transformations
  • Understanding HTML 5 canvas scale and translate order