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' : ''; } } }