var Shape = function () {
this.x = undefined;
this.y = undefined;
this.strokeStyle = 'rgba(255, 253, 208, 0.9)';
this.fillStyle = 'rgba(147, 197, 114, 0.8)';
};
Shape.prototype = {
/*该方法在每个shape对象上调用getAxes方法,然后将获取
* 到的投影轴传递给separationOnAxes方法,后者将两个受测对象分别投射到每个投影轴上,
* 只要在某个投影轴上发现了相互分离的投影,就返回true*/
collidesWith: function (shape) {
var axes = this.getAxes().concat(shape.getAxes());
return !this.separationOnAxes(axes, shape);
},
separationOnAxes: function (axes, shape) {
for (var i=0; i < axes.length; ++i) {
axis = axes[i];
projection1 = shape.project(axis);/*获取shape在某个轴上的投影*/
projection2 = this.project(axis);/*获取this在这个轴上的投影*/
/*比较两个投影在这个轴上最大值和最小值是否重叠*/
if (! projection1.overlaps(projection2)) {
return true; // don't have to test remaining axes
}
}
return false;
},
move: function (dx, dy) {
throw 'move(dx, dy) not implemented';
},
createPath: function (context) {
throw 'createPath(context) not implemented';
},
getAxes: function () {
throw 'getAxes() not implemented';
},
project: function (axis) {
throw 'project(axis) not implemented';
},
fill: function (context) {
context.save();
context.fillStyle = this.fillStyle;
this.createPath(context);
context.fill();
context.restore();
},
stroke: function (context) {
context.save();
context.strokeStyle = this.strokeStyle;
this.createPath(context);
context.stroke();
context.restore();
},
isPointInPath: function (context, x, y) {
this.createPath(context);
return context.isPointInPath(x, y);
},
};
var Projection = function (min, max) {
this.min = min;
this.max = max;
};
Projection.prototype = {
overlaps: function (projection) {
return this.max > projection.min && projection.max > this.min;
}
};
----------------------------------------------------------------------------------------
/*多边形*/
var Polygon = function () {
this.points = [];
this.strokeStyle = 'blue';
this.fillStyle = 'white';
};
Polygon.prototype = new Shape();
/*获取多边形每个边的单位法向量*/
Polygon.prototype.getAxes = function () {
var v1 = new Vector(),
v2 = new Vector(),
axes = [];
for (var i=0; i < this.points.length-1; i++) {
v1.x = this.points[i].x;
v1.y = this.points[i].y;
v2.x = this.points[i+1].x;
v2.y = this.points[i+1].y;
axes.push(v1.edge(v2).normal());
}
v1.x = this.points[this.points.length-1].x;
v1.y = this.points[this.points.length-1].y;
v2.x = this.points[0].x;
v2.y = this.points[0].y;
axes.push(v1.edge(v2).normal());
return axes;
};
/*返回该多边形在某条轴上的投影
* 参数axis是某个边缘法向量*/Polygon.prototype.project = function (axis) {
var scalars = [],
v = new Vector();
this.points.forEach( function (point) {
v.x = point.x;
v.y = point.y;
scalars.push(v.dotProduct(axis));
/*两向量积相乘点积 等同于|a||b|cos@
* axis是某一个单位法向量长度为1,所以|a||b|cos@ = |b|cos@ 就是v在axis上的投影
* 将多边形的每个顶点和这条单位法向量投影得到的最大值和最小值之差就是这个投影的长度*/
/*dotProduct方法*/
/* dotProduct: function (vector) {
return this.x * vector.x +
this.y * vector.y;
},*/
});
return new Projection(Math.min.apply(Math, scalars),
Math.max.apply(Math, scalars));
};
Polygon.prototype.addPoint = function (x, y) {
this.points.push(new Point(x,y));
};
Polygon.prototype.createPath = function (context) {
if (this.points.length === 0)
return;
context.beginPath();
context.moveTo(this.points[0].x,
this.points[0].y);
for (var i=0; i < this.points.length; ++i) {
context.lineTo(this.points[i].x,
this.points[i].y);
}
context.closePath();
};
Polygon.prototype.move = function (dx, dy) {
var point, x;
for(var i=0; i < this.points.length; ++i) {
point = this.points[i];
point.x += dx;
point.y += dy;
}
};
Polygon.prototype.move = function (dx, dy) {
for (var i=0, point; i < this.points.length; ++i) {
point = this.points[i];
point.x += dx;
point.y += dy;
}
};