Rect Basics

Rendering

Canvas tag not supported
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();
}
                            

Wrapping

Canvas tag not supported
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();
}
                        

Transforming Into a Polygon

Canvas tag not supported
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

Canvas tag not supported
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.

Canvas tag not supported
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' : '';
        }
    }
}