Polygon Chain Basics

Rendering

Canvas tag not supported
constructor(options={}) {
    super(options);
    ...
    this.polyChain1 = new hamonengine.geometry.polyChain();
    this.polyChain1.addVertex(0, 0);
    this.polyChain1.addVertex(50, 50);
    this.polyChain1.addVertex(0, 50);

    this.lineSegment1 = new hamonengine.geometry.lineSegment(0, 0, 50, 50);
    this.lineSegment2 = new hamonengine.geometry.lineSegment(50, 50, 0, 50);

    this.polyChain2 = new hamonengine.geometry.polyChain();
    this.polyChain2.addLine(this.lineSegment1);
    this.polyChain2.addLine(this.lineSegment2);

    this.polyChain3 = new hamonengine.geometry.polyChain();
    this.polyChain3.addLine(new hamonengine.geometry.lineSegment(0, 0, 50, 50));
    this.polyChain3.addLine(new hamonengine.geometry.lineSegment(50, 50, 0, 50));
    this.polyChain3.addLine(new hamonengine.geometry.lineSegment(50, 100, 25, 150));
    ...
}
renderBasics1(screen, elapsedTimeInMilliseconds) {
    screen.beginPainting();

    screen.drawShape(this.polyChain1, 100, 100, { color: 'red', drawNormals: true, lineWidth: 2 });
    screen.drawText('polyChain1', 100, 180);

    screen.drawShape(this.lineSegment1, 200, 100, { color: 'green', drawNormals: true, lineWidth: 2 });
    screen.drawText('lineSegment1', 200, 180);

    screen.drawShape(this.lineSegment2, 200, 160, { color: 'green', drawNormals: true, lineWidth: 2 });
    screen.drawText('lineSegment2', 200, 250);

    screen.drawShape(this.polyChain2, 300, 100, { color: 'red', drawNormals: true, lineWidth: 2 });
    screen.drawText('polyChain2', 300, 180);

    screen.drawShape(this.polyChain3, 400, 100, { color: 'red', drawNormals: true, lineWidth: 2 });
    screen.drawText('polyChain3', 400, 260);

    screen.endPainting();
}
                            

Transforming into to a Polygon

Canvas tag not supported
constructor(options={}) {
    super(options);
    ...
    this.polyChain1 = new hamonengine.geometry.polyChain();
    this.polyChain1.addVertex(0, 0);
    this.polyChain1.addVertex(50, 50);
    this.polyChain1.addVertex(0, 50);
    ...
}
renderTransformIntoPolygon(screen, elapsedTimeInMilliseconds) {
    screen.beginPainting();

    screen.drawShape(this.polyChain1, 100, 100, { color: 'red', drawNormals: true, lineWidth: 2 });
    screen.drawText('polyChain1', 100, 180);

    screen.drawShape(this.polyChain1.toPolygon(), 200, 100, { color: 'red', drawNormals: true, lineWidth: 2 });
    screen.drawText('polygon', 200, 180);

    screen.endPainting();
}
                            

Rotating a PolyChain

Canvas tag not supported
constructor(options={}) {
    super(options);
    ...
    this.polyChain3 = new hamonengine.geometry.polyChain();
    this.polyChain3.addLine(new hamonengine.geometry.lineSegment(0, 0, 50, 50));
    this.polyChain3.addLine(new hamonengine.geometry.lineSegment(50, 50, 0, 50));
    this.polyChain3.addLine(new hamonengine.geometry.lineSegment(50, 100, 25, 150));
    ...
}
renderRotatingPolychain(screen, elapsedTimeInMilliseconds) {
    screen.beginPainting();

    screen.drawShape(this.polyChain3, 50, 50, { color: 'red', drawNormals: true, lineWidth: 2 });
    screen.drawText('red polychain3', 25, 210);
    
    screen.drawShape(this.polyChain3.rotate(Math.PI/2), 350, 50, { color: 'yellow', drawNormals: true, lineWidth: 2 });
    screen.drawText('yellow rotated 90 degrees', 200, 120);

    screen.drawShape(this.polyChain3.rotate(Math.PI/4), 550, 50, { color: 'green', drawNormals: true, lineWidth: 2 });
    screen.drawText('green rotated 45 degrees', 450, 200);

    screen.endPainting();
}
                            

Scaling a PolyChain

Canvas tag not supported
constructor(options={}) {
    super(options);
    ...
    this.polyChain3 = new hamonengine.geometry.polyChain();
    this.polyChain3.addLine(new hamonengine.geometry.lineSegment(0, 0, 50, 50));
    this.polyChain3.addLine(new hamonengine.geometry.lineSegment(50, 50, 0, 50));
    this.polyChain3.addLine(new hamonengine.geometry.lineSegment(50, 100, 25, 150));
    ...
}
renderScalingPolychain(screen, elapsedTimeInMilliseconds) {
    screen.beginPainting();

    //Shrink the green polygon by half.
    screen.drawShape(this.polyChain3, 50, 50, { color: 'red', drawNormals: true, lineWidth: 2 });
    screen.drawText('red polychain3', 50, 110);
    
    screen.drawShape(this.polyChain3.scale(new hamonengine.math.vector2(0.5, 0.5)), 50, 180, { color: 'yellow', drawNormals: true, lineWidth: 2 });
    screen.drawText('yellow scaled down (0.5, 0.5)', 50, 210);

    screen.drawShape(this.polyChain3, 250, 50, { color: 'red', drawNormals: true, lineWidth: 2 });
    screen.drawText('red polychain3', 250, 110);
    
    screen.drawShape(this.polyChain3.scale(new hamonengine.math.vector2(1.5, 1.5)), 250, 160, { color: 'yellow', drawNormals: true, lineWidth: 2 });
    screen.drawText('yellow scaled up (1.5, 1.5)', 250, 250);

    screen.endPainting();
}
                            

Collision Detection Logic

The shape can be moved by using the arrow keys below. Each line segment is collidable and will reject the shape in the direction of the normal.

  • ArrowKeys - Moves the shape.
  • C - Resets the shape's location.
  • D - Toggles the shape between polygon and rect.

Canvas tag not supported
constructor(options={}) {
    super(options);
    ...
    this.rect = new hamonengine.geometry.rect(0, 0,50, 50);

    this.polygon = new hamonengine.geometry.polygon();
    this.polygon.addLine(this.lineSegment1);
    this.polygon.addVertex(0, 50);

    this._polygonObject = new hamonengine.entities.shapeObject({
        shape: this.polygon,
        position: new hamonengine.math.vector2(250, 100),
        isMovable: false
    });

    this._lineSegmentObjectActor = new hamonengine.entities.shapeObject({
        //The movement rate is the number of pixels * the number of seconds that have elapsed between frames.
        movementRate: 0.15,
        width: this.lineSegment1.length,
        height: this.lineSegment1.length,
        shape: this.polygon,
        position: new hamonengine.math.vector2(80, 120),
        direction: new hamonengine.math.vector2(0, 0),
        isMovable: true,
        isSolid: true,
        faceAxisOnMove: OBJECT_FACE_DIRECTION.NONE
    });

    const lineSegmentObject = new hamonengine.entities.shapeObject({
        shape: new hamonengine.geometry.lineSegment(0, 80, 0, 0),
        position: new hamonengine.math.vector2(200, 120),
        isMovable: false,
        isSolid: true
    });

    const lineSegmentObject2 = new hamonengine.entities.shapeObject({
        shape: new hamonengine.geometry.lineSegment(0, 0, 0, 80),
        position: new hamonengine.math.vector2(400, 120),
        isMovable: false,
        isSolid: true
    });

    const lineSegmentObject3 = new hamonengine.entities.shapeObject({
        shape: new hamonengine.geometry.lineSegment(0, 0, 50, 80),
        position: new hamonengine.math.vector2(600, 120),
        isMovable: false,
        isSolid: true
    });

    this.objects = [];
    this.objects.push(lineSegmentObject);
    this.objects.push(lineSegmentObject2);
    this.objects.push(lineSegmentObject3);
    ...
}   
renderCollisionDetection(screen, elapsedTimeInMilliseconds) {
    screen.beginPainting();

    this.objects.forEach(object => object && object.render && object.render(screen, elapsedTimeInMilliseconds, { color: 'red', drawNormals: true }));

    //Move the shape and if there is a collision then correct the movement.
    //This prevents bouncing.
    this.lineObjectActor.move(elapsedTimeInMilliseconds);

    //Handle collisions detection with otherShapes.
    let correctionMTV = new hamonengine.math.vector2();
    for (let i = 0; i < this.objects.length; i++) {
        //Determine if this shape has collided with another.
        let mtv = this.lineObjectActor.isCollision(this.objects[i]);
        if (mtv.length > 0) {
            //Adjust the position of the moving object.
            correctionMTV = correctionMTV.add(mtv);
        }
    }

    //Move the object if any corrections were made due to collisions.
    this.lineObjectActor.move(elapsedTimeInMilliseconds, correctionMTV);
    this.lineObjectActor.render(screen, elapsedTimeInMilliseconds, { color: 'red', drawNormals: true, lineWidth: '1px' });

    screen.endPainting();
}