constructor(options={}) {
super(options);
...
this._rect = new hamonengine.geometry.rect(0, 0, 75, 75);
this._rect2 = new hamonengine.geometry.rect(0, 0, 150, 100);
...
}
renderBasics1(screen, elapsedTimeInMilliseconds) {
screen.beginPainting();
//Render the rect at the specific position that has a line width of 3px and the color is blue.
//The final parameter determines if normals are drawn.
screen.drawRect(this._rect, 50, 50, { lineWidth: 3, color: 'blue' });
//Render the rect at the specific position that has a line width of 3px and the color is red.
screen.drawRect(this._rect2, 75, 100, { lineWidth: 3, color: 'red' });
//Render the rect at the specific position that has a line width of 3px and the color is yellow.
screen.drawRect(this._rect, 150, 150, { lineWidth: 3, color: 'yellow' });
screen.endPainting();
}
constructor(options={}) {
super(options);
...
this._rect = new hamonengine.geometry.rect(0, 0, 75, 75);
...
}
renderWrapping(screen, elapsedTimeInMilliseconds) {
screen.beginPainting();
//Begin wrapping
screen.wrapVertical = screen.wrapHorizontal = true;
//Draw beyond the left edge of the screen.
screen.drawRect(this._rect, screen.viewPort.x - this._rect.width/2, 25, { lineWidth: 3, color: 'blue', drawNormals: true });
//Draw beyond the right edge of the screen.
screen.drawRect(this._rect, screen.viewPort.width - this._rect.width/2, 200, { lineWidth: 3, color: 'green', drawNormals: true });
//Draw beyond the top edge of the screen.
screen.drawRect(this._rect, 150, screen.viewPort.y - this._rect.height/2, { lineWidth: 3, color: 'red', drawNormals: true });
//Draw beyond the bottom edge of the screen.
screen.drawRect(this._rect, 350, screen.viewPort.height - this._rect.height/2, { lineWidth: 3, color: 'orange', drawNormals: true });
screen.wrapVertical = screen.wrapHorizontal = false;
screen.endPainting();
}
constructor(options={}) {
super(options);
...
this._rect = new hamonengine.geometry.rect(0, 0, 75, 75);
...
}
renderTransformToPolygon(screen, elapsedTimeInMilliseconds) {
screen.beginPainting();
//Draw the rect as a polygon.
let newPolygon = this._rect.toPolygon();
screen.drawPolygon(newPolygon, 50, 50, { lineWidth: 3, color: 'blue' });
//Rotate the red polygon 90 degrees.
let theta = Math.PI / 4;
let rotatedShape = newPolygon.rotateAtCenter(theta);
screen.drawPolygon(rotatedShape, 200, 50, { lineWidth: 3, color: 'red' });
//Translate the yellow polygon down and to the right by 25 pixels
let translatedShape = newPolygon.translate(new hamonengine.math.vector2(25, 25));
screen.drawPolygon(translatedShape, 350, 50, { lineWidth: 3, color: 'yellow' });
//Shrink the green polygon by half.
let scaledShape = newPolygon.scale(new hamonengine.math.vector2(0.5, 0.5));
screen.drawPolygon(scaledShape, 50, 200, { lineWidth: 3, color: 'green' });
screen.endPainting();
}
Collision Detection Logic
The blue rect can be moved by using the following keys below. Red shapes are can be solid and cannot be passed. Yellow shapes are opaque.
- ArrowKeys - Moves the rect
- C - Resets the rect
constructor(options={}) {
super(options);
//Our main, movable shape.
this._object = new hamonengine.demos.actors.rectObject({ x: 0, y: 0, width: 75, height: 75 });
this._rect = new hamonengine.geometry.rect(0, 0, 75, 75);
this._rect2 = new hamonengine.geometry.rect(0, 0, 150, 100);
this._rect3Position = new hamonengine.math.vector2(100, 160);
this._rect3 = new hamonengine.geometry.rect(this._rect3Position.x, this._rect3Position.y, 150, 100);
...
//Create the shape and add the vertices.
this._shape1 = new hamonengine.geometry.polygon();
this._shape1.addVertex(0, 0);
this._shape1.addVertex(75, 75);
this._shape1.addVertex(0, 75);
this._shape2Position = new hamonengine.math.vector2(400, 100);
this._shape2 = new hamonengine.geometry.polygon();
this._shape2.addVertex(0, 0);
this._shape2.addVertex(75, 0);
this._shape2.addVertex(100, 75 / 2);
this._shape2.addVertex(75, 75);
this._shape2.addVertex(0, 75);
this._shape2 = this._shape2.translate(this._shape2Position);
...
}
process(elapsedTimeInMilliseconds, otherShapes) {
//Precalculate the movement vector and update it with any collision information.
let movementVector = this.calcMove(elapsedTimeInMilliseconds);
//Set the initial position of the shape based on this object's position.
this._transformedRect = this.shape.translate(this.position);
//Handle collisions detection with otherShapes.
for(let i = 0; i < otherShapes.length; i++) {
//Determine if this shape has collided with another.
const mtv = this._transformedRect.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._transformedRect = this._transformedRect.translate(mtv);
}
}
//Move the object.
this.move(elapsedTimeInMilliseconds, movementVector);
}
renderCollisionDetection(screen, elapsedTimeInMilliseconds) {
screen.beginPainting();
screen.drawPolygon(this._shape1, 300, 25, { lineWidth: 1, color: 'yellow' });
screen.drawRect(this._rect2, 25, 25, { lineWidth: 1, color: 'yellow' });
screen.drawPolygon(this._shape2, 0, 0, { lineWidth: 3, color: 'red' });
screen.drawRect(this._rect3, 0, 0, { lineWidth: 3, color: 'red' });
this._object.process(elapsedTimeInMilliseconds, [
{
shape: this._shape2,
position: this._shape2Position
},
{
shape: this._rect3,
position: this._rect3Position
}
]);
//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 (Point Containment Detection Logic)
Drag and drop the blue rect inside the green rect.
constructor(options={}) {
super(options);
this._rect3Position = new hamonengine.math.vector2(100, 160);
this._rect3 = new hamonengine.geometry.rect(this._rect3Position.x, this._rect3Position.y, 150, 100);
...
this._object3 = new hamonengine.demos.actors.rectObject({ x: this._rect3Position.x, y: this._rect3Position.y, width: 50, height: 50 });
...
this._beginContainmentSample = false;
this._mouseCaptured = false;
this._cursorPosition = new hamonengine.math.vector2();
}
process(elapsedTimeInMilliseconds, otherShapes) {
//Precalculate the movement vector and update it with any collision information.
let movementVector = this.calcMove(elapsedTimeInMilliseconds);
//Set the initial position of the shape based on this object's position.
this._transformedRect = this.shape.translate(this.position);
//Handle collisions detection with otherShapes.
for(let i = 0; i < otherShapes.length; i++) {
//Determine if this shape has collided with another.
const mtv = this._transformedRect.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._transformedRect = this._transformedRect.translate(mtv);
}
}
//Move the object.
this.move(elapsedTimeInMilliseconds, movementVector);
}
renderPointCollisionDetection(screen, elapsedTimeInMilliseconds) {
screen.beginPainting();
screen.drawRect(this._rect3, 0, 0, { lineWidth: 3, color: 'green' });
if (!this._mouseCaptured) {
this._object3.process(elapsedTimeInMilliseconds, [{
shape: this._rect3,
position: this._rect3Position
}]);
}
else {
this._object3.process(elapsedTimeInMilliseconds);
}
//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._object3.render(screen, elapsedTimeInMilliseconds, this._mouseCaptured);
screen.endPainting();
}
onMouseEvent(type, v, e, caller) {
if (caller === this.getScreen('canvas-pointcollision')) {
//Determine if the mouse button is being held down.
if (type === 'down') {
//Determine if the cursor is within the object.
const mtv = this._object3.transformedRect.isCollision(v);
if (mtv.length > 0) {
//If so, record mouse as being captured.
this._mouseCaptured = true;
//Calculate the position of the cursor within the object.
let distance = this._object3.position.subtract(v);
this._object3.mtv = mtv;
}
}
//Determine if the mouse button is no longer being held.
else if (type === 'up') {
this._mouseCaptured = false;
}
//Determine if the mouse is being moved and is captured.
else if (type === 'move') {
if (this._mouseCaptured) {
this._object3.position.x = v.x - this._object3.mtv.x;
this._object3.position.y = v.y - this._object3.mtv.y;
}
//Determine if the cursor is within the object.
const isHovering = this._object3.transformedRect.isCollision(v).length > 0;
caller.cursor = isHovering ? (this._mouseCaptured ? 'grabbing' : 'grab') : 'auto';
caller.tooltip = isHovering ? 'Drag the rect' : '';
}
}
}