From f10c772ff3b074be302bf15288d6fc5119119e8e Mon Sep 17 00:00:00 2001 From: jdowell Date: Fri, 2 May 2014 12:30:49 -0500 Subject: [PATCH] Graphics.drawTriangles && Polygon.area Demo: http://phaser-triangles.herokuapp.com --- src/gameobjects/Graphics.js | 86 +++++++++++++++++++++++++++++++++++++ src/geom/Polygon.js | 77 ++++++++++++++++++++++++++++++++- 2 files changed, 161 insertions(+), 2 deletions(-) diff --git a/src/gameobjects/Graphics.js b/src/gameobjects/Graphics.js index 30bd2307e..33d7b8ab8 100644 --- a/src/gameobjects/Graphics.js +++ b/src/gameobjects/Graphics.js @@ -212,6 +212,92 @@ Phaser.Graphics.prototype.drawPolygon = function (poly) { }; +/* +* Draws a single {Phaser.Polygon} triangle from a {Phaser.Point} array +* +* @param {Array} points - An array of Phaser.Points that make up the three vertices of this triangle +* @param {boolean} [cull=false] - Should we check if the triangle is back-facing +* @method Phaser.Graphics.prototype.drawTriangle +*/ + +Phaser.Graphics.prototype.drawTriangle = function(points, cull) { + var triangle = new Phaser.Polygon(points); + if (cull) { + var cameraToFace = new Phaser.Point(this.game.camera.x - points[0].x, this.game.camera.y - points[0].y); + var ab = new Phaser.Point(points[1].x - points[0].x, points[1].y - points[0].y); + var cb = new Phaser.Point(points[1].x - points[2].x, points[1].y - points[2].y); + var faceNormal = cb.cross(ab); + if (cameraToFace.dot(faceNormal) > 0) { + this.drawPolygon(triangle); + } + } else { + this.drawPolygon(triangle); + } + return; +}; + +/* +* Draws {Phaser.Polygon} triangles +* +* @param {Array|Array} vertices - An array of Phaser.Points or numbers that make up the vertices of the triangles +* @param {Array} {indices=null} - An array of numbers that describe what order to draw the vertices in +* @param {boolean} [cull=false] - Should we check if the triangle is back-facing +* @method Phaser.Graphics.prototype.drawTriangles +*/ + +Phaser.Graphics.prototype.drawTriangles = function(vertices, indices, cull) { + + var point1 = new Phaser.Point(), + point2 = new Phaser.Point(), + point3 = new Phaser.Point(), + points = [], + i; + + if (!indices) { + if(vertices[0] instanceof Phaser.Point) { + for(i = 0; i < vertices.length / 3; i++) { + this.drawTriangle([vertices[i * 3], vertices[i * 3 + 1], vertices[i * 3 + 2]], cull); + } + } else { + for (i = 0; i < vertices.length / 6; i++) { + point1.x = vertices[i * 6 + 0]; + point1.y = vertices[i * 6 + 1]; + point2.x = vertices[i * 6 + 2]; + point2.y = vertices[i * 6 + 3]; + point3.x = vertices[i * 6 + 4]; + point3.y = vertices[i * 6 + 5]; + this.drawTriangle([point1, point2, point3], cull); + } + + } + } else { + if(vertices[0] instanceof Phaser.Point) { + for(i = 0; i < indices.length /3; i++) { + points.push(vertices[indices[i * 3 ]]); + points.push(vertices[indices[i * 3 + 1]]); + points.push(vertices[indices[i * 3 + 2]]); + if(points.length === 3) { + this.drawTriangle(points, cull); + points = []; + } + + } + } else { + for (i = 0; i < indices.length; i++) { + point1.x = vertices[indices[i] * 2]; + point1.y = vertices[indices[i] * 2 + 1]; + points.push(point1.copyTo({})); + if (points.length === 3) { + this.drawTriangle(points, cull); + points = []; + } + } + } + } +}; + + + /** * Indicates the rotation of the Graphics, in degrees, from its original orientation. Values from 0 to 180 represent clockwise rotation; values from 0 to -180 represent counterclockwise rotation. * Values outside this range are added to or subtracted from 360 to obtain a value within the range. For example, the statement player.angle = 450 is the same as player.angle = 90. diff --git a/src/geom/Polygon.js b/src/geom/Polygon.js index a47bada65..5d7de3bfc 100644 --- a/src/geom/Polygon.js +++ b/src/geom/Polygon.js @@ -43,9 +43,10 @@ Phaser.Polygon = function (points) { } /** - * @property {array|array} points - The array of Points. + * @property {array|array} points - The array of vertex Points. + * @private */ - this.points = points; + this._points = points; }; @@ -106,5 +107,77 @@ Phaser.Polygon.prototype = { Phaser.Polygon.prototype.constructor = Phaser.Polygon; +/* + * Sets and modifys the points of this polygon. + * + * @name Phaser.Graphics#fixedToCamera + * @property {array|array} points - The array of vertex points + */ + +Object.defineProperty(Phaser.Polygon.prototype, 'points', { + get: function() { + return this._points; + }, + set: function(points) { + //if points isn't an array, use arguments as the array + if (!(points instanceof Array)) + { + points = Array.prototype.slice.call(arguments); + } + + //if this is a flat array of numbers, convert it to points + if (typeof points[0] === 'number') + { + var p = []; + + for (var i = 0, len = points.length; i < len; i += 2) + { + p.push(new Phaser.Point(points[i], points[i + 1])); + } + + points = p; + } + this._points = points; + } +}); + +/** +* Returns the area of the polygon. +* +* @name Phaser.Polygon#area +* @readonly +*/ + +Object.defineProperty(Phaser.Polygon.prototype, 'area', { + get: function() { + var p1, p2, avgHeight, width, i, + y0 = Number.MAX_VALUE, + area = 0; + + // Find lowest boundary + for(i = 0; i< this.points.length; i++) { + if(this.points[i].y < y0) { + y0 = this.points[i].y; + } + } + + for(i = 0; i< this.points.length; i++) { + p1 = this.points[i]; + if(i === this.points.length - 1) { + p2 = this.points[0]; + } else { + p2 = this.points[i+1]; + } + + avgHeight = ((p1.y - y0) + (p2.y - y0)) / 2; + width = p1.x - p2.x; + area += avgHeight * width; + } + + return area; + } +}); // Because PIXI uses its own Polygon, we'll replace it with ours to avoid duplicating code or confusion. PIXI.Polygon = Phaser.Polygon; + +