mirror of
https://github.com/photonstorm/phaser
synced 2024-11-24 13:43:26 +00:00
Added getStartPoint and draw methods to all curves and paths.
This commit is contained in:
parent
6631985a3e
commit
8a4fff945c
6 changed files with 298 additions and 68 deletions
|
@ -2,18 +2,20 @@
|
|||
|
||||
var Class = require('../utils/Class');
|
||||
var LineCurve = require('./curves/line/LineCurve');
|
||||
var SplineCurve = require('./curves/spline/SplineCurve');
|
||||
var CubicBezierCurve = require('./curves/cubicbezier/CubicBezierCurve');
|
||||
var Vector2 = require('../math/Vector2');
|
||||
|
||||
// Local cache vars
|
||||
|
||||
var tmpVec2A = new Vector2();
|
||||
// var tmpVec2B = new Vector2();
|
||||
var tmpVec2B = new Vector2();
|
||||
|
||||
var Path = new Class({
|
||||
|
||||
initialize:
|
||||
|
||||
function Path ()
|
||||
function Path (x, y)
|
||||
{
|
||||
this.curves = [];
|
||||
|
||||
|
@ -21,29 +23,66 @@ var Path = new Class({
|
|||
|
||||
// Automatically closes the path
|
||||
this.autoClose = false;
|
||||
|
||||
this.startPoint = new Vector2(x, y);
|
||||
},
|
||||
|
||||
// If x2/y2 are not given then it creates a line between the previous curve end point (or 0x0) and x1,y1
|
||||
addLineCurve: function (x1, y1, x2, y2)
|
||||
// Creates a line curve from the previous end point to x/y
|
||||
lineTo: function (x, y)
|
||||
{
|
||||
if (x2 === undefined && y2 === undefined)
|
||||
if (x instanceof Vector2)
|
||||
{
|
||||
// Create a line from the previous end point to x1/y1
|
||||
x2 = x1;
|
||||
y2 = y1;
|
||||
|
||||
var end = this.getEndPoint(tmpVec2A);
|
||||
|
||||
this.curves.push(new LineCurve([ end.x, end.y, x2, y2 ]));
|
||||
tmpVec2B.copy(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.curves.push(new LineCurve([ x1, y1, x2, y2 ]));
|
||||
tmpVec2B.set(x, y);
|
||||
}
|
||||
|
||||
return this;
|
||||
var end = this.getEndPoint(tmpVec2A);
|
||||
|
||||
return this.add(new LineCurve([ end.x, end.y, tmpVec2B.x, tmpVec2B.y ]));
|
||||
},
|
||||
|
||||
// Creates a spline curve starting at the previous end point, using the given parameters
|
||||
splineTo: function (points)
|
||||
{
|
||||
points.shift(this.getEndPoint());
|
||||
|
||||
return this.add(new SplineCurve(points));
|
||||
},
|
||||
|
||||
// Creates a cubic bezier curve starting at the previous end point and ending at p3, using p1 and p2 as control points
|
||||
cubicBezierTo: function (x, y, control1X, control1Y, control2X, control2Y)
|
||||
{
|
||||
var p0 = this.getEndPoint();
|
||||
var p1;
|
||||
var p2;
|
||||
var p3;
|
||||
|
||||
// Assume they're all vec2s
|
||||
if (x instanceof Vector2)
|
||||
{
|
||||
p1 = x;
|
||||
p2 = y;
|
||||
p3 = control1X;
|
||||
}
|
||||
else
|
||||
{
|
||||
p1 = new Vector2(control1X, control1Y);
|
||||
p2 = new Vector2(control2X, control2Y);
|
||||
p3 = new Vector2(x, y);
|
||||
}
|
||||
|
||||
return this.add(new CubicBezierCurve(p0, p1, p2, p3));
|
||||
},
|
||||
|
||||
// Creates an ellipse curve positioned at the previous end point, using the given parameters
|
||||
// ellipseTo: function (xRadius, yRadius, startAngle, endAngle, clockwise, rotation)
|
||||
// {
|
||||
// function EllipseCurve (x, y, xRadius, yRadius, startAngle, endAngle, clockwise, rotation)
|
||||
// },
|
||||
|
||||
add: function (curve)
|
||||
{
|
||||
this.curves.push(curve);
|
||||
|
@ -61,7 +100,7 @@ var Path = new Class({
|
|||
}
|
||||
else
|
||||
{
|
||||
out.set(0, 0);
|
||||
out.copy(this.startPoint);
|
||||
}
|
||||
|
||||
return out;
|
||||
|
@ -227,6 +266,16 @@ var Path = new Class({
|
|||
}
|
||||
|
||||
return points;
|
||||
},
|
||||
|
||||
draw: function (graphics, pointsTotal)
|
||||
{
|
||||
for (var i = 0; i < this.curves.length; i++)
|
||||
{
|
||||
this.curves[i].draw(graphics, pointsTotal);
|
||||
}
|
||||
|
||||
return graphics;
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
// Based on the three.js Curve classes created by [zz85](http://www.lab4games.net/zz85/blog)
|
||||
|
||||
var Clamp = require('../../math/Clamp');
|
||||
var Vector2 = require('../../math/Vector2');
|
||||
var Vector3 = require('../../math/Vector3');
|
||||
var Matrix4 = require('../../math/Matrix4');
|
||||
var Class = require('../../utils/Class');
|
||||
var Vector2 = require('../../math/Vector2');
|
||||
|
||||
// Local cache vars
|
||||
|
||||
|
@ -237,6 +234,29 @@ var Curve = new Class({
|
|||
var t = this.getUtoTmapping(u);
|
||||
|
||||
return this.getTangent(t, out);
|
||||
},
|
||||
|
||||
draw: function (graphics, pointsTotal)
|
||||
{
|
||||
if (pointsTotal === undefined) { pointsTotal = 32; }
|
||||
|
||||
var start = this.getStartPoint();
|
||||
var points = this.getPoints(pointsTotal);
|
||||
|
||||
graphics.beginPath();
|
||||
|
||||
graphics.moveTo(start.x, start.y);
|
||||
|
||||
for (var i = 1; i < points.length; i++)
|
||||
{
|
||||
graphics.lineTo(points[i].x, points[i].y);
|
||||
}
|
||||
|
||||
graphics.strokePath();
|
||||
graphics.closePath();
|
||||
|
||||
// So you can chain graphics calls
|
||||
return graphics;
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -13,14 +13,27 @@ var CubicBezierCurve = new Class({
|
|||
|
||||
initialize:
|
||||
|
||||
function CubicBezierCurve (v0, v1, v2, v3)
|
||||
function CubicBezierCurve (p0, p1, p2, p3)
|
||||
{
|
||||
Curve.call(this);
|
||||
|
||||
this.v0 = v0;
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
this.v3 = v3;
|
||||
if (Array.isArray(p0))
|
||||
{
|
||||
p3 = new Vector2(p0[6], p0[7]);
|
||||
p2 = new Vector2(p0[4], p0[5]);
|
||||
p1 = new Vector2(p0[2], p0[3]);
|
||||
p0 = new Vector2(p0[0], p0[1]);
|
||||
}
|
||||
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.p3 = p3;
|
||||
},
|
||||
|
||||
getStartPoint: function ()
|
||||
{
|
||||
return this.p0;
|
||||
},
|
||||
|
||||
getResolution: function (divisions)
|
||||
|
@ -32,12 +45,33 @@ var CubicBezierCurve = new Class({
|
|||
{
|
||||
if (out === undefined) { out = new Vector2(); }
|
||||
|
||||
var v0 = this.v0;
|
||||
var v1 = this.v1;
|
||||
var v2 = this.v2;
|
||||
var v3 = this.v3;
|
||||
var p0 = this.p0;
|
||||
var p1 = this.p1;
|
||||
var p2 = this.p2;
|
||||
var p3 = this.p3;
|
||||
|
||||
return out.set(CubicBezier(t, v0.x, v1.x, v2.x, v3.x), CubicBezier(t, v0.y, v1.y, v2.y, v3.y));
|
||||
return out.set(CubicBezier(t, p0.x, p1.x, p2.x, p3.x), CubicBezier(t, p0.y, p1.y, p2.y, p3.y));
|
||||
},
|
||||
|
||||
draw: function (graphics, pointsTotal)
|
||||
{
|
||||
if (pointsTotal === undefined) { pointsTotal = 32; }
|
||||
|
||||
var points = this.getPoints(pointsTotal);
|
||||
|
||||
graphics.beginPath();
|
||||
graphics.moveTo(this.p0.x, this.p0.y);
|
||||
|
||||
for (var i = 1; i < points.length; i++)
|
||||
{
|
||||
graphics.lineTo(points[i].x, points[i].y);
|
||||
}
|
||||
|
||||
graphics.strokePath();
|
||||
graphics.closePath();
|
||||
|
||||
// So you can chain graphics calls
|
||||
return graphics;
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -23,21 +23,27 @@ var EllipseCurve = new Class({
|
|||
|
||||
Curve.call(this);
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.p0 = new Vector2(x, y);
|
||||
|
||||
this.xRadius = xRadius;
|
||||
this.yRadius = yRadius;
|
||||
this._xRadius = xRadius;
|
||||
this._yRadius = yRadius;
|
||||
|
||||
// Radians
|
||||
this.startAngle = DegToRad(startAngle);
|
||||
this.endAngle = DegToRad(endAngle);
|
||||
this._startAngle = DegToRad(startAngle);
|
||||
this._endAngle = DegToRad(endAngle);
|
||||
|
||||
// Boolean (anti-clockwise direction)
|
||||
this.clockwise = clockwise;
|
||||
this._clockwise = clockwise;
|
||||
|
||||
// The rotation of the arc
|
||||
this.rotation = DegToRad(rotation);
|
||||
this._rotation = DegToRad(rotation);
|
||||
|
||||
this._startPoint = this.getPoint(0);
|
||||
},
|
||||
|
||||
getStartPoint: function ()
|
||||
{
|
||||
return this._startPoint;
|
||||
},
|
||||
|
||||
getResolution: function (divisions)
|
||||
|
@ -50,8 +56,8 @@ var EllipseCurve = new Class({
|
|||
if (out === undefined) { out = new Vector2(); }
|
||||
|
||||
var twoPi = Math.PI * 2;
|
||||
var deltaAngle = this.endAngle - this.startAngle;
|
||||
var samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
|
||||
var deltaAngle = this._endAngle - this._startAngle;
|
||||
var samePoints = Math.abs(deltaAngle) < Number.EPSILON;
|
||||
|
||||
// ensures that deltaAngle is 0 .. 2 PI
|
||||
while (deltaAngle < 0)
|
||||
|
@ -76,7 +82,7 @@ var EllipseCurve = new Class({
|
|||
}
|
||||
}
|
||||
|
||||
if (this.clockwise && ! samePoints)
|
||||
if (this._clockwise && !samePoints)
|
||||
{
|
||||
if (deltaAngle === twoPi)
|
||||
{
|
||||
|
@ -88,24 +94,126 @@ var EllipseCurve = new Class({
|
|||
}
|
||||
}
|
||||
|
||||
var angle = this.startAngle + t * deltaAngle;
|
||||
var x = this.x + this.xRadius * Math.cos(angle);
|
||||
var y = this.y + this.yRadius * Math.sin(angle);
|
||||
var angle = this._startAngle + t * deltaAngle;
|
||||
var x = this.p0.x + this._xRadius * Math.cos(angle);
|
||||
var y = this.p0.y + this._yRadius * Math.sin(angle);
|
||||
|
||||
if (this.rotation !== 0)
|
||||
if (this._rotation !== 0)
|
||||
{
|
||||
var cos = Math.cos(this.rotation);
|
||||
var sin = Math.sin(this.rotation);
|
||||
var cos = Math.cos(this._rotation);
|
||||
var sin = Math.sin(this._rotation);
|
||||
|
||||
var tx = x - this.x;
|
||||
var ty = y - this.y;
|
||||
var tx = x - this.p0.x;
|
||||
var ty = y - this.p0.y;
|
||||
|
||||
// Rotate the point about the center of the ellipse.
|
||||
x = tx * cos - ty * sin + this.x;
|
||||
y = tx * sin + ty * cos + this.y;
|
||||
x = tx * cos - ty * sin + this.p0.x;
|
||||
y = tx * sin + ty * cos + this.p0.y;
|
||||
}
|
||||
|
||||
return out.set(x, y);
|
||||
},
|
||||
|
||||
x: {
|
||||
get: function ()
|
||||
{
|
||||
return this.p0.x;
|
||||
},
|
||||
|
||||
set: function (value)
|
||||
{
|
||||
this.p0.x = value;
|
||||
}
|
||||
},
|
||||
|
||||
y: {
|
||||
get: function ()
|
||||
{
|
||||
return this.p0.y;
|
||||
},
|
||||
|
||||
set: function (value)
|
||||
{
|
||||
this.p0.y = value;
|
||||
}
|
||||
},
|
||||
|
||||
xRadius: {
|
||||
get: function ()
|
||||
{
|
||||
return this._xRadius;
|
||||
},
|
||||
|
||||
set: function (value)
|
||||
{
|
||||
this._xRadius = value;
|
||||
this.getPoint(0, this._startPoint);
|
||||
}
|
||||
},
|
||||
|
||||
yRadius: {
|
||||
get: function ()
|
||||
{
|
||||
return this._yRadius;
|
||||
},
|
||||
|
||||
set: function (value)
|
||||
{
|
||||
this._yRadius = value;
|
||||
this.getPoint(0, this._startPoint);
|
||||
}
|
||||
},
|
||||
|
||||
startAngle: {
|
||||
get: function ()
|
||||
{
|
||||
return this._startAngle;
|
||||
},
|
||||
|
||||
set: function (value)
|
||||
{
|
||||
this._startAngle = DegToRad(value);
|
||||
this.getPoint(0, this._startPoint);
|
||||
}
|
||||
},
|
||||
|
||||
endAngle: {
|
||||
get: function ()
|
||||
{
|
||||
return this._endAngle;
|
||||
},
|
||||
|
||||
set: function (value)
|
||||
{
|
||||
this._endAngle = DegToRad(value);
|
||||
this.getPoint(0, this._startPoint);
|
||||
}
|
||||
},
|
||||
|
||||
clockwise: {
|
||||
get: function ()
|
||||
{
|
||||
return this._clockwise;
|
||||
},
|
||||
|
||||
set: function (value)
|
||||
{
|
||||
this._clockwise = value;
|
||||
this.getPoint(0, this._startPoint);
|
||||
}
|
||||
},
|
||||
|
||||
rotation: {
|
||||
get: function ()
|
||||
{
|
||||
return this._rotation;
|
||||
},
|
||||
|
||||
set: function (value)
|
||||
{
|
||||
this._rotation = DegToRad(value);
|
||||
this.getPoint(0, this._startPoint);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -14,22 +14,27 @@ var LineCurve = new Class({
|
|||
|
||||
initialize:
|
||||
|
||||
// vec2s
|
||||
function LineCurve (v1, v2)
|
||||
// vec2s or array
|
||||
function LineCurve (p0, p1)
|
||||
{
|
||||
if (Array.isArray(v1))
|
||||
{
|
||||
v2 = new Vector2(v1[2], v1[3]);
|
||||
v1 = new Vector2(v1[0], v1[1]);
|
||||
}
|
||||
|
||||
Curve.call(this);
|
||||
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
if (Array.isArray(p0))
|
||||
{
|
||||
p1 = new Vector2(p0[2], p0[3]);
|
||||
p0 = new Vector2(p0[0], p0[1]);
|
||||
}
|
||||
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
},
|
||||
|
||||
getResolution: function (divisions)
|
||||
getStartPoint: function ()
|
||||
{
|
||||
return this.p0;
|
||||
},
|
||||
|
||||
getResolution: function ()
|
||||
{
|
||||
return 1;
|
||||
},
|
||||
|
@ -40,10 +45,10 @@ var LineCurve = new Class({
|
|||
|
||||
if (t === 1)
|
||||
{
|
||||
return out.copy(this.v2);
|
||||
return out.copy(this.p1);
|
||||
}
|
||||
|
||||
out.copy(this.v2).sub(this.v1).scale(t).add(this.v1);
|
||||
out.copy(this.p1).sub(this.p0).scale(t).add(this.p0);
|
||||
|
||||
return out;
|
||||
},
|
||||
|
@ -56,9 +61,18 @@ var LineCurve = new Class({
|
|||
|
||||
getTangent: function ()
|
||||
{
|
||||
var tangent = tmpVec2.copy(this.v2).sub(this.v1);
|
||||
var tangent = tmpVec2.copy(this.p1).sub(this.p0);
|
||||
|
||||
return tangent.normalize();
|
||||
},
|
||||
|
||||
// Override default Curve.draw because this is better than calling getPoints on a line!
|
||||
draw: function (graphics)
|
||||
{
|
||||
graphics.lineBetween(this.p0.x, this.p0.y, this.p1.x, this.p1.y);
|
||||
|
||||
// So you can chain graphics calls
|
||||
return graphics;
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -23,6 +23,11 @@ var SplineCurve = new Class({
|
|||
this.points = points;
|
||||
},
|
||||
|
||||
getStartPoint: function ()
|
||||
{
|
||||
return this.points[0];
|
||||
},
|
||||
|
||||
getResolution: function (divisions)
|
||||
{
|
||||
return divisions * this.points.length;
|
||||
|
@ -40,10 +45,10 @@ var SplineCurve = new Class({
|
|||
|
||||
var weight = point - intPoint;
|
||||
|
||||
var p0 = points[ (intPoint === 0) ? intPoint : intPoint - 1 ];
|
||||
var p1 = points[ intPoint ];
|
||||
var p2 = points[ (intPoint > points.length - 2) ? points.length - 1 : intPoint + 1 ];
|
||||
var p3 = points[ (intPoint > points.length - 3) ? points.length - 1 : intPoint + 2 ];
|
||||
var p0 = points[(intPoint === 0) ? intPoint : intPoint - 1];
|
||||
var p1 = points[intPoint];
|
||||
var p2 = points[(intPoint > points.length - 2) ? points.length - 1 : intPoint + 1];
|
||||
var p3 = points[(intPoint > points.length - 3) ? points.length - 1 : intPoint + 2];
|
||||
|
||||
return out.set(CatmullRom(weight, p0.x, p1.x, p2.x, p3.x), CatmullRom(weight, p0.y, p1.y, p2.y, p3.y));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue