Collision Detect with Polygon & Rect
The blue polygon can be moved and transformed by using the following keys below. Red shapes are can be solid and cannot be passed. Yellow shapes are opaque.
- ArrowKeys - Moves the polygon
- Q - Rotates the polygon
- R - Increases the polygon size
- F - Decreases the polygon size
- C - Resets the polygon
Creating the PolygonObject
constructor(options={}) {
options.isMovable = true;
options.movementRate = 0.25,
super(options);
this._shape = new hamonengine.geometry.polygon();
this._shape.addVertex(0, 0);
this._shape.addVertex(75, 0);
this._shape.addVertex(100, 75/2);
this._shape.addVertex(75, 75);
this._shape.addVertex(0, 75);
this._polygonRotation = 0;
this._polygonScale = 1.0;
this._rotateHold = 0;
this._scaleDirection = 0;
this._scaleHoldDown = 0;
this._transformedShape = this._shape;
}
Creating the Polygons
constructor(options={}) {
super(options);
//Our main, movable shape.
this._object = new hamonengine.demos.actors.polygonObject();
//Create the shape and add the vertices.
this._shape3 = new hamonengine.geometry.polygon();
this._shape3.addVertex(0, 0);
this._shape3.addVertex(75, 75);
this._shape3.addVertex(0, 75);
//Create the shape and add the vertices.
this._shape2Position = new hamonengine.math.vector2(160, 150);
this._shape2 = this._shape3.translate(this._shape2Position);
this._rectPosition = new hamonengine.math.vector2(400, 100);
this._rect = new hamonengine.geometry.rect(400, 100, 100, 100);
}
Rendering the Polygons
renderBasics1(screen, elapsedTimeInMilliseconds) {
screen.beginPainting();
screen.drawPolygon(this._shape2, 0, 0, {lineWidth: 1, color: 'red'});
screen.drawPolygon(this._shape3, 300, 25, {lineWidth: 1, color: 'yellow', fill: true, fillColor: 'yellow'});
screen.drawRect(this._rect, 0, 0, {lineWidth: 1, color: 'red'});
this._object.process(screen, elapsedTimeInMilliseconds, [
{
shape: this._rect,
position: this._rectPosition
},
{
shape: this._shape2,
position: this._shape2Position
}
]);
//Render the polygon at the specific position that has a line width of 3px and the color is blue with no normals drawn.
//The final parameter determines if normals are drawn.
this._object.render(screen, elapsedTimeInMilliseconds);
screen.endPainting();
}
Collision Detection Logic
process(screen, elapsedTimeInMilliseconds, otherShapes) {
//Handle rotation & scale.
this._polygonRotation = ((this._polygonRotation + (this._rotateHold * elapsedTimeInMilliseconds / 1000 * Math.PI / 4)) % Math.PI2);
this._polygonScale = (this._polygonScale + (this._scaleDirection * elapsedTimeInMilliseconds / 1000 * 0.10));
//Precalculate the movement vector and update it with any collision information.
let movementVector = this.calcMove(elapsedTimeInMilliseconds);
//Perform the actual rotation & scaling and cache it for rendering.
this._transformedShape = this._shape.scale(new hamonengine.math.vector2(this._polygonScale, this._polygonScale))
.rotateAtCenter(this._polygonRotation)
.translate(this.position.add(movementVector));
//Handle collisions detection with otherShapes.
let hasCollisions = false;
let collisionCount = 0;
do {
//Make note if we have a collision.
hasCollisions = false;
for (let i = 0; i < otherShapes.length; i++) {
//Determine if this shape has collided with another.
const mtv = this._transformedShape.isCollision(otherShapes[i].shape);
if (mtv.length > 0) {
//Determine the position of the two shapes and correct the direction of the MTV based on the position of the two shapes.
let distance = otherShapes[i].position.subtract(this.position);
if (mtv.dot(distance) >= 0) {
mtv = mtv.invert();
}
//Adjust the movement vector and shape.
movementVector = movementVector.add(mtv);
this._transformedShape = this._transformedShape.translate(mtv);
hasCollisions = true;
}
}
//If a collision has occurred then we need to recalculate the collision detection again between the shapes.
//The MTV generated by one object may force one object to clip into another one, so another round of collision detection is needed.
} while (hasCollisions && collisionCount++ <= hamonengine.core.collisionDetection.limit);
this.move(elapsedTimeInMilliseconds, movementVector);
}