Added VerletManager and lots of new tests

This commit is contained in:
Richard Davey
2013-05-21 04:12:54 +01:00
parent 0b2d818ba8
commit e2141c91a6
37 changed files with 3612 additions and 29 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

+10
View File
@@ -15,7 +15,9 @@
/// <reference path="Stage.ts" />
/// <reference path="Time.ts" />
/// <reference path="TweenManager.ts" />
/// <reference path="VerletManager.ts" />
/// <reference path="World.ts" />
/// <reference path="geom/Vector2.ts" />
/// <reference path="system/Device.ts" />
/// <reference path="system/RandomDataGenerator.ts" />
/// <reference path="system/RequestAnimationFrame.ts" />
@@ -230,6 +232,12 @@ module Phaser {
*/
public tweens: TweenManager;
/**
* Reference to the verlet manager.
* @type {VerletManager}
*/
public verlet: Phaser.Verlet.VerletManager;
/**
* Reference to the world.
* @type {World}
@@ -292,6 +300,7 @@ module Phaser {
this.tweens = new TweenManager(this);
this.input = new Input(this);
this.rnd = new RandomDataGenerator([(Date.now() * Math.random()).toString()]);
this.verlet = new Phaser.Verlet.VerletManager(this, width, height);
this.framerate = 60;
this.isBooted = true;
@@ -368,6 +377,7 @@ module Phaser {
this.tweens.update();
this.input.update();
this.stage.update();
this.verlet.update();
this._accumulator += this.time.delta;
+39
View File
@@ -1022,6 +1022,45 @@ module Phaser {
}
/**
* Returns the distance from this Point object to the given Point object.
* @method distanceFrom
* @param {Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
public static distanceBetween(x1: number, y1: number, x2: number, y2: number): number {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
/**
* Rotates a point around the x/y coordinates given to the desired angle
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param angle {number} The angle of the rotation in radians
* @param point {Point} The point object to perform the rotation on
* @return The modified point object
*/
public rotatePoint(x: number, y: number, angle: number, point) {
var s: number = Math.sin(angle);
var c: number = Math.cos(angle);
point.x -= x;
point.y -= y;
var newX: number = point.x * c - point.y * s;
var newY: number = point.x * s - point.y * c;
return point.setTo(newX + x, newY + y);
}
}
}
+95 -9
View File
@@ -21,9 +21,31 @@ module Phaser {
this._maxSize = MaxSize;
this._marker = 0;
this._sortIndex = null;
this.cameraBlacklist = [];
}
/**
* Internal tracker for the maximum capacity of the group.
* Default is 0, or no max capacity.
*/
private _maxSize: number;
/**
* Internal helper variable for recycling objects a la <code>Emitter</code>.
*/
private _marker: number;
/**
* Helper for sort.
*/
private _sortIndex: string;
/**
* Helper for sort.
*/
private _sortOrder: number;
/**
* Use with <code>sort()</code> to sort in ascending order.
*/
@@ -47,25 +69,62 @@ module Phaser {
public length: number;
/**
* Internal tracker for the maximum capacity of the group.
* Default is 0, or no max capacity.
* You can set a globalCompositeOperation that will be applied before the render method is called on this Groups children.
* This is useful if you wish to apply an effect like 'lighten' to a whole group of children as it saves doing it one-by-one.
* If this value is set it will call a canvas context save and restore before and after the render pass.
* Set to null to disable.
*/
private _maxSize: number;
public globalCompositeOperation: string = null;
/**
* Internal helper variable for recycling objects a la <code>Emitter</code>.
* You can set an alpha value on this Group that will be applied before the render method is called on this Groups children.
* This is useful if you wish to alpha a whole group of children as it saves doing it one-by-one.
* Set to 0 to disable.
*/
private _marker: number;
public alpha: number = 0;
/**
* Helper for sort.
* An Array of Cameras to which this Group, or any of its children, won't render
* @type {Array}
*/
private _sortIndex: string;
public cameraBlacklist: number[];
/**
* Helper for sort.
* If you do not wish this object to be visible to a specific camera, pass the camera here.
*
* @param camera {Camera} The specific camera.
*/
public hideFromCamera(camera: Camera) {
if (this.cameraBlacklist.indexOf(camera.ID) == -1)
{
this.cameraBlacklist.push(camera.ID);
}
}
/**
* Make this object only visible to a specific camera.
*
* @param camera {Camera} The camera you wish it to be visible.
*/
public showToCamera(camera: Camera) {
if (this.cameraBlacklist.indexOf(camera.ID) !== -1)
{
this.cameraBlacklist.slice(this.cameraBlacklist.indexOf(camera.ID), 1);
}
}
/**
* This clears the camera black list, making the GameObject visible to all cameras.
*/
private _sortOrder: number;
public clearCameraList() {
this.cameraBlacklist.length = 0;
}
/**
* Override this function to handle any deleting or "shutdown" type operations you might need,
@@ -126,11 +185,28 @@ module Phaser {
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number, forceRender?: bool = false) {
if (this.cameraBlacklist.indexOf(camera.ID) !== -1)
{
return;
}
if (this.ignoreGlobalRender && forceRender == false)
{
return;
}
if (this.globalCompositeOperation)
{
this._game.stage.context.save();
this._game.stage.context.globalCompositeOperation = this.globalCompositeOperation;
}
if (this.alpha > 0)
{
var prevAlpha: number = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
}
var basic: Basic;
var i: number = 0;
@@ -143,6 +219,16 @@ module Phaser {
basic.render(camera, cameraOffsetX, cameraOffsetY, forceRender);
}
}
if (this.alpha > 0)
{
this._game.stage.context.globalAlpha = prevAlpha;
}
if (this.globalCompositeOperation)
{
this._game.stage.context.restore();
}
}
/**
+28
View File
@@ -105,9 +105,25 @@
<Content Include="gameobjects\Tilemap.js">
<DependentUpon>Tilemap.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="verlet\AngleConstraint.ts" />
<TypeScriptCompile Include="VerletManager.ts" />
<Content Include="VerletManager.js">
<DependentUpon>VerletManager.ts</DependentUpon>
</Content>
<Content Include="verlet\AngleConstraint.js">
<DependentUpon>AngleConstraint.ts</DependentUpon>
</Content>
<Content Include="geom\Circle.js">
<DependentUpon>Circle.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="verlet\DistanceConstraint.ts" />
<TypeScriptCompile Include="verlet\Composite.ts" />
<Content Include="verlet\Composite.js">
<DependentUpon>Composite.ts</DependentUpon>
</Content>
<Content Include="verlet\DistanceConstraint.js">
<DependentUpon>DistanceConstraint.ts</DependentUpon>
</Content>
<Content Include="geom\IntersectResult.js">
<DependentUpon>IntersectResult.ts</DependentUpon>
</Content>
@@ -118,6 +134,14 @@
<Content Include="geom\MicroPoint.js">
<DependentUpon>MicroPoint.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="verlet\PinConstraint.ts" />
<TypeScriptCompile Include="verlet\Particle.ts" />
<Content Include="verlet\Particle.js">
<DependentUpon>Particle.ts</DependentUpon>
</Content>
<Content Include="verlet\PinConstraint.js">
<DependentUpon>PinConstraint.ts</DependentUpon>
</Content>
<Content Include="geom\Point.js">
<DependentUpon>Point.ts</DependentUpon>
</Content>
@@ -128,6 +152,10 @@
<Content Include="geom\Rectangle.js">
<DependentUpon>Rectangle.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geom\Vector2.ts" />
<Content Include="geom\Vector2.js">
<DependentUpon>Vector2.ts</DependentUpon>
</Content>
<Content Include="SoundManager.js">
<DependentUpon>SoundManager.ts</DependentUpon>
</Content>
+1
View File
@@ -47,6 +47,7 @@ module Phaser {
this.canvas.style['ms-touch-action'] = 'none';
this.canvas.style['touch-action'] = 'none';
this.canvas.style.backgroundColor = 'rgb(0,0,0)';
this.canvas.oncontextmenu = function(event) { event.preventDefault(); };
this.context = this.canvas.getContext('2d');
+401
View File
@@ -0,0 +1,401 @@
/// <reference path="Game.ts" />
/// <reference path="geom/Vector2.ts" />
/// <reference path="verlet/Composite.ts" />
/// <reference path="verlet/Particle.ts" />
/// <reference path="verlet/DistanceConstraint.ts" />
/// <reference path="verlet/PinConstraint.ts" />
/// <reference path="verlet/AngleConstraint.ts" />
/**
* Phaser - Verlet
*
* Based on verlet-js by Sub Protocol released under MIT
*/
module Phaser.Verlet {
export class VerletManager {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Vector2} This object
**/
constructor(game: Game, width: number, height: number) {
this._game = game;
this.width = width;
this.height = height;
this.gravity = new Vector2(0, 0.2);
this.friction = 0.99;
this.groundFriction = 0.8;
this.canvas = game.stage.canvas;
this.context = game.stage.context;
this._game.input.onDown.add(this.mouseDownHandler, this);
this._game.input.onUp.add(this.mouseUpHandler, this);
}
private _game: Game;
public composites = [];
public width: number;
public height: number;
public step: number = 32;
public gravity: Vector2;
public friction: number;
public groundFriction: number;
public selectionRadius: number = 20;
public draggedEntity = null;
public highlightColor = '#4f545c';
/**
* This class is actually a wrapper of canvas.
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
* Canvas context of this object.
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
/**
* Computes time of intersection of a particle with a wall
*
* @param {Vec2} line wall's root position
* @param {Vec2} p particle's position
* @param {Vec2} dir walls's direction
* @param {Vec2} v particle's velocity
*/
public intersectionTime(wall, p, dir, v) {
if (dir.x != 0)
{
var denominator = v.y - dir.y * v.x / dir.x;
if (denominator == 0) return undefined; // Movement is parallel to wall
var numerator = wall.y + dir.y * (p.x - wall.x) / dir.x - p.y;
return numerator / denominator;
}
else
{
if (v.x == 0) return undefined; // parallel again
var denominator = v.x;
var numerator = wall.x - p.x;
return numerator / denominator;
}
}
public intersectionPoint(wall, p, dir, v) {
var t = this.intersectionTime(wall, p, dir, v);
return new Phaser.Vector2(p.x + v.x * t, p.y + v.y * t);
}
private v = new Phaser.Vector2();
public bounds(particle: Phaser.Verlet.Particle) {
this.v.mutableSet(particle.pos);
this.v.mutableSub(particle.lastPos);
if (particle.pos.y > this.height - 1)
{
particle.pos.mutableSet(
this.intersectionPoint(new Phaser.Vector2(0, this.height - 1), particle.lastPos, new Phaser.Vector2(1, 0), this.v));
}
if (particle.pos.x < 0)
{
particle.pos.mutableSet(
this.intersectionPoint(new Phaser.Vector2(0, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
}
if (particle.pos.x > this.width - 1)
{
particle.pos.mutableSet(
this.intersectionPoint(new Phaser.Vector2(this.width - 1, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
}
}
public OLDbounds(particle: Phaser.Verlet.Particle) {
if (particle.pos.y > this.height - 1)
particle.pos.y = this.height - 1;
if (particle.pos.x < 0)
{
var vx = particle.pos.x - particle.lastPos.x;
var vy = particle.pos.y - particle.lastPos.y;
if (vx == 0)
{
particle.pos.x = 0;
}
else
{
var t = -particle.lastPos.x / vx;
particle.pos.x = particle.lastPos.x + t * vx;
particle.pos.y = particle.lastPos.y + t * vy;
}
}
if (particle.pos.x > this.width - 1)
particle.pos.x = this.width - 1;
}
public createPoint(pos: Vector2) {
var composite = new Phaser.Verlet.Composite(this._game);
composite.particles.push(new Phaser.Verlet.Particle(pos));
this.composites.push(composite);
return composite;
}
public createLineSegments(vertices, stiffness) {
var i;
var composite = new Phaser.Verlet.Composite(this._game);
for (i in vertices)
{
composite.particles.push(new Phaser.Verlet.Particle(vertices[i]));
if (i > 0)
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[i], composite.particles[i - 1], stiffness));
}
this.composites.push(composite);
return composite;
}
public createCloth(origin, width, height, segments, pinMod, stiffness) {
var composite = new Phaser.Verlet.Composite(this._game);
var xStride = width / segments;
var yStride = height / segments;
var x, y;
for (y = 0; y < segments; ++y)
{
for (x = 0; x < segments; ++x)
{
var px = origin.x + x * xStride - width / 2 + xStride / 2;
var py = origin.y + y * yStride - height / 2 + yStride / 2;
composite.particles.push(new Phaser.Verlet.Particle(new Vector2(px, py)));
if (x > 0)
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[y * segments + x - 1], stiffness));
if (y > 0)
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[(y - 1) * segments + x], stiffness));
}
}
for (x = 0; x < segments; ++x)
{
if (x % pinMod == 0)
composite.pin(x);
}
this.composites.push(composite);
return composite;
}
public createTire(origin, radius, segments, spokeStiffness, treadStiffness) {
var stride = (2 * Math.PI) / segments;
var i;
var composite = new Phaser.Verlet.Composite(this._game);
// particles
for (i = 0; i < segments; ++i)
{
var theta = i * stride;
composite.particles.push(new Particle(new Vector2(origin.x + Math.cos(theta) * radius, origin.y + Math.sin(theta) * radius)));
}
var center = new Particle(origin);
composite.particles.push(center);
// constraints
for (i = 0; i < segments; ++i)
{
composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[(i + 1) % segments], treadStiffness));
composite.constraints.push(new DistanceConstraint(composite.particles[i], center, spokeStiffness))
composite.constraints.push(new DistanceConstraint(composite.particles[i], composite.particles[(i + 5) % segments], treadStiffness));
}
this.composites.push(composite);
return composite;
}
public update() {
if (this.composites.length == 0)
{
return;
}
var i, j, c;
for (c in this.composites)
{
for (i in this.composites[c].particles)
{
var particles = this.composites[c].particles;
// calculate velocity
var velocity = particles[i].pos.sub(particles[i].lastPos).scale(this.friction);
// ground friction
if (particles[i].pos.y >= this.height - 1 && velocity.length2() > 0.000001)
{
var m = velocity.length();
velocity.x /= m;
velocity.y /= m;
velocity.mutableScale(m * this.groundFriction);
}
// save last good state
particles[i].lastPos.mutableSet(particles[i].pos);
// gravity
particles[i].pos.mutableAdd(this.gravity);
// inertia
particles[i].pos.mutableAdd(velocity);
}
}
// handle dragging of entities
if (this.draggedEntity)
this.draggedEntity.pos.mutableSet(new Vector2(this._game.input.x, this._game.input.y));
// relax
var stepCoef = 1 / this.step;
for (c in this.composites)
{
var constraints = this.composites[c].constraints;
for (i = 0; i < this.step; ++i)
for (j in constraints)
constraints[j].relax(stepCoef);
}
// bounds checking
for (c in this.composites)
{
var particles = this.composites[c].particles;
for (i in particles)
this.bounds(particles[i]);
}
}
private mouseDownHandler() {
var nearest = this.nearestEntity();
if (nearest)
{
this.draggedEntity = nearest;
}
}
private mouseUpHandler() {
this.draggedEntity = null;
}
public nearestEntity() {
var c, i;
var d2Nearest = 0;
var entity = null;
var constraintsNearest = null;
// find nearest point
for (c in this.composites)
{
var particles = this.composites[c].particles;
for (i in particles)
{
var d2 = particles[i].pos.dist2(new Vector2(this._game.input.x, this._game.input.y));
if (d2 <= this.selectionRadius * this.selectionRadius && (entity == null || d2 < d2Nearest))
{
entity = particles[i];
constraintsNearest = this.composites[c].constraints;
d2Nearest = d2;
}
}
}
// search for pinned constraints for this entity
for (i in constraintsNearest)
if (constraintsNearest[i] instanceof PinConstraint && constraintsNearest[i].a == entity)
entity = constraintsNearest[i];
return entity;
}
public render() {
var i, c;
for (c in this.composites)
{
// draw constraints
if (this.composites[c].drawConstraints)
{
this.composites[c].drawConstraints(this.context, this.composites[c]);
} else
{
var constraints = this.composites[c].constraints;
for (i in constraints)
constraints[i].render(this.context);
}
// draw particles
if (this.composites[c].drawParticles)
{
this.composites[c].drawParticles(this.context, this.composites[c]);
} else
{
var particles = this.composites[c].particles;
for (i in particles)
particles[i].render(this.context);
}
}
// highlight nearest / dragged entity
var nearest = this.draggedEntity || this.nearestEntity();
if (nearest)
{
this.context.beginPath();
this.context.arc(nearest.pos.x, nearest.pos.y, 8, 0, 2 * Math.PI);
this.context.strokeStyle = this.highlightColor;
this.context.stroke();
}
}
}
}
-1
View File
@@ -41,7 +41,6 @@ module Phaser {
this.scale = new MicroPoint(1, 1);
this.last = new MicroPoint(x, y);
//this.origin = new MicroPoint(this.frameBounds.halfWidth, this.frameBounds.halfHeight);
this.align = GameObject.ALIGN_TOP_LEFT;
this.mass = 1;
this.elasticity = 0;
+26
View File
@@ -296,6 +296,32 @@ module Phaser {
}
/**
* Rotates the point around the x/y coordinates given to the desired angle
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
* @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
public rotate(cx: number, cy: number, angle: number, asDegrees: bool = false, distance?:number = null) {
if (asDegrees)
{
angle = angle * GameMath.DEG_TO_RAD;
}
// Get distance from origin (cx/cy) to this point
if (distance === null)
{
distance = Math.sqrt(((cx - this.x) * (cx - this.x)) + ((cy - this.y) * (cy - this.y)));
}
return this.setTo(cx + distance * Math.cos(angle), cy + distance * Math.sin(angle));
}
/**
* Sets the x and y values of this Point object to the given coordinates.
* @method setTo
+1 -1
View File
@@ -19,7 +19,7 @@ module Phaser {
* @param {Number} y The y coordinate of the top-left corner of the quad.
* @param {Number} width The width of the quad.
* @param {Number} height The height of the quad.
* @return {Quad } This object
* @return {Quad} This object
**/
constructor(x: number = 0, y: number = 0, width: number = 0, height: number = 0) {
+151
View File
@@ -0,0 +1,151 @@
/// <reference path="../Game.ts" />
/**
* Phaser - Vector2
*
* A simple 2-dimensional vector class. Based on the one included with verlet-js by Sub Protocol released under MIT
*/
module Phaser {
export class Vector2 {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Vector2} This object
**/
constructor(x: number = 0, y: number = 0) {
this.x = x;
this.y = y;
}
public x: number;
public y: number;
public setTo(x: number, y: number): Vector2 {
this.x = x;
this.y = y;
return this;
}
public add(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x + v.x, this.y + v.y);
}
public sub(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x - v.x, this.y - v.y);
}
public mul(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x * v.x, this.y * v.y);
}
public div(v: Vector2, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x / v.x, this.y / v.y);
}
public scale(coef: number, output?:Vector2 = new Vector2): Vector2 {
return output.setTo(this.x * coef, this.y * coef);
}
public mutableSet(v: Vector2): Vector2 {
this.x = v.x;
this.y = v.y;
return this;
}
public mutableAdd(v: Vector2): Vector2 {
this.x += v.x;
this.y += v.y;
return this;
}
public mutableSub(v: Vector2): Vector2 {
this.x -= v.x;
this.y -= v.y;
return this;
}
public mutableMul(v: Vector2): Vector2 {
this.x *= v.x;
this.y *= v.y;
return this;
}
public mutableDiv(v: Vector2): Vector2 {
this.x /= v.x;
this.y /= v.y;
return this;
}
public mutableScale(coef: number): Vector2 {
this.x *= coef;
this.y *= coef;
return this;
}
public equals(v: Vector2): bool {
return this.x == v.x && this.y == v.y;
}
public epsilonEquals(v: Vector2, epsilon:number): bool {
return Math.abs(this.x - v.x) <= epsilon && Math.abs(this.y - v.y) <= epsilon;
}
public length(): number {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
public length2(): number {
return this.x * this.x + this.y * this.y;
}
public dist(v: Vector2): number {
return Math.sqrt(this.dist2(v));
}
public dist2(v: Vector2): number {
return ((v.x - this.x) * (v.x - this.x)) + ((v.y - this.y) * (v.y - this.y));
}
public normal(output?: Vector2 = new Vector2) {
var m = Math.sqrt(this.x * this.x + this.y * this.y);
return output.setTo(this.x / m, this.y / m);
}
public dot(v: Vector2): number {
return this.x * v.x + this.y * v.y;
}
public angle(v: Vector2): number {
return Math.atan2(this.x * v.y - this.y * v.x, this.x * v.x + this.y * v.y);
}
public angle2(vLeft: Vector2, vRight: Vector2): number {
return vLeft.sub(this).angle(vRight.sub(this));
}
public rotate(origin, theta, output?: Vector2 = new Vector2): Vector2 {
var x = this.x - origin.x;
var y = this.y - origin.y;
return output.setTo(x * Math.cos(theta) - y * Math.sin(theta) + origin.x, x * Math.sin(theta) + y * Math.cos(theta) + origin.y);
}
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the object.
**/
public toString(): string {
return "[{Vector2 (x=" + this.x + " y=" + this.y + ")}]";
}
}
}
+74
View File
@@ -0,0 +1,74 @@
/// <reference path="../Game.ts" />
/// <reference path="Particle.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - AngleConstraint
*
* constrains 3 particles to an angle
*/
module Phaser.Verlet {
export class AngleConstraint {
/**
* Creates a new AngleConstraint object.
* @class AngleConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {AngleConstraint} This object
**/
constructor(a: Phaser.Verlet.Particle, b: Phaser.Verlet.Particle, c: Phaser.Verlet.Particle, stiffness: number) {
this.a = a;
this.b = b;
this.c = c;
this.angle = this.b.pos.angle2(this.a.pos, this.c.pos);
this.stiffness = stiffness;
}
public a: Phaser.Verlet.Particle;
public b: Phaser.Verlet.Particle;
public c: Phaser.Verlet.Particle;
public angle: number;
public stiffness: number;
public relax(stepCoef: number) {
var angle = this.b.pos.angle2(this.a.pos, this.c.pos);
var diff = angle - this.angle;
if (diff <= -Math.PI)
diff += 2 * Math.PI;
else if (diff >= Math.PI)
diff -= 2 * Math.PI;
diff *= stepCoef * this.stiffness;
this.a.pos = this.a.pos.rotate(this.b.pos, diff);
this.c.pos = this.c.pos.rotate(this.b.pos, -diff);
this.b.pos = this.b.pos.rotate(this.a.pos, diff);
this.b.pos = this.b.pos.rotate(this.c.pos, -diff);
}
public render(ctx) {
ctx.beginPath();
ctx.moveTo(this.a.pos.x, this.a.pos.y);
ctx.lineTo(this.b.pos.x, this.b.pos.y);
ctx.lineTo(this.c.pos.x, this.c.pos.y);
var tmp = ctx.lineWidth;
ctx.lineWidth = 5;
ctx.strokeStyle = "rgba(255,255,0,0.2)";
ctx.stroke();
ctx.lineWidth = tmp;
}
}
}
+78
View File
@@ -0,0 +1,78 @@
/// <reference path="../Game.ts" />
/// <reference path="../geom/Vector2.ts" />
/// <reference path="Particle.ts" />
/// <reference path="PinConstraint.ts" />
/**
* Phaser - Verlet - Composite
*
*
*/
module Phaser.Verlet {
export class Composite {
/**
* Creates a new Composite object.
* @class Composite
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Composite} This object
**/
constructor(game: Game) {
this._game = game;
this.particles = [];
this.constraints = [];
}
private _game: Game;
public particles: Phaser.Verlet.Particle[];
public constraints;
public drawParticles = null;
public drawConstraints = null;
// Map sprites to particles
public createDistanceConstraint(a: Phaser.Verlet.Particle, b: Phaser.Verlet.Particle, stiffness: number, distance?: number = null): Phaser.Verlet.DistanceConstraint {
this.constraints.push(new Phaser.Verlet.DistanceConstraint(a, b, stiffness, distance));
return this.constraints[this.constraints.length - 1];
}
public createAngleConstraint(a: Phaser.Verlet.Particle, b: Phaser.Verlet.Particle, c: Phaser.Verlet.Particle, stiffness: number): Phaser.Verlet.AngleConstraint {
this.constraints.push(new Phaser.Verlet.AngleConstraint(a, b, c, stiffness));
return this.constraints[this.constraints.length - 1];
}
public createPinConstraint(a: Phaser.Verlet.Particle, pos: Vector2): Phaser.Verlet.PinConstraint {
this.constraints.push(new Phaser.Verlet.PinConstraint(a, pos));
return this.constraints[this.constraints.length - 1];
}
public pin(index, pos?=null) {
if (pos == null)
{
pos = this.particles[index].pos;
}
var pc = new Phaser.Verlet.PinConstraint(this.particles[index], pos);
this.constraints.push(pc);
return pc;
}
}
}
+69
View File
@@ -0,0 +1,69 @@
/// <reference path="../Game.ts" />
/// <reference path="Particle.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - DistanceConstraint
*
* Constrains to initial distance
*/
module Phaser.Verlet {
export class DistanceConstraint {
/**
* Creates a new DistanceConstraint object.
* @class DistanceConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {DistanceConstraint} This object
**/
constructor(a: Phaser.Verlet.Particle, b: Phaser.Verlet.Particle, stiffness: number, distance?:number = null) {
this.a = a;
this.b = b;
if (distance === null)
{
this.distance = a.pos.sub(b.pos).length();
}
else
{
this.distance = distance;
}
this.stiffness = stiffness;
}
public a: Phaser.Verlet.Particle;
public b: Phaser.Verlet.Particle;
public distance: number;
public stiffness: number;
public relax(stepCoef: number) {
var normal = this.a.pos.sub(this.b.pos);
var m = normal.length2();
normal.mutableScale(((this.distance * this.distance - m) / m) * this.stiffness * stepCoef);
this.a.pos.mutableAdd(normal);
this.b.pos.mutableSub(normal);
}
public render(ctx) {
ctx.beginPath();
ctx.moveTo(this.a.pos.x, this.a.pos.y);
ctx.lineTo(this.b.pos.x, this.b.pos.y);
ctx.strokeStyle = "#d8dde2";
ctx.stroke();
}
}
}
+44
View File
@@ -0,0 +1,44 @@
/// <reference path="../Game.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - Verlet - Particle
*
*
*/
module Phaser.Verlet {
export class Particle {
/**
* Creates a new Particle object.
* @class Particle
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Particle} This object
**/
constructor(pos: Vector2) {
this.pos = (new Vector2()).mutableSet(pos);
this.lastPos = (new Vector2()).mutableSet(pos);
}
public pos: Vector2;
public lastPos: Vector2;
public render(ctx) {
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, 2, 0, 2*Math.PI);
ctx.fillStyle = "#2dad8f";
ctx.fill();
}
}
}
+48
View File
@@ -0,0 +1,48 @@
/// <reference path="../Game.ts" />
/// <reference path="Particle.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - PinConstraint
*
* Constrains to static / fixed point
*/
module Phaser.Verlet {
export class PinConstraint {
/**
* Creates a new PinConstraint object.
* @class PinConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {PinConstraint} This object
**/
constructor(a: Phaser.Verlet.Particle, pos: Vector2) {
this.a = a;
this.pos = (new Vector2()).mutableSet(pos);
}
public a: Phaser.Verlet.Particle;
public pos: Vector2;
public relax() {
this.a.pos.mutableSet(this.pos);
}
public render(ctx) {
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, 6, 0, 2*Math.PI);
ctx.fillStyle = "rgba(0,153,255,0.1)";
ctx.fill();
}
}
}
+5
View File
@@ -86,6 +86,11 @@ V0.9.6
* Updated QuadTree to use the new CollisionMask values and significantly optimised and reduced overall class size
* Updated Collision.seperate to use the new CollisionMask
* Added a callback context parameter to Game.collide, Collision.overlap and the QuadTree class
* Stage.canvas now calls preventDefault() when the context menu is activated (oncontextmenu)
* Added Point.rotate to allow you to rotate a point around another point, with optional distance clamping. Also created test cases.
* Added Group.alpha to apply a globalAlpha before the groups children are rendered. Useful to save on alpha calls.
* Added Group.globalCompositeOperation to apply a composite operation before all of the groups children are rendered.
* Added Camera black list support to Group along with Group.showToCamera, Group.hideFromCamera and Group.clearCameraList
+28
View File
@@ -125,6 +125,34 @@
<Content Include="collision\mask test 2.js">
<DependentUpon>mask test 2.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geometry\multi rotate.ts" />
<Content Include="geometry\multi rotate.js">
<DependentUpon>multi rotate.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geometry\rotate point 2.ts" />
<TypeScriptCompile Include="geometry\rotate point 1.ts" />
<Content Include="geometry\rotate point 1.js">
<DependentUpon>rotate point 1.ts</DependentUpon>
</Content>
<Content Include="geometry\rotate point 2.js">
<DependentUpon>rotate point 2.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geometry\rotate point 3.ts" />
<Content Include="geometry\rotate point 3.js">
<DependentUpon>rotate point 3.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geometry\verlet 1.ts" />
<TypeScriptCompile Include="geometry\rotate point 4.ts" />
<Content Include="geometry\rotate point 4.js">
<DependentUpon>rotate point 4.ts</DependentUpon>
</Content>
<Content Include="geometry\verlet 1.js">
<DependentUpon>verlet 1.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geometry\verlet sprites.ts" />
<Content Include="geometry\verlet sprites.js">
<DependentUpon>verlet sprites.ts</DependentUpon>
</Content>
<Content Include="groups\display order.js">
<DependentUpon>display order.ts</DependentUpon>
</Content>
+31
View File
@@ -0,0 +1,31 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var p1;
var p2;
var p3;
var p4;
var d = 0;
function create() {
p1 = new Phaser.Point(myGame.stage.centerX, myGame.stage.centerY);
p2 = new Phaser.Point(p1.x - 50, p1.y - 50);
p3 = new Phaser.Point(p1.x - 100, p1.y - 100);
p4 = new Phaser.Point(p1.x - 150, p1.y - 150);
}
function update() {
p2.rotate(p1.x, p1.y, myGame.math.wrapAngle(d), true);
p3.rotate(p1.x, p1.y, myGame.math.wrapAngle(d), true);
p4.rotate(p1.x, p1.y, myGame.math.wrapAngle(d), true);
d++;
}
function render() {
myGame.stage.context.fillStyle = 'rgb(255,255,0)';
myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(255,0,0)';
myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(0,255,0)';
myGame.stage.context.fillRect(p3.x, p3.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(255,0,255)';
myGame.stage.context.fillRect(p4.x, p4.y, 4, 4);
}
})();
+49
View File
@@ -0,0 +1,49 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var p1:Phaser.Point;
var p2:Phaser.Point;
var p3:Phaser.Point;
var p4:Phaser.Point;
var d: number = 0;
function create() {
p1 = new Phaser.Point(myGame.stage.centerX, myGame.stage.centerY);
p2 = new Phaser.Point(p1.x - 50, p1.y - 50);
p3 = new Phaser.Point(p1.x - 100, p1.y - 100);
p4 = new Phaser.Point(p1.x - 150, p1.y - 150);
}
function update() {
p2.rotate(p1.x, p1.y, myGame.math.wrapAngle(d), true);
p3.rotate(p1.x, p1.y, myGame.math.wrapAngle(d), true);
p4.rotate(p1.x, p1.y, myGame.math.wrapAngle(d), true);
d++;
}
function render() {
myGame.stage.context.fillStyle = 'rgb(255,255,0)';
myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(255,0,0)';
myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(0,255,0)';
myGame.stage.context.fillRect(p3.x, p3.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(255,0,255)';
myGame.stage.context.fillRect(p4.x, p4.y, 4, 4);
}
})();
+21
View File
@@ -0,0 +1,21 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var p1;
var p2;
var d = 0;
function create() {
p1 = new Phaser.Point(200, 300);
p2 = new Phaser.Point(300, 300);
}
function update() {
p1.rotate(p2.x, p2.y, myGame.math.wrapAngle(d), true);
d++;
}
function render() {
myGame.stage.context.fillStyle = 'rgb(255,255,0)';
myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(255,0,0)';
myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
}
})();
+36
View File
@@ -0,0 +1,36 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var p1:Phaser.Point;
var p2:Phaser.Point;
var d: number = 0;
function create() {
p1 = new Phaser.Point(200, 300);
p2 = new Phaser.Point(300, 300);
}
function update() {
p1.rotate(p2.x, p2.y, myGame.math.wrapAngle(d), true);
d++;
}
function render() {
myGame.stage.context.fillStyle = 'rgb(255,255,0)';
myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(255,0,0)';
myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
}
})();
+43
View File
@@ -0,0 +1,43 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var p1;
var p2;
var p3;
var p4;
var d2 = 0;
var d3 = 0;
var d4 = 0;
function create() {
p1 = new Phaser.Point(myGame.stage.centerX, myGame.stage.centerY);
p2 = new Phaser.Point(p1.x - 50, p1.y - 50);
p3 = new Phaser.Point(p2.x - 50, p2.y - 50);
p4 = new Phaser.Point(p3.x - 50, p3.y - 50);
}
function update() {
p2.rotate(p1.x, p1.y, myGame.math.wrapAngle(d2), true, 150);
p3.rotate(p2.x, p2.y, myGame.math.wrapAngle(d3), true, 50);
p4.rotate(p3.x, p3.y, myGame.math.wrapAngle(d4), true, 100);
d2 += 1;
d3 += 4;
d4 += 6;
}
function render() {
myGame.stage.context.strokeStyle = 'rgb(0,255,255)';
myGame.stage.context.beginPath();
myGame.stage.context.moveTo(p1.x, p1.y);
myGame.stage.context.lineTo(p2.x, p2.y);
myGame.stage.context.lineTo(p3.x, p3.y);
myGame.stage.context.lineTo(p4.x, p4.y);
myGame.stage.context.stroke();
myGame.stage.context.closePath();
myGame.stage.context.fillStyle = 'rgb(255,255,0)';
myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(255,0,0)';
myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(0,255,0)';
myGame.stage.context.fillRect(p3.x, p3.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(255,0,255)';
myGame.stage.context.fillRect(p4.x, p4.y, 4, 4);
}
})();
+62
View File
@@ -0,0 +1,62 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var p1:Phaser.Point;
var p2:Phaser.Point;
var p3:Phaser.Point;
var p4:Phaser.Point;
var d2: number = 0;
var d3: number = 0;
var d4: number = 0;
function create() {
p1 = new Phaser.Point(myGame.stage.centerX, myGame.stage.centerY);
p2 = new Phaser.Point(p1.x - 50, p1.y - 50);
p3 = new Phaser.Point(p2.x - 50, p2.y - 50);
p4 = new Phaser.Point(p3.x - 50, p3.y - 50);
}
function update() {
p2.rotate(p1.x, p1.y, myGame.math.wrapAngle(d2), true, 150);
p3.rotate(p2.x, p2.y, myGame.math.wrapAngle(d3), true, 50);
p4.rotate(p3.x, p3.y, myGame.math.wrapAngle(d4), true, 100);
d2 += 1;
d3 += 4;
d4 += 6;
}
function render() {
myGame.stage.context.strokeStyle = 'rgb(0,255,255)';
myGame.stage.context.beginPath();
myGame.stage.context.moveTo(p1.x, p1.y);
myGame.stage.context.lineTo(p2.x, p2.y);
myGame.stage.context.lineTo(p3.x, p3.y);
myGame.stage.context.lineTo(p4.x, p4.y);
myGame.stage.context.stroke();
myGame.stage.context.closePath();
myGame.stage.context.fillStyle = 'rgb(255,255,0)';
myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(255,0,0)';
myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(0,255,0)';
myGame.stage.context.fillRect(p3.x, p3.y, 4, 4);
myGame.stage.context.fillStyle = 'rgb(255,0,255)';
myGame.stage.context.fillRect(p4.x, p4.y, 4, 4);
}
})();
+71
View File
@@ -0,0 +1,71 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var origin;
var p1;
var p2;
var p3;
var p4;
var d = 0;
function create() {
// This creates a box made up of 4 edge-points and rotates it around the origin
origin = new Phaser.Point(400, 300);
p1 = new Phaser.Point()// top left
;
p2 = new Phaser.Point()// top right
;
p3 = new Phaser.Point()// bottom right
;
p4 = new Phaser.Point()// bottom left
;
}
function update() {
// top left (red)
p1.rotate(origin.x, origin.y, myGame.math.wrapAngle(d), true, 200);
// top right (yellow)
p2.rotate(origin.x, origin.y, myGame.math.wrapAngle(d + 90), true, 200);
// bottom right (aqua)
p3.rotate(origin.x, origin.y, myGame.math.wrapAngle(d + 180), true, 200);
// bottom left (blue)
p4.rotate(origin.x, origin.y, myGame.math.wrapAngle(d + 270), true, 200);
d++;
}
function render() {
// Render the shape
myGame.stage.context.beginPath();
myGame.stage.context.fillStyle = 'rgba(0,255,0,0.2)';
myGame.stage.context.strokeStyle = 'rgb(0,255,0)';
myGame.stage.context.lineWidth = 1;
myGame.stage.context.moveTo(p1.x, p1.y);
myGame.stage.context.lineTo(p2.x, p2.y);
myGame.stage.context.lineTo(p3.x, p3.y);
myGame.stage.context.lineTo(p4.x, p4.y);
myGame.stage.context.lineTo(p1.x, p1.y);
myGame.stage.context.fill();
myGame.stage.context.stroke();
myGame.stage.context.closePath();
// Render the points
myGame.stage.context.fillStyle = 'rgb(255,255,255)';
myGame.stage.context.fillRect(origin.x, origin.y, 4, 4);
myGame.stage.context.beginPath();
myGame.stage.context.fillStyle = 'rgb(255,0,0)';
myGame.stage.context.arc(p1.x, p1.y, 4, 0, Math.PI * 2);
myGame.stage.context.fill();
myGame.stage.context.closePath();
myGame.stage.context.beginPath();
myGame.stage.context.fillStyle = 'rgb(255,255,0)';
myGame.stage.context.arc(p2.x, p2.y, 4, 0, Math.PI * 2);
myGame.stage.context.fill();
myGame.stage.context.closePath();
myGame.stage.context.beginPath();
myGame.stage.context.fillStyle = 'rgb(0,255,255)';
myGame.stage.context.arc(p3.x, p3.y, 4, 0, Math.PI * 2);
myGame.stage.context.fill();
myGame.stage.context.closePath();
myGame.stage.context.beginPath();
myGame.stage.context.fillStyle = 'rgb(0,0,255)';
myGame.stage.context.arc(p4.x, p4.y, 4, 0, Math.PI * 2);
myGame.stage.context.fill();
myGame.stage.context.closePath();
}
})();
+95
View File
@@ -0,0 +1,95 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var origin:Phaser.Point;
var p1:Phaser.Point;
var p2:Phaser.Point;
var p3:Phaser.Point;
var p4:Phaser.Point;
var d: number = 0;
function create() {
// This creates a box made up of 4 edge-points and rotates it around the origin
origin = new Phaser.Point(400, 300);
p1 = new Phaser.Point(); // top left
p2 = new Phaser.Point(); // top right
p3 = new Phaser.Point(); // bottom right
p4 = new Phaser.Point(); // bottom left
}
function update() {
// top left (red)
p1.rotate(origin.x, origin.y, myGame.math.wrapAngle(d), true, 200);
// top right (yellow)
p2.rotate(origin.x, origin.y, myGame.math.wrapAngle(d + 90), true, 200);
// bottom right (aqua)
p3.rotate(origin.x, origin.y, myGame.math.wrapAngle(d + 180), true, 200);
// bottom left (blue)
p4.rotate(origin.x, origin.y, myGame.math.wrapAngle(d + 270), true, 200);
d++;
}
function render() {
// Render the shape
myGame.stage.context.beginPath();
myGame.stage.context.fillStyle = 'rgba(0,255,0,0.2)';
myGame.stage.context.strokeStyle = 'rgb(0,255,0)';
myGame.stage.context.lineWidth = 1;
myGame.stage.context.moveTo(p1.x, p1.y);
myGame.stage.context.lineTo(p2.x, p2.y);
myGame.stage.context.lineTo(p3.x, p3.y);
myGame.stage.context.lineTo(p4.x, p4.y);
myGame.stage.context.lineTo(p1.x, p1.y);
myGame.stage.context.fill();
myGame.stage.context.stroke();
myGame.stage.context.closePath();
// Render the points
myGame.stage.context.fillStyle = 'rgb(255,255,255)';
myGame.stage.context.fillRect(origin.x, origin.y, 4, 4);
myGame.stage.context.beginPath();
myGame.stage.context.fillStyle = 'rgb(255,0,0)';
myGame.stage.context.arc(p1.x, p1.y, 4, 0, Math.PI * 2);
myGame.stage.context.fill();
myGame.stage.context.closePath();
myGame.stage.context.beginPath();
myGame.stage.context.fillStyle = 'rgb(255,255,0)';
myGame.stage.context.arc(p2.x, p2.y, 4, 0, Math.PI * 2);
myGame.stage.context.fill();
myGame.stage.context.closePath();
myGame.stage.context.beginPath();
myGame.stage.context.fillStyle = 'rgb(0,255,255)';
myGame.stage.context.arc(p3.x, p3.y, 4, 0, Math.PI * 2);
myGame.stage.context.fill();
myGame.stage.context.closePath();
myGame.stage.context.beginPath();
myGame.stage.context.fillStyle = 'rgb(0,0,255)';
myGame.stage.context.arc(p4.x, p4.y, 4, 0, Math.PI * 2);
myGame.stage.context.fill();
myGame.stage.context.closePath();
}
})();
+54
View File
@@ -0,0 +1,54 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var origin;
var origin2;
var points = [];
var points2 = [];
var d = 0;
var d2 = 0;
var m = 64;
function create() {
// Let's have some fun :)
origin = new Phaser.Point(300, 200);
origin2 = new Phaser.Point(600, 350);
for(var i = 0; i < m; i++) {
points.push(new Phaser.Point());
points2.push(new Phaser.Point());
}
}
function update() {
for(var i = 0; i < m; i++) {
points[i].rotate(origin.x, origin.y, myGame.math.wrapAngle(d + (i * (360 / m))), true, i * 5);
//points2[i].rotate(origin2.x, origin2.y, myGame.math.wrapAngle(d2 + (i * (360/m))), true, i * 10);
//points[i].rotate(origin.x, origin.y, myGame.math.wrapAngle(d + (i * (360/m))), true, 200);
points2[i].rotate(origin2.x, origin2.y, myGame.math.wrapAngle(d2 + (i * (360 / m))), true, 200);
}
d -= 2;
d2 += 2;
}
function render() {
// Render the shape
myGame.stage.context.save();
//myGame.stage.context.globalCompositeOperation = 'xor';
myGame.stage.context.globalCompositeOperation = 'lighter';
myGame.stage.context.lineWidth = 20;
for(var i = 0; i < m; i++) {
myGame.stage.context.beginPath();
myGame.stage.context.strokeStyle = 'rgba(255,' + Math.round(i * (255 / m)).toString() + ',0,1)';
myGame.stage.context.moveTo(origin.x, origin.y);
myGame.stage.context.lineTo(points[i].x, points[i].y);
myGame.stage.context.stroke();
myGame.stage.context.closePath();
}
for(var i = 0; i < m; i++) {
myGame.stage.context.beginPath();
myGame.stage.context.strokeStyle = 'rgba(0,' + Math.round(i * (255 / m)).toString() + ',255,1)';
myGame.stage.context.moveTo(origin2.x, origin2.y);
myGame.stage.context.lineTo(points2[i].x, points2[i].y);
myGame.stage.context.stroke();
myGame.stage.context.closePath();
}
myGame.stage.context.restore();
}
})();
+82
View File
@@ -0,0 +1,82 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var origin:Phaser.Point;
var origin2:Phaser.Point;
var points:Phaser.Point[] = [];
var points2:Phaser.Point[] = [];
var d: number = 0;
var d2: number = 0;
var m: number = 64;
function create() {
// Let's have some fun :)
origin = new Phaser.Point(300, 200);
origin2 = new Phaser.Point(600, 350);
for (var i = 0; i < m; i++)
{
points.push(new Phaser.Point());
points2.push(new Phaser.Point());
}
}
function update() {
for (var i = 0; i < m; i++)
{
points[i].rotate(origin.x, origin.y, myGame.math.wrapAngle(d + (i * (360/m))), true, i * 5);
//points2[i].rotate(origin2.x, origin2.y, myGame.math.wrapAngle(d2 + (i * (360/m))), true, i * 10);
//points[i].rotate(origin.x, origin.y, myGame.math.wrapAngle(d + (i * (360/m))), true, 200);
points2[i].rotate(origin2.x, origin2.y, myGame.math.wrapAngle(d2 + (i * (360/m))), true, 200);
}
d -= 2;
d2 += 2;
}
function render() {
// Render the shape
myGame.stage.context.save();
//myGame.stage.context.globalCompositeOperation = 'xor';
myGame.stage.context.globalCompositeOperation = 'lighter';
myGame.stage.context.lineWidth = 20;
for (var i = 0; i < m; i++)
{
myGame.stage.context.beginPath();
myGame.stage.context.strokeStyle = 'rgba(255,' + Math.round(i * (255/m)).toString() + ',0,1)';
myGame.stage.context.moveTo(origin.x, origin.y);
myGame.stage.context.lineTo(points[i].x, points[i].y);
myGame.stage.context.stroke();
myGame.stage.context.closePath();
}
for (var i = 0; i < m; i++)
{
myGame.stage.context.beginPath();
myGame.stage.context.strokeStyle = 'rgba(0,' + Math.round(i * (255/m)).toString() + ',255,1)';
myGame.stage.context.moveTo(origin2.x, origin2.y);
myGame.stage.context.lineTo(points2[i].x, points2[i].y);
myGame.stage.context.stroke();
myGame.stage.context.closePath();
}
myGame.stage.context.restore();
}
})();
+30
View File
@@ -0,0 +1,30 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var segment;
function create() {
myGame.verlet.friction = 1;
segment = myGame.verlet.createLineSegments([
new Phaser.Vector2(20, 10),
new Phaser.Vector2(40, 10),
new Phaser.Vector2(60, 10),
new Phaser.Vector2(80, 10),
new Phaser.Vector2(100, 10)
], 0.02);
segment.pin(0);
segment.pin(4);
var wheel = myGame.verlet.createTire(new Phaser.Vector2(200, 50), 100, 30, 0.3, 0.9);
var tire2 = myGame.verlet.createTire(new Phaser.Vector2(400, 50), 70, 7, 0.1, 0.2);
var cube = myGame.verlet.createTire(new Phaser.Vector2(600, 50), 70, 4, 1, 1);
var tri = myGame.verlet.createTire(new Phaser.Vector2(700, 50), 100, 3, 1, 1);
}
function update() {
}
function render() {
myGame.verlet.render();
//myGame.stage.context.fillStyle = 'rgb(255,255,0)';
//myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
//myGame.stage.context.fillStyle = 'rgb(255,0,0)';
//myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
}
})();
+39
View File
@@ -0,0 +1,39 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, null, create, update, render);
var segment: Phaser.Verlet.Composite;
function create() {
myGame.verlet.friction = 1;
segment = myGame.verlet.createLineSegments([new Phaser.Vector2(20, 10), new Phaser.Vector2(40, 10), new Phaser.Vector2(60, 10), new Phaser.Vector2(80, 10), new Phaser.Vector2(100, 10)], 0.02);
segment.pin(0);
segment.pin(4);
var wheel = myGame.verlet.createTire(new Phaser.Vector2(200,50), 100, 30, 0.3, 0.9);
var tire2 = myGame.verlet.createTire(new Phaser.Vector2(400,50), 70, 7, 0.1, 0.2);
var cube = myGame.verlet.createTire(new Phaser.Vector2(600,50), 70, 4, 1, 1);
var tri = myGame.verlet.createTire(new Phaser.Vector2(700,50), 100, 3, 1, 1);
}
function update() {
}
function render() {
myGame.verlet.render();
//myGame.stage.context.fillStyle = 'rgb(255,255,0)';
//myGame.stage.context.fillRect(p1.x, p1.y, 4, 4);
//myGame.stage.context.fillStyle = 'rgb(255,0,0)';
//myGame.stage.context.fillRect(p2.x, p2.y, 4, 4);
}
})();
+49
View File
@@ -0,0 +1,49 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
var cube;
var b1;
var b2;
var b3;
var b4;
function init() {
myGame.loader.addImageFile('ball0', 'assets/sprites/yellow_ball.png');
myGame.loader.addImageFile('ball1', 'assets/sprites/aqua_ball.png');
myGame.loader.addImageFile('ball2', 'assets/sprites/blue_ball.png');
myGame.loader.addImageFile('ball3', 'assets/sprites/green_ball.png');
myGame.loader.addImageFile('ball4', 'assets/sprites/red_ball.png');
myGame.loader.addImageFile('ball5', 'assets/sprites/purple_ball.png');
myGame.loader.load();
}
function create() {
myGame.verlet.friction = 1;
myGame.verlet.step = 32;
//var wheel = myGame.verlet.createTire(new Phaser.Vector2(200,50), 100, 30, 0.3, 0.9);
//var tire2 = myGame.verlet.createTire(new Phaser.Vector2(400,50), 70, 7, 0.1, 0.2);
cube = myGame.verlet.createTire(new Phaser.Vector2(300, 50), 100, 4, 1, 1);
//var tri = myGame.verlet.createTire(new Phaser.Vector2(700,50), 100, 3, 1, 1);
var dc = new Phaser.Verlet.DistanceConstraint(cube.particles[0], cube.particles[1], 1);
cube.constraints.push(dc);
var dc2 = new Phaser.Verlet.DistanceConstraint(cube.particles[1], cube.particles[2], 1);
cube.constraints.push(dc2);
var dc3 = new Phaser.Verlet.DistanceConstraint(cube.particles[2], cube.particles[3], 1);
cube.constraints.push(dc3);
b1 = myGame.createSprite(cube.particles[0].pos.x, cube.particles[0].pos.y, 'ball0');
b2 = myGame.createSprite(cube.particles[1].pos.x, cube.particles[1].pos.y, 'ball1');
b3 = myGame.createSprite(cube.particles[2].pos.x, cube.particles[2].pos.y, 'ball2');
b4 = myGame.createSprite(cube.particles[3].pos.x, cube.particles[3].pos.y, 'ball3');
}
function update() {
b1.x = cube.particles[0].pos.x - 8;
b1.y = cube.particles[0].pos.y - 8;
b2.x = cube.particles[1].pos.x - 8;
b2.y = cube.particles[1].pos.y - 8;
b3.x = cube.particles[2].pos.x - 8;
b3.y = cube.particles[2].pos.y - 8;
b4.x = cube.particles[3].pos.x - 8;
b4.y = cube.particles[3].pos.y - 8;
}
function render() {
myGame.verlet.render();
}
})();
+75
View File
@@ -0,0 +1,75 @@
/// <reference path="../../Phaser/Game.ts" />
(function () {
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update, render);
var cube: Phaser.Verlet.Composite;
var b1: Phaser.Sprite;
var b2: Phaser.Sprite;
var b3: Phaser.Sprite;
var b4: Phaser.Sprite;
function init() {
myGame.loader.addImageFile('ball0', 'assets/sprites/yellow_ball.png');
myGame.loader.addImageFile('ball1', 'assets/sprites/aqua_ball.png');
myGame.loader.addImageFile('ball2', 'assets/sprites/blue_ball.png');
myGame.loader.addImageFile('ball3', 'assets/sprites/green_ball.png');
myGame.loader.addImageFile('ball4', 'assets/sprites/red_ball.png');
myGame.loader.addImageFile('ball5', 'assets/sprites/purple_ball.png');
myGame.loader.load();
}
function create() {
myGame.verlet.friction = 1;
myGame.verlet.step = 32;
//var wheel = myGame.verlet.createTire(new Phaser.Vector2(200,50), 100, 30, 0.3, 0.9);
//var tire2 = myGame.verlet.createTire(new Phaser.Vector2(400,50), 70, 7, 0.1, 0.2);
cube = myGame.verlet.createTire(new Phaser.Vector2(300, 50), 100, 4, 1, 1);
//var tri = myGame.verlet.createTire(new Phaser.Vector2(700,50), 100, 3, 1, 1);
var dc: Phaser.Verlet.DistanceConstraint = new Phaser.Verlet.DistanceConstraint(cube.particles[0], cube.particles[1], 1);
cube.constraints.push(dc);
var dc2: Phaser.Verlet.DistanceConstraint = new Phaser.Verlet.DistanceConstraint(cube.particles[1], cube.particles[2], 1);
cube.constraints.push(dc2);
var dc3: Phaser.Verlet.DistanceConstraint = new Phaser.Verlet.DistanceConstraint(cube.particles[2], cube.particles[3], 1);
cube.constraints.push(dc3);
b1 = myGame.createSprite(cube.particles[0].pos.x, cube.particles[0].pos.y, 'ball0');
b2 = myGame.createSprite(cube.particles[1].pos.x, cube.particles[1].pos.y, 'ball1');
b3 = myGame.createSprite(cube.particles[2].pos.x, cube.particles[2].pos.y, 'ball2');
b4 = myGame.createSprite(cube.particles[3].pos.x, cube.particles[3].pos.y, 'ball3');
}
function update() {
b1.x = cube.particles[0].pos.x - 8;
b1.y = cube.particles[0].pos.y - 8;
b2.x = cube.particles[1].pos.x - 8;
b2.y = cube.particles[1].pos.y - 8;
b3.x = cube.particles[2].pos.x - 8;
b3.y = cube.particles[2].pos.y - 8;
b4.x = cube.particles[3].pos.x - 8;
b4.y = cube.particles[3].pos.y - 8;
}
function render() {
myGame.verlet.render();
}
})();
+740 -2
View File
@@ -3286,6 +3286,27 @@ var Phaser;
**/
function (length, angle) {
};
Point.prototype.rotate = /**
* Rotates the point around the x/y coordinates given to the desired angle
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
* @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
function (cx, cy, angle, asDegrees, distance) {
if (typeof asDegrees === "undefined") { asDegrees = false; }
if (typeof distance === "undefined") { distance = null; }
if(asDegrees) {
angle = angle * Phaser.GameMath.DEG_TO_RAD;
}
// Get distance from origin (cx/cy) to this point
if(distance === null) {
distance = Math.sqrt(((cx - this.x) * (cx - this.x)) + ((cy - this.y) * (cy - this.y)));
}
return this.setTo(cx + distance * Math.cos(angle), cy + distance * Math.sin(angle));
};
Point.prototype.setTo = /**
* Sets the x and y values of this Point object to the given coordinates.
* @method setTo
@@ -4081,7 +4102,7 @@ var Phaser;
* @param {Number} y The y coordinate of the top-left corner of the quad.
* @param {Number} width The width of the quad.
* @param {Number} height The height of the quad.
* @return {Quad } This object
* @return {Quad} This object
**/
function Quad(x, y, width, height) {
if (typeof x === "undefined") { x = 0; }
@@ -5290,7 +5311,6 @@ var Phaser;
continue;
}
if(QuadTree._object.collisionMask.checkHullIntersection(checkObject.collisionMask)) {
console.log('quad hull');
//Execute callback functions if they exist
if((QuadTree._processingCallback == null) || QuadTree._processingCallback(QuadTree._object, checkObject)) {
overlapProcessed = true;
@@ -7312,6 +7332,35 @@ var Phaser;
}
return array;
};
GameMath.distanceBetween = /**
* Returns the distance from this Point object to the given Point object.
* @method distanceFrom
* @param {Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
function distanceBetween(x1, y1, x2, y2) {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
};
GameMath.prototype.rotatePoint = /**
* Rotates a point around the x/y coordinates given to the desired angle
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param angle {number} The angle of the rotation in radians
* @param point {Point} The point object to perform the rotation on
* @return The modified point object
*/
function (x, y, angle, point) {
var s = Math.sin(angle);
var c = Math.cos(angle);
point.x -= x;
point.y -= y;
var newX = point.x * c - point.y * s;
var newY = point.x * s - point.y * c;
return point.setTo(newX + x, newY + y);
};
return GameMath;
})();
Phaser.GameMath = GameMath;
@@ -7330,6 +7379,19 @@ var Phaser;
function Group(game, MaxSize) {
if (typeof MaxSize === "undefined") { MaxSize = 0; }
_super.call(this, game);
/**
* You can set a globalCompositeOperation that will be applied before the render method is called on this Groups children.
* This is useful if you wish to apply an effect like 'lighten' to a whole group of children as it saves doing it one-by-one.
* If this value is set it will call a canvas context save and restore before and after the render pass.
* Set to null to disable.
*/
this.globalCompositeOperation = null;
/**
* You can set an alpha value on this Group that will be applied before the render method is called on this Groups children.
* This is useful if you wish to alpha a whole group of children as it saves doing it one-by-one.
* Set to 0 to disable.
*/
this.alpha = 0;
this.isGroup = true;
this.members = [];
this.length = 0;
@@ -7384,6 +7446,14 @@ var Phaser;
if(this.ignoreGlobalRender && forceRender == false) {
return;
}
if(this.globalCompositeOperation) {
this._game.stage.context.save();
this._game.stage.context.globalCompositeOperation = this.globalCompositeOperation;
}
if(this.alpha > 0) {
var prevAlpha = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
}
var basic;
var i = 0;
while(i < this.length) {
@@ -7392,6 +7462,12 @@ var Phaser;
basic.render(camera, cameraOffsetX, cameraOffsetY, forceRender);
}
}
if(this.alpha > 0) {
this._game.stage.context.globalAlpha = prevAlpha;
}
if(this.globalCompositeOperation) {
this._game.stage.context.restore();
}
};
Object.defineProperty(Group.prototype, "maxSize", {
get: /**
@@ -9286,6 +9362,9 @@ var Phaser;
this.canvas.style['ms-touch-action'] = 'none';
this.canvas.style['touch-action'] = 'none';
this.canvas.style.backgroundColor = 'rgb(0,0,0)';
this.canvas.oncontextmenu = function (event) {
event.preventDefault();
};
this.context = this.canvas.getContext('2d');
this.offset = this.getOffset(this.canvas);
this.bounds = new Phaser.Quad(this.offset.x, this.offset.y, width, height);
@@ -10278,6 +10357,661 @@ var Phaser;
})();
Phaser.TweenManager = TweenManager;
})(Phaser || (Phaser = {}));
/// <reference path="../Game.ts" />
/**
* Phaser - Vector2
*
* A simple 2-dimensional vector class. Based on the one included with verlet-js by Sub Protocol released under MIT
*/
var Phaser;
(function (Phaser) {
var Vector2 = (function () {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Vector2} This object
**/
function Vector2(x, y) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
this.x = x;
this.y = y;
}
Vector2.prototype.setTo = function (x, y) {
this.x = x;
this.y = y;
return this;
};
Vector2.prototype.add = function (v, output) {
if (typeof output === "undefined") { output = new Vector2(); }
return output.setTo(this.x + v.x, this.y + v.y);
};
Vector2.prototype.sub = function (v, output) {
if (typeof output === "undefined") { output = new Vector2(); }
return output.setTo(this.x - v.x, this.y - v.y);
};
Vector2.prototype.mul = function (v, output) {
if (typeof output === "undefined") { output = new Vector2(); }
return output.setTo(this.x * v.x, this.y * v.y);
};
Vector2.prototype.div = function (v, output) {
if (typeof output === "undefined") { output = new Vector2(); }
return output.setTo(this.x / v.x, this.y / v.y);
};
Vector2.prototype.scale = function (coef, output) {
if (typeof output === "undefined") { output = new Vector2(); }
return output.setTo(this.x * coef, this.y * coef);
};
Vector2.prototype.mutableSet = function (v) {
this.x = v.x;
this.y = v.y;
return this;
};
Vector2.prototype.mutableAdd = function (v) {
this.x += v.x;
this.y += v.y;
return this;
};
Vector2.prototype.mutableSub = function (v) {
this.x -= v.x;
this.y -= v.y;
return this;
};
Vector2.prototype.mutableMul = function (v) {
this.x *= v.x;
this.y *= v.y;
return this;
};
Vector2.prototype.mutableDiv = function (v) {
this.x /= v.x;
this.y /= v.y;
return this;
};
Vector2.prototype.mutableScale = function (coef) {
this.x *= coef;
this.y *= coef;
return this;
};
Vector2.prototype.equals = function (v) {
return this.x == v.x && this.y == v.y;
};
Vector2.prototype.epsilonEquals = function (v, epsilon) {
return Math.abs(this.x - v.x) <= epsilon && Math.abs(this.y - v.y) <= epsilon;
};
Vector2.prototype.length = function () {
return Math.sqrt(this.x * this.x + this.y * this.y);
};
Vector2.prototype.length2 = function () {
return this.x * this.x + this.y * this.y;
};
Vector2.prototype.dist = function (v) {
return Math.sqrt(this.dist2(v));
};
Vector2.prototype.dist2 = function (v) {
return ((v.x - this.x) * (v.x - this.x)) + ((v.y - this.y) * (v.y - this.y));
};
Vector2.prototype.normal = function (output) {
if (typeof output === "undefined") { output = new Vector2(); }
var m = Math.sqrt(this.x * this.x + this.y * this.y);
return output.setTo(this.x / m, this.y / m);
};
Vector2.prototype.dot = function (v) {
return this.x * v.x + this.y * v.y;
};
Vector2.prototype.angle = function (v) {
return Math.atan2(this.x * v.y - this.y * v.x, this.x * v.x + this.y * v.y);
};
Vector2.prototype.angle2 = function (vLeft, vRight) {
return vLeft.sub(this).angle(vRight.sub(this));
};
Vector2.prototype.rotate = function (origin, theta, output) {
if (typeof output === "undefined") { output = new Vector2(); }
var x = this.x - origin.x;
var y = this.y - origin.y;
return output.setTo(x * Math.cos(theta) - y * Math.sin(theta) + origin.x, x * Math.sin(theta) + y * Math.cos(theta) + origin.y);
};
Vector2.prototype.toString = /**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the object.
**/
function () {
return "[{Vector2 (x=" + this.x + " y=" + this.y + ")}]";
};
return Vector2;
})();
Phaser.Vector2 = Vector2;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="../Game.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - Verlet - Particle
*
*
*/
(function (Verlet) {
var Particle = (function () {
/**
* Creates a new Particle object.
* @class Particle
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Particle} This object
**/
function Particle(pos) {
this.pos = (new Phaser.Vector2()).mutableSet(pos);
this.lastPos = (new Phaser.Vector2()).mutableSet(pos);
}
Particle.prototype.render = function (ctx) {
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, 2, 0, 2 * Math.PI);
ctx.fillStyle = "#2dad8f";
ctx.fill();
};
return Particle;
})();
Verlet.Particle = Particle;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="../Game.ts" />
/// <reference path="Particle.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - PinConstraint
*
* Constrains to static / fixed point
*/
(function (Verlet) {
var PinConstraint = (function () {
/**
* Creates a new PinConstraint object.
* @class PinConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {PinConstraint} This object
**/
function PinConstraint(a, pos) {
this.a = a;
this.pos = (new Phaser.Vector2()).mutableSet(pos);
}
PinConstraint.prototype.relax = function () {
this.a.pos.mutableSet(this.pos);
};
PinConstraint.prototype.render = function (ctx) {
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, 6, 0, 2 * Math.PI);
ctx.fillStyle = "rgba(0,153,255,0.1)";
ctx.fill();
};
return PinConstraint;
})();
Verlet.PinConstraint = PinConstraint;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="../Game.ts" />
/// <reference path="../geom/Vector2.ts" />
/// <reference path="Particle.ts" />
/// <reference path="PinConstraint.ts" />
/**
* Phaser - Verlet - Composite
*
*
*/
(function (Verlet) {
var Composite = (function () {
/**
* Creates a new Composite object.
* @class Composite
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Composite} This object
**/
function Composite(game) {
this.drawParticles = null;
this.drawConstraints = null;
this._game = game;
this.particles = [];
this.constraints = [];
}
Composite.prototype.createDistanceConstraint = // Map sprites to particles
function (a, b, stiffness, distance) {
if (typeof distance === "undefined") { distance = null; }
this.constraints.push(new Phaser.Verlet.DistanceConstraint(a, b, stiffness, distance));
return this.constraints[this.constraints.length - 1];
};
Composite.prototype.createAngleConstraint = function (a, b, c, stiffness) {
this.constraints.push(new Phaser.Verlet.AngleConstraint(a, b, c, stiffness));
return this.constraints[this.constraints.length - 1];
};
Composite.prototype.createPinConstraint = function (a, pos) {
this.constraints.push(new Phaser.Verlet.PinConstraint(a, pos));
return this.constraints[this.constraints.length - 1];
};
Composite.prototype.pin = function (index, pos) {
if (typeof pos === "undefined") { pos = null; }
if(pos == null) {
pos = this.particles[index].pos;
}
var pc = new Phaser.Verlet.PinConstraint(this.particles[index], pos);
this.constraints.push(pc);
return pc;
};
return Composite;
})();
Verlet.Composite = Composite;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="../Game.ts" />
/// <reference path="Particle.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - DistanceConstraint
*
* Constrains to initial distance
*/
(function (Verlet) {
var DistanceConstraint = (function () {
/**
* Creates a new DistanceConstraint object.
* @class DistanceConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {DistanceConstraint} This object
**/
function DistanceConstraint(a, b, stiffness, distance) {
if (typeof distance === "undefined") { distance = null; }
this.a = a;
this.b = b;
if(distance === null) {
this.distance = a.pos.sub(b.pos).length();
} else {
this.distance = distance;
}
this.stiffness = stiffness;
}
DistanceConstraint.prototype.relax = function (stepCoef) {
var normal = this.a.pos.sub(this.b.pos);
var m = normal.length2();
normal.mutableScale(((this.distance * this.distance - m) / m) * this.stiffness * stepCoef);
this.a.pos.mutableAdd(normal);
this.b.pos.mutableSub(normal);
};
DistanceConstraint.prototype.render = function (ctx) {
ctx.beginPath();
ctx.moveTo(this.a.pos.x, this.a.pos.y);
ctx.lineTo(this.b.pos.x, this.b.pos.y);
ctx.strokeStyle = "#d8dde2";
ctx.stroke();
};
return DistanceConstraint;
})();
Verlet.DistanceConstraint = DistanceConstraint;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="../Game.ts" />
/// <reference path="Particle.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - AngleConstraint
*
* constrains 3 particles to an angle
*/
(function (Verlet) {
var AngleConstraint = (function () {
/**
* Creates a new AngleConstraint object.
* @class AngleConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {AngleConstraint} This object
**/
function AngleConstraint(a, b, c, stiffness) {
this.a = a;
this.b = b;
this.c = c;
this.angle = this.b.pos.angle2(this.a.pos, this.c.pos);
this.stiffness = stiffness;
}
AngleConstraint.prototype.relax = function (stepCoef) {
var angle = this.b.pos.angle2(this.a.pos, this.c.pos);
var diff = angle - this.angle;
if(diff <= -Math.PI) {
diff += 2 * Math.PI;
} else if(diff >= Math.PI) {
diff -= 2 * Math.PI;
}
diff *= stepCoef * this.stiffness;
this.a.pos = this.a.pos.rotate(this.b.pos, diff);
this.c.pos = this.c.pos.rotate(this.b.pos, -diff);
this.b.pos = this.b.pos.rotate(this.a.pos, diff);
this.b.pos = this.b.pos.rotate(this.c.pos, -diff);
};
AngleConstraint.prototype.render = function (ctx) {
ctx.beginPath();
ctx.moveTo(this.a.pos.x, this.a.pos.y);
ctx.lineTo(this.b.pos.x, this.b.pos.y);
ctx.lineTo(this.c.pos.x, this.c.pos.y);
var tmp = ctx.lineWidth;
ctx.lineWidth = 5;
ctx.strokeStyle = "rgba(255,255,0,0.2)";
ctx.stroke();
ctx.lineWidth = tmp;
};
return AngleConstraint;
})();
Verlet.AngleConstraint = AngleConstraint;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="Game.ts" />
/// <reference path="geom/Vector2.ts" />
/// <reference path="verlet/Composite.ts" />
/// <reference path="verlet/Particle.ts" />
/// <reference path="verlet/DistanceConstraint.ts" />
/// <reference path="verlet/PinConstraint.ts" />
/// <reference path="verlet/AngleConstraint.ts" />
/**
* Phaser - Verlet
*
* Based on verlet-js by Sub Protocol released under MIT
*/
(function (Verlet) {
var VerletManager = (function () {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Vector2} This object
**/
function VerletManager(game, width, height) {
this.composites = [];
this.step = 32;
this.selectionRadius = 20;
this.draggedEntity = null;
this.highlightColor = '#4f545c';
this.v = new Phaser.Vector2();
this._game = game;
this.width = width;
this.height = height;
this.gravity = new Phaser.Vector2(0, 0.2);
this.friction = 0.99;
this.groundFriction = 0.8;
this.canvas = game.stage.canvas;
this.context = game.stage.context;
this._game.input.onDown.add(this.mouseDownHandler, this);
this._game.input.onUp.add(this.mouseUpHandler, this);
}
VerletManager.prototype.intersectionTime = /**
* Computes time of intersection of a particle with a wall
*
* @param {Vec2} line wall's root position
* @param {Vec2} p particle's position
* @param {Vec2} dir walls's direction
* @param {Vec2} v particle's velocity
*/
function (wall, p, dir, v) {
if(dir.x != 0) {
var denominator = v.y - dir.y * v.x / dir.x;
if(denominator == 0) {
return undefined;
}// Movement is parallel to wall
var numerator = wall.y + dir.y * (p.x - wall.x) / dir.x - p.y;
return numerator / denominator;
} else {
if(v.x == 0) {
return undefined;
}// parallel again
var denominator = v.x;
var numerator = wall.x - p.x;
return numerator / denominator;
}
};
VerletManager.prototype.intersectionPoint = function (wall, p, dir, v) {
var t = this.intersectionTime(wall, p, dir, v);
return new Phaser.Vector2(p.x + v.x * t, p.y + v.y * t);
};
VerletManager.prototype.bounds = function (particle) {
this.v.mutableSet(particle.pos);
this.v.mutableSub(particle.lastPos);
if(particle.pos.y > this.height - 1) {
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, this.height - 1), particle.lastPos, new Phaser.Vector2(1, 0), this.v));
}
if(particle.pos.x < 0) {
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
}
if(particle.pos.x > this.width - 1) {
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(this.width - 1, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
}
};
VerletManager.prototype.OLDbounds = function (particle) {
if(particle.pos.y > this.height - 1) {
particle.pos.y = this.height - 1;
}
if(particle.pos.x < 0) {
var vx = particle.pos.x - particle.lastPos.x;
var vy = particle.pos.y - particle.lastPos.y;
if(vx == 0) {
particle.pos.x = 0;
} else {
var t = -particle.lastPos.x / vx;
particle.pos.x = particle.lastPos.x + t * vx;
particle.pos.y = particle.lastPos.y + t * vy;
}
}
if(particle.pos.x > this.width - 1) {
particle.pos.x = this.width - 1;
}
};
VerletManager.prototype.createPoint = function (pos) {
var composite = new Phaser.Verlet.Composite(this._game);
composite.particles.push(new Phaser.Verlet.Particle(pos));
this.composites.push(composite);
return composite;
};
VerletManager.prototype.createLineSegments = function (vertices, stiffness) {
var i;
var composite = new Phaser.Verlet.Composite(this._game);
for(i in vertices) {
composite.particles.push(new Phaser.Verlet.Particle(vertices[i]));
if(i > 0) {
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[i], composite.particles[i - 1], stiffness));
}
}
this.composites.push(composite);
return composite;
};
VerletManager.prototype.createCloth = function (origin, width, height, segments, pinMod, stiffness) {
var composite = new Phaser.Verlet.Composite(this._game);
var xStride = width / segments;
var yStride = height / segments;
var x, y;
for(y = 0; y < segments; ++y) {
for(x = 0; x < segments; ++x) {
var px = origin.x + x * xStride - width / 2 + xStride / 2;
var py = origin.y + y * yStride - height / 2 + yStride / 2;
composite.particles.push(new Phaser.Verlet.Particle(new Phaser.Vector2(px, py)));
if(x > 0) {
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[y * segments + x - 1], stiffness));
}
if(y > 0) {
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[(y - 1) * segments + x], stiffness));
}
}
}
for(x = 0; x < segments; ++x) {
if(x % pinMod == 0) {
composite.pin(x);
}
}
this.composites.push(composite);
return composite;
};
VerletManager.prototype.createTire = function (origin, radius, segments, spokeStiffness, treadStiffness) {
var stride = (2 * Math.PI) / segments;
var i;
var composite = new Phaser.Verlet.Composite(this._game);
// particles
for(i = 0; i < segments; ++i) {
var theta = i * stride;
composite.particles.push(new Verlet.Particle(new Phaser.Vector2(origin.x + Math.cos(theta) * radius, origin.y + Math.sin(theta) * radius)));
}
var center = new Verlet.Particle(origin);
composite.particles.push(center);
// constraints
for(i = 0; i < segments; ++i) {
composite.constraints.push(new Verlet.DistanceConstraint(composite.particles[i], composite.particles[(i + 1) % segments], treadStiffness));
composite.constraints.push(new Verlet.DistanceConstraint(composite.particles[i], center, spokeStiffness));
composite.constraints.push(new Verlet.DistanceConstraint(composite.particles[i], composite.particles[(i + 5) % segments], treadStiffness));
}
this.composites.push(composite);
return composite;
};
VerletManager.prototype.update = function () {
if(this.composites.length == 0) {
return;
}
var i, j, c;
for(c in this.composites) {
for(i in this.composites[c].particles) {
var particles = this.composites[c].particles;
// calculate velocity
var velocity = particles[i].pos.sub(particles[i].lastPos).scale(this.friction);
// ground friction
if(particles[i].pos.y >= this.height - 1 && velocity.length2() > 0.000001) {
var m = velocity.length();
velocity.x /= m;
velocity.y /= m;
velocity.mutableScale(m * this.groundFriction);
}
// save last good state
particles[i].lastPos.mutableSet(particles[i].pos);
// gravity
particles[i].pos.mutableAdd(this.gravity);
// inertia
particles[i].pos.mutableAdd(velocity);
}
}
// handle dragging of entities
if(this.draggedEntity) {
this.draggedEntity.pos.mutableSet(new Phaser.Vector2(this._game.input.x, this._game.input.y));
}
// relax
var stepCoef = 1 / this.step;
for(c in this.composites) {
var constraints = this.composites[c].constraints;
for(i = 0; i < this.step; ++i) {
for(j in constraints) {
constraints[j].relax(stepCoef);
}
}
}
// bounds checking
for(c in this.composites) {
var particles = this.composites[c].particles;
for(i in particles) {
this.bounds(particles[i]);
}
}
};
VerletManager.prototype.mouseDownHandler = function () {
var nearest = this.nearestEntity();
if(nearest) {
this.draggedEntity = nearest;
}
};
VerletManager.prototype.mouseUpHandler = function () {
this.draggedEntity = null;
};
VerletManager.prototype.nearestEntity = function () {
var c, i;
var d2Nearest = 0;
var entity = null;
var constraintsNearest = null;
// find nearest point
for(c in this.composites) {
var particles = this.composites[c].particles;
for(i in particles) {
var d2 = particles[i].pos.dist2(new Phaser.Vector2(this._game.input.x, this._game.input.y));
if(d2 <= this.selectionRadius * this.selectionRadius && (entity == null || d2 < d2Nearest)) {
entity = particles[i];
constraintsNearest = this.composites[c].constraints;
d2Nearest = d2;
}
}
}
// search for pinned constraints for this entity
for(i in constraintsNearest) {
if(constraintsNearest[i] instanceof Verlet.PinConstraint && constraintsNearest[i].a == entity) {
entity = constraintsNearest[i];
}
}
return entity;
};
VerletManager.prototype.render = function () {
var i, c;
for(c in this.composites) {
// draw constraints
if(this.composites[c].drawConstraints) {
this.composites[c].drawConstraints(this.context, this.composites[c]);
} else {
var constraints = this.composites[c].constraints;
for(i in constraints) {
constraints[i].render(this.context);
}
}
// draw particles
if(this.composites[c].drawParticles) {
this.composites[c].drawParticles(this.context, this.composites[c]);
} else {
var particles = this.composites[c].particles;
for(i in particles) {
particles[i].render(this.context);
}
}
}
// highlight nearest / dragged entity
var nearest = this.draggedEntity || this.nearestEntity();
if(nearest) {
this.context.beginPath();
this.context.arc(nearest.pos.x, nearest.pos.y, 8, 0, 2 * Math.PI);
this.context.strokeStyle = this.highlightColor;
this.context.stroke();
}
};
return VerletManager;
})();
Verlet.VerletManager = VerletManager;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
/// <reference path="Game.ts" />
/**
* Phaser - World
@@ -14847,7 +15581,9 @@ var Phaser;
/// <reference path="Stage.ts" />
/// <reference path="Time.ts" />
/// <reference path="TweenManager.ts" />
/// <reference path="VerletManager.ts" />
/// <reference path="World.ts" />
/// <reference path="geom/Vector2.ts" />
/// <reference path="system/Device.ts" />
/// <reference path="system/RandomDataGenerator.ts" />
/// <reference path="system/RequestAnimationFrame.ts" />
@@ -15025,6 +15761,7 @@ var Phaser;
this.rnd = new Phaser.RandomDataGenerator([
(Date.now() * Math.random()).toString()
]);
this.verlet = new Phaser.Verlet.VerletManager(this, width, height);
this.framerate = 60;
this.isBooted = true;
this.input.start();
@@ -15075,6 +15812,7 @@ var Phaser;
this.tweens.update();
this.input.update();
this.stage.update();
this.verlet.update();
this._accumulator += this.time.delta;
if(this._accumulator > this._maxAccumulation) {
this._accumulator = this._maxAccumulation;
+3
View File
@@ -21,6 +21,9 @@
emitter = myGame.createEmitter(myGame.stage.centerX + 16, myGame.stage.centerY + 12);
emitter.makeParticles('jet', 250, false, 0);
emitter.setRotation(0, 0);
// Looks like a smoke trail!
//emitter.globalCompositeOperation = 'xor';
emitter.globalCompositeOperation = 'lighter';
bullets = myGame.createGroup(50);
// Create our bullet pool
for(var i = 0; i < 50; i++) {
+6
View File
@@ -33,6 +33,12 @@
emitter.makeParticles('jet', 250, false, 0);
emitter.setRotation(0, 0);
// Looks like a smoke trail!
//emitter.globalCompositeOperation = 'xor';
// Looks way cool :)
emitter.globalCompositeOperation = 'lighter';
bullets = myGame.createGroup(50);
// Create our bullet pool
+288 -14
View File
@@ -2071,6 +2071,16 @@ module Phaser {
**/
public polar(length, angle): void;
/**
* Rotates the point around the x/y coordinates given to the desired angle
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
* @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
public rotate(cx: number, cy: number, angle: number, asDegrees?: bool, distance?: number): Point;
/**
* Sets the x and y values of this Point object to the given coordinates.
* @method setTo
* @param {Number} x - The horizontal position of this point.
@@ -2578,7 +2588,7 @@ module Phaser {
* @param {Number} y The y coordinate of the top-left corner of the quad.
* @param {Number} width The width of the quad.
* @param {Number} height The height of the quad.
* @return {Quad } This object
* @return {Quad} This object
**/
constructor(x?: number, y?: number, width?: number, height?: number);
public x: number;
@@ -4250,6 +4260,23 @@ module Phaser {
* @return The array
*/
public shuffleArray(array);
/**
* Returns the distance from this Point object to the given Point object.
* @method distanceFrom
* @param {Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
static distanceBetween(x1: number, y1: number, x2: number, y2: number): number;
/**
* Rotates a point around the x/y coordinates given to the desired angle
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param angle {number} The angle of the rotation in radians
* @param point {Point} The point object to perform the rotation on
* @return The modified point object
*/
public rotatePoint(x: number, y: number, angle: number, point);
}
}
/**
@@ -4261,6 +4288,23 @@ module Phaser {
class Group extends Basic {
constructor(game: Game, MaxSize?: number);
/**
* Internal tracker for the maximum capacity of the group.
* Default is 0, or no max capacity.
*/
private _maxSize;
/**
* Internal helper variable for recycling objects a la <code>Emitter</code>.
*/
private _marker;
/**
* Helper for sort.
*/
private _sortIndex;
/**
* Helper for sort.
*/
private _sortOrder;
/**
* Use with <code>sort()</code> to sort in ascending order.
*/
static ASCENDING: number;
@@ -4279,22 +4323,18 @@ module Phaser {
*/
public length: number;
/**
* Internal tracker for the maximum capacity of the group.
* Default is 0, or no max capacity.
* You can set a globalCompositeOperation that will be applied before the render method is called on this Groups children.
* This is useful if you wish to apply an effect like 'lighten' to a whole group of children as it saves doing it one-by-one.
* If this value is set it will call a canvas context save and restore before and after the render pass.
* Set to null to disable.
*/
private _maxSize;
public globalCompositeOperation: string;
/**
* Internal helper variable for recycling objects a la <code>Emitter</code>.
* You can set an alpha value on this Group that will be applied before the render method is called on this Groups children.
* This is useful if you wish to alpha a whole group of children as it saves doing it one-by-one.
* Set to 0 to disable.
*/
private _marker;
/**
* Helper for sort.
*/
private _sortIndex;
/**
* Helper for sort.
*/
private _sortOrder;
public alpha: number;
/**
* Override this function to handle any deleting or "shutdown" type operations you might need,
* such as removing traditional Flash children like Basic objects.
@@ -5731,6 +5771,235 @@ module Phaser {
}
}
/**
* Phaser - Vector2
*
* A simple 2-dimensional vector class. Based on the one included with verlet-js by Sub Protocol released under MIT
*/
module Phaser {
class Vector2 {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Vector2} This object
**/
constructor(x?: number, y?: number);
public x: number;
public y: number;
public setTo(x: number, y: number): Vector2;
public add(v: Vector2, output?: Vector2): Vector2;
public sub(v: Vector2, output?: Vector2): Vector2;
public mul(v: Vector2, output?: Vector2): Vector2;
public div(v: Vector2, output?: Vector2): Vector2;
public scale(coef: number, output?: Vector2): Vector2;
public mutableSet(v: Vector2): Vector2;
public mutableAdd(v: Vector2): Vector2;
public mutableSub(v: Vector2): Vector2;
public mutableMul(v: Vector2): Vector2;
public mutableDiv(v: Vector2): Vector2;
public mutableScale(coef: number): Vector2;
public equals(v: Vector2): bool;
public epsilonEquals(v: Vector2, epsilon: number): bool;
public length(): number;
public length2(): number;
public dist(v: Vector2): number;
public dist2(v: Vector2): number;
public normal(output?: Vector2): Vector2;
public dot(v: Vector2): number;
public angle(v: Vector2): number;
public angle2(vLeft: Vector2, vRight: Vector2): number;
public rotate(origin, theta, output?: Vector2): Vector2;
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the object.
**/
public toString(): string;
}
}
/**
* Phaser - Verlet - Particle
*
*
*/
module Phaser.Verlet {
class Particle {
/**
* Creates a new Particle object.
* @class Particle
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Particle} This object
**/
constructor(pos: Vector2);
public pos: Vector2;
public lastPos: Vector2;
public render(ctx): void;
}
}
/**
* Phaser - PinConstraint
*
* Constrains to static / fixed point
*/
module Phaser.Verlet {
class PinConstraint {
/**
* Creates a new PinConstraint object.
* @class PinConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {PinConstraint} This object
**/
constructor(a: Particle, pos: Vector2);
public a: Particle;
public pos: Vector2;
public relax(): void;
public render(ctx): void;
}
}
/**
* Phaser - Verlet - Composite
*
*
*/
module Phaser.Verlet {
class Composite {
/**
* Creates a new Composite object.
* @class Composite
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Composite} This object
**/
constructor(game: Game);
private _game;
public particles: Particle[];
public constraints;
public drawParticles;
public drawConstraints;
public createDistanceConstraint(a: Particle, b: Particle, stiffness: number, distance?: number): DistanceConstraint;
public createAngleConstraint(a: Particle, b: Particle, c: Particle, stiffness: number): AngleConstraint;
public createPinConstraint(a: Particle, pos: Vector2): PinConstraint;
public pin(index, pos?): PinConstraint;
}
}
/**
* Phaser - DistanceConstraint
*
* Constrains to initial distance
*/
module Phaser.Verlet {
class DistanceConstraint {
/**
* Creates a new DistanceConstraint object.
* @class DistanceConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {DistanceConstraint} This object
**/
constructor(a: Particle, b: Particle, stiffness: number, distance?: number);
public a: Particle;
public b: Particle;
public distance: number;
public stiffness: number;
public relax(stepCoef: number): void;
public render(ctx): void;
}
}
/**
* Phaser - AngleConstraint
*
* constrains 3 particles to an angle
*/
module Phaser.Verlet {
class AngleConstraint {
/**
* Creates a new AngleConstraint object.
* @class AngleConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {AngleConstraint} This object
**/
constructor(a: Particle, b: Particle, c: Particle, stiffness: number);
public a: Particle;
public b: Particle;
public c: Particle;
public angle: number;
public stiffness: number;
public relax(stepCoef: number): void;
public render(ctx): void;
}
}
/**
* Phaser - Verlet
*
* Based on verlet-js by Sub Protocol released under MIT
*/
module Phaser.Verlet {
class VerletManager {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Vector2} This object
**/
constructor(game: Game, width: number, height: number);
private _game;
public composites: any[];
public width: number;
public height: number;
public step: number;
public gravity: Vector2;
public friction: number;
public groundFriction: number;
public selectionRadius: number;
public draggedEntity;
public highlightColor: string;
/**
* This class is actually a wrapper of canvas.
* @type {HTMLCanvasElement}
*/
public canvas: HTMLCanvasElement;
/**
* Canvas context of this object.
* @type {CanvasRenderingContext2D}
*/
public context: CanvasRenderingContext2D;
/**
* Computes time of intersection of a particle with a wall
*
* @param {Vec2} line wall's root position
* @param {Vec2} p particle's position
* @param {Vec2} dir walls's direction
* @param {Vec2} v particle's velocity
*/
public intersectionTime(wall, p, dir, v): number;
public intersectionPoint(wall, p, dir, v): Vector2;
private v;
public bounds(particle: Particle): void;
public OLDbounds(particle: Particle): void;
public createPoint(pos: Vector2): Composite;
public createLineSegments(vertices, stiffness): Composite;
public createCloth(origin, width, height, segments, pinMod, stiffness): Composite;
public createTire(origin, radius, segments, spokeStiffness, treadStiffness): Composite;
public update(): void;
private mouseDownHandler();
private mouseUpHandler();
public nearestEntity();
public render(): void;
}
}
/**
* Phaser - World
*
* "This world is but a canvas to our imagination." - Henry David Thoreau
@@ -8590,6 +8859,11 @@ module Phaser {
*/
public tweens: TweenManager;
/**
* Reference to the verlet manager.
* @type {VerletManager}
*/
public verlet: Verlet.VerletManager;
/**
* Reference to the world.
* @type {World}
*/
+740 -2
View File
@@ -3286,6 +3286,27 @@ var Phaser;
**/
function (length, angle) {
};
Point.prototype.rotate = /**
* Rotates the point around the x/y coordinates given to the desired angle
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)?
* @param {Number} distance An optional distance constraint between the point and the anchor
* @return The modified point object
*/
function (cx, cy, angle, asDegrees, distance) {
if (typeof asDegrees === "undefined") { asDegrees = false; }
if (typeof distance === "undefined") { distance = null; }
if(asDegrees) {
angle = angle * Phaser.GameMath.DEG_TO_RAD;
}
// Get distance from origin (cx/cy) to this point
if(distance === null) {
distance = Math.sqrt(((cx - this.x) * (cx - this.x)) + ((cy - this.y) * (cy - this.y)));
}
return this.setTo(cx + distance * Math.cos(angle), cy + distance * Math.sin(angle));
};
Point.prototype.setTo = /**
* Sets the x and y values of this Point object to the given coordinates.
* @method setTo
@@ -4081,7 +4102,7 @@ var Phaser;
* @param {Number} y The y coordinate of the top-left corner of the quad.
* @param {Number} width The width of the quad.
* @param {Number} height The height of the quad.
* @return {Quad } This object
* @return {Quad} This object
**/
function Quad(x, y, width, height) {
if (typeof x === "undefined") { x = 0; }
@@ -5290,7 +5311,6 @@ var Phaser;
continue;
}
if(QuadTree._object.collisionMask.checkHullIntersection(checkObject.collisionMask)) {
console.log('quad hull');
//Execute callback functions if they exist
if((QuadTree._processingCallback == null) || QuadTree._processingCallback(QuadTree._object, checkObject)) {
overlapProcessed = true;
@@ -7312,6 +7332,35 @@ var Phaser;
}
return array;
};
GameMath.distanceBetween = /**
* Returns the distance from this Point object to the given Point object.
* @method distanceFrom
* @param {Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
function distanceBetween(x1, y1, x2, y2) {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
};
GameMath.prototype.rotatePoint = /**
* Rotates a point around the x/y coordinates given to the desired angle
* @param x {number} The x coordinate of the anchor point
* @param y {number} The y coordinate of the anchor point
* @param angle {number} The angle of the rotation in radians
* @param point {Point} The point object to perform the rotation on
* @return The modified point object
*/
function (x, y, angle, point) {
var s = Math.sin(angle);
var c = Math.cos(angle);
point.x -= x;
point.y -= y;
var newX = point.x * c - point.y * s;
var newY = point.x * s - point.y * c;
return point.setTo(newX + x, newY + y);
};
return GameMath;
})();
Phaser.GameMath = GameMath;
@@ -7330,6 +7379,19 @@ var Phaser;
function Group(game, MaxSize) {
if (typeof MaxSize === "undefined") { MaxSize = 0; }
_super.call(this, game);
/**
* You can set a globalCompositeOperation that will be applied before the render method is called on this Groups children.
* This is useful if you wish to apply an effect like 'lighten' to a whole group of children as it saves doing it one-by-one.
* If this value is set it will call a canvas context save and restore before and after the render pass.
* Set to null to disable.
*/
this.globalCompositeOperation = null;
/**
* You can set an alpha value on this Group that will be applied before the render method is called on this Groups children.
* This is useful if you wish to alpha a whole group of children as it saves doing it one-by-one.
* Set to 0 to disable.
*/
this.alpha = 0;
this.isGroup = true;
this.members = [];
this.length = 0;
@@ -7384,6 +7446,14 @@ var Phaser;
if(this.ignoreGlobalRender && forceRender == false) {
return;
}
if(this.globalCompositeOperation) {
this._game.stage.context.save();
this._game.stage.context.globalCompositeOperation = this.globalCompositeOperation;
}
if(this.alpha > 0) {
var prevAlpha = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
}
var basic;
var i = 0;
while(i < this.length) {
@@ -7392,6 +7462,12 @@ var Phaser;
basic.render(camera, cameraOffsetX, cameraOffsetY, forceRender);
}
}
if(this.alpha > 0) {
this._game.stage.context.globalAlpha = prevAlpha;
}
if(this.globalCompositeOperation) {
this._game.stage.context.restore();
}
};
Object.defineProperty(Group.prototype, "maxSize", {
get: /**
@@ -9286,6 +9362,9 @@ var Phaser;
this.canvas.style['ms-touch-action'] = 'none';
this.canvas.style['touch-action'] = 'none';
this.canvas.style.backgroundColor = 'rgb(0,0,0)';
this.canvas.oncontextmenu = function (event) {
event.preventDefault();
};
this.context = this.canvas.getContext('2d');
this.offset = this.getOffset(this.canvas);
this.bounds = new Phaser.Quad(this.offset.x, this.offset.y, width, height);
@@ -10278,6 +10357,661 @@ var Phaser;
})();
Phaser.TweenManager = TweenManager;
})(Phaser || (Phaser = {}));
/// <reference path="../Game.ts" />
/**
* Phaser - Vector2
*
* A simple 2-dimensional vector class. Based on the one included with verlet-js by Sub Protocol released under MIT
*/
var Phaser;
(function (Phaser) {
var Vector2 = (function () {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Vector2} This object
**/
function Vector2(x, y) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
this.x = x;
this.y = y;
}
Vector2.prototype.setTo = function (x, y) {
this.x = x;
this.y = y;
return this;
};
Vector2.prototype.add = function (v, output) {
if (typeof output === "undefined") { output = new Vector2(); }
return output.setTo(this.x + v.x, this.y + v.y);
};
Vector2.prototype.sub = function (v, output) {
if (typeof output === "undefined") { output = new Vector2(); }
return output.setTo(this.x - v.x, this.y - v.y);
};
Vector2.prototype.mul = function (v, output) {
if (typeof output === "undefined") { output = new Vector2(); }
return output.setTo(this.x * v.x, this.y * v.y);
};
Vector2.prototype.div = function (v, output) {
if (typeof output === "undefined") { output = new Vector2(); }
return output.setTo(this.x / v.x, this.y / v.y);
};
Vector2.prototype.scale = function (coef, output) {
if (typeof output === "undefined") { output = new Vector2(); }
return output.setTo(this.x * coef, this.y * coef);
};
Vector2.prototype.mutableSet = function (v) {
this.x = v.x;
this.y = v.y;
return this;
};
Vector2.prototype.mutableAdd = function (v) {
this.x += v.x;
this.y += v.y;
return this;
};
Vector2.prototype.mutableSub = function (v) {
this.x -= v.x;
this.y -= v.y;
return this;
};
Vector2.prototype.mutableMul = function (v) {
this.x *= v.x;
this.y *= v.y;
return this;
};
Vector2.prototype.mutableDiv = function (v) {
this.x /= v.x;
this.y /= v.y;
return this;
};
Vector2.prototype.mutableScale = function (coef) {
this.x *= coef;
this.y *= coef;
return this;
};
Vector2.prototype.equals = function (v) {
return this.x == v.x && this.y == v.y;
};
Vector2.prototype.epsilonEquals = function (v, epsilon) {
return Math.abs(this.x - v.x) <= epsilon && Math.abs(this.y - v.y) <= epsilon;
};
Vector2.prototype.length = function () {
return Math.sqrt(this.x * this.x + this.y * this.y);
};
Vector2.prototype.length2 = function () {
return this.x * this.x + this.y * this.y;
};
Vector2.prototype.dist = function (v) {
return Math.sqrt(this.dist2(v));
};
Vector2.prototype.dist2 = function (v) {
return ((v.x - this.x) * (v.x - this.x)) + ((v.y - this.y) * (v.y - this.y));
};
Vector2.prototype.normal = function (output) {
if (typeof output === "undefined") { output = new Vector2(); }
var m = Math.sqrt(this.x * this.x + this.y * this.y);
return output.setTo(this.x / m, this.y / m);
};
Vector2.prototype.dot = function (v) {
return this.x * v.x + this.y * v.y;
};
Vector2.prototype.angle = function (v) {
return Math.atan2(this.x * v.y - this.y * v.x, this.x * v.x + this.y * v.y);
};
Vector2.prototype.angle2 = function (vLeft, vRight) {
return vLeft.sub(this).angle(vRight.sub(this));
};
Vector2.prototype.rotate = function (origin, theta, output) {
if (typeof output === "undefined") { output = new Vector2(); }
var x = this.x - origin.x;
var y = this.y - origin.y;
return output.setTo(x * Math.cos(theta) - y * Math.sin(theta) + origin.x, x * Math.sin(theta) + y * Math.cos(theta) + origin.y);
};
Vector2.prototype.toString = /**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the object.
**/
function () {
return "[{Vector2 (x=" + this.x + " y=" + this.y + ")}]";
};
return Vector2;
})();
Phaser.Vector2 = Vector2;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="../Game.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - Verlet - Particle
*
*
*/
(function (Verlet) {
var Particle = (function () {
/**
* Creates a new Particle object.
* @class Particle
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Particle} This object
**/
function Particle(pos) {
this.pos = (new Phaser.Vector2()).mutableSet(pos);
this.lastPos = (new Phaser.Vector2()).mutableSet(pos);
}
Particle.prototype.render = function (ctx) {
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, 2, 0, 2 * Math.PI);
ctx.fillStyle = "#2dad8f";
ctx.fill();
};
return Particle;
})();
Verlet.Particle = Particle;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="../Game.ts" />
/// <reference path="Particle.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - PinConstraint
*
* Constrains to static / fixed point
*/
(function (Verlet) {
var PinConstraint = (function () {
/**
* Creates a new PinConstraint object.
* @class PinConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {PinConstraint} This object
**/
function PinConstraint(a, pos) {
this.a = a;
this.pos = (new Phaser.Vector2()).mutableSet(pos);
}
PinConstraint.prototype.relax = function () {
this.a.pos.mutableSet(this.pos);
};
PinConstraint.prototype.render = function (ctx) {
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, 6, 0, 2 * Math.PI);
ctx.fillStyle = "rgba(0,153,255,0.1)";
ctx.fill();
};
return PinConstraint;
})();
Verlet.PinConstraint = PinConstraint;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="../Game.ts" />
/// <reference path="../geom/Vector2.ts" />
/// <reference path="Particle.ts" />
/// <reference path="PinConstraint.ts" />
/**
* Phaser - Verlet - Composite
*
*
*/
(function (Verlet) {
var Composite = (function () {
/**
* Creates a new Composite object.
* @class Composite
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Composite} This object
**/
function Composite(game) {
this.drawParticles = null;
this.drawConstraints = null;
this._game = game;
this.particles = [];
this.constraints = [];
}
Composite.prototype.createDistanceConstraint = // Map sprites to particles
function (a, b, stiffness, distance) {
if (typeof distance === "undefined") { distance = null; }
this.constraints.push(new Phaser.Verlet.DistanceConstraint(a, b, stiffness, distance));
return this.constraints[this.constraints.length - 1];
};
Composite.prototype.createAngleConstraint = function (a, b, c, stiffness) {
this.constraints.push(new Phaser.Verlet.AngleConstraint(a, b, c, stiffness));
return this.constraints[this.constraints.length - 1];
};
Composite.prototype.createPinConstraint = function (a, pos) {
this.constraints.push(new Phaser.Verlet.PinConstraint(a, pos));
return this.constraints[this.constraints.length - 1];
};
Composite.prototype.pin = function (index, pos) {
if (typeof pos === "undefined") { pos = null; }
if(pos == null) {
pos = this.particles[index].pos;
}
var pc = new Phaser.Verlet.PinConstraint(this.particles[index], pos);
this.constraints.push(pc);
return pc;
};
return Composite;
})();
Verlet.Composite = Composite;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="../Game.ts" />
/// <reference path="Particle.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - DistanceConstraint
*
* Constrains to initial distance
*/
(function (Verlet) {
var DistanceConstraint = (function () {
/**
* Creates a new DistanceConstraint object.
* @class DistanceConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {DistanceConstraint} This object
**/
function DistanceConstraint(a, b, stiffness, distance) {
if (typeof distance === "undefined") { distance = null; }
this.a = a;
this.b = b;
if(distance === null) {
this.distance = a.pos.sub(b.pos).length();
} else {
this.distance = distance;
}
this.stiffness = stiffness;
}
DistanceConstraint.prototype.relax = function (stepCoef) {
var normal = this.a.pos.sub(this.b.pos);
var m = normal.length2();
normal.mutableScale(((this.distance * this.distance - m) / m) * this.stiffness * stepCoef);
this.a.pos.mutableAdd(normal);
this.b.pos.mutableSub(normal);
};
DistanceConstraint.prototype.render = function (ctx) {
ctx.beginPath();
ctx.moveTo(this.a.pos.x, this.a.pos.y);
ctx.lineTo(this.b.pos.x, this.b.pos.y);
ctx.strokeStyle = "#d8dde2";
ctx.stroke();
};
return DistanceConstraint;
})();
Verlet.DistanceConstraint = DistanceConstraint;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="../Game.ts" />
/// <reference path="Particle.ts" />
/// <reference path="../geom/Vector2.ts" />
/**
* Phaser - AngleConstraint
*
* constrains 3 particles to an angle
*/
(function (Verlet) {
var AngleConstraint = (function () {
/**
* Creates a new AngleConstraint object.
* @class AngleConstraint
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {AngleConstraint} This object
**/
function AngleConstraint(a, b, c, stiffness) {
this.a = a;
this.b = b;
this.c = c;
this.angle = this.b.pos.angle2(this.a.pos, this.c.pos);
this.stiffness = stiffness;
}
AngleConstraint.prototype.relax = function (stepCoef) {
var angle = this.b.pos.angle2(this.a.pos, this.c.pos);
var diff = angle - this.angle;
if(diff <= -Math.PI) {
diff += 2 * Math.PI;
} else if(diff >= Math.PI) {
diff -= 2 * Math.PI;
}
diff *= stepCoef * this.stiffness;
this.a.pos = this.a.pos.rotate(this.b.pos, diff);
this.c.pos = this.c.pos.rotate(this.b.pos, -diff);
this.b.pos = this.b.pos.rotate(this.a.pos, diff);
this.b.pos = this.b.pos.rotate(this.c.pos, -diff);
};
AngleConstraint.prototype.render = function (ctx) {
ctx.beginPath();
ctx.moveTo(this.a.pos.x, this.a.pos.y);
ctx.lineTo(this.b.pos.x, this.b.pos.y);
ctx.lineTo(this.c.pos.x, this.c.pos.y);
var tmp = ctx.lineWidth;
ctx.lineWidth = 5;
ctx.strokeStyle = "rgba(255,255,0,0.2)";
ctx.stroke();
ctx.lineWidth = tmp;
};
return AngleConstraint;
})();
Verlet.AngleConstraint = AngleConstraint;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// <reference path="Game.ts" />
/// <reference path="geom/Vector2.ts" />
/// <reference path="verlet/Composite.ts" />
/// <reference path="verlet/Particle.ts" />
/// <reference path="verlet/DistanceConstraint.ts" />
/// <reference path="verlet/PinConstraint.ts" />
/// <reference path="verlet/AngleConstraint.ts" />
/**
* Phaser - Verlet
*
* Based on verlet-js by Sub Protocol released under MIT
*/
(function (Verlet) {
var VerletManager = (function () {
/**
* Creates a new Vector2 object.
* @class Vector2
* @constructor
* @param {Number} x The x coordinate of vector2
* @param {Number} y The y coordinate of vector2
* @return {Vector2} This object
**/
function VerletManager(game, width, height) {
this.composites = [];
this.step = 32;
this.selectionRadius = 20;
this.draggedEntity = null;
this.highlightColor = '#4f545c';
this.v = new Phaser.Vector2();
this._game = game;
this.width = width;
this.height = height;
this.gravity = new Phaser.Vector2(0, 0.2);
this.friction = 0.99;
this.groundFriction = 0.8;
this.canvas = game.stage.canvas;
this.context = game.stage.context;
this._game.input.onDown.add(this.mouseDownHandler, this);
this._game.input.onUp.add(this.mouseUpHandler, this);
}
VerletManager.prototype.intersectionTime = /**
* Computes time of intersection of a particle with a wall
*
* @param {Vec2} line wall's root position
* @param {Vec2} p particle's position
* @param {Vec2} dir walls's direction
* @param {Vec2} v particle's velocity
*/
function (wall, p, dir, v) {
if(dir.x != 0) {
var denominator = v.y - dir.y * v.x / dir.x;
if(denominator == 0) {
return undefined;
}// Movement is parallel to wall
var numerator = wall.y + dir.y * (p.x - wall.x) / dir.x - p.y;
return numerator / denominator;
} else {
if(v.x == 0) {
return undefined;
}// parallel again
var denominator = v.x;
var numerator = wall.x - p.x;
return numerator / denominator;
}
};
VerletManager.prototype.intersectionPoint = function (wall, p, dir, v) {
var t = this.intersectionTime(wall, p, dir, v);
return new Phaser.Vector2(p.x + v.x * t, p.y + v.y * t);
};
VerletManager.prototype.bounds = function (particle) {
this.v.mutableSet(particle.pos);
this.v.mutableSub(particle.lastPos);
if(particle.pos.y > this.height - 1) {
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, this.height - 1), particle.lastPos, new Phaser.Vector2(1, 0), this.v));
}
if(particle.pos.x < 0) {
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(0, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
}
if(particle.pos.x > this.width - 1) {
particle.pos.mutableSet(this.intersectionPoint(new Phaser.Vector2(this.width - 1, 0), particle.pos, new Phaser.Vector2(0, 1), this.v));
}
};
VerletManager.prototype.OLDbounds = function (particle) {
if(particle.pos.y > this.height - 1) {
particle.pos.y = this.height - 1;
}
if(particle.pos.x < 0) {
var vx = particle.pos.x - particle.lastPos.x;
var vy = particle.pos.y - particle.lastPos.y;
if(vx == 0) {
particle.pos.x = 0;
} else {
var t = -particle.lastPos.x / vx;
particle.pos.x = particle.lastPos.x + t * vx;
particle.pos.y = particle.lastPos.y + t * vy;
}
}
if(particle.pos.x > this.width - 1) {
particle.pos.x = this.width - 1;
}
};
VerletManager.prototype.createPoint = function (pos) {
var composite = new Phaser.Verlet.Composite(this._game);
composite.particles.push(new Phaser.Verlet.Particle(pos));
this.composites.push(composite);
return composite;
};
VerletManager.prototype.createLineSegments = function (vertices, stiffness) {
var i;
var composite = new Phaser.Verlet.Composite(this._game);
for(i in vertices) {
composite.particles.push(new Phaser.Verlet.Particle(vertices[i]));
if(i > 0) {
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[i], composite.particles[i - 1], stiffness));
}
}
this.composites.push(composite);
return composite;
};
VerletManager.prototype.createCloth = function (origin, width, height, segments, pinMod, stiffness) {
var composite = new Phaser.Verlet.Composite(this._game);
var xStride = width / segments;
var yStride = height / segments;
var x, y;
for(y = 0; y < segments; ++y) {
for(x = 0; x < segments; ++x) {
var px = origin.x + x * xStride - width / 2 + xStride / 2;
var py = origin.y + y * yStride - height / 2 + yStride / 2;
composite.particles.push(new Phaser.Verlet.Particle(new Phaser.Vector2(px, py)));
if(x > 0) {
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[y * segments + x - 1], stiffness));
}
if(y > 0) {
composite.constraints.push(new Phaser.Verlet.DistanceConstraint(composite.particles[y * segments + x], composite.particles[(y - 1) * segments + x], stiffness));
}
}
}
for(x = 0; x < segments; ++x) {
if(x % pinMod == 0) {
composite.pin(x);
}
}
this.composites.push(composite);
return composite;
};
VerletManager.prototype.createTire = function (origin, radius, segments, spokeStiffness, treadStiffness) {
var stride = (2 * Math.PI) / segments;
var i;
var composite = new Phaser.Verlet.Composite(this._game);
// particles
for(i = 0; i < segments; ++i) {
var theta = i * stride;
composite.particles.push(new Verlet.Particle(new Phaser.Vector2(origin.x + Math.cos(theta) * radius, origin.y + Math.sin(theta) * radius)));
}
var center = new Verlet.Particle(origin);
composite.particles.push(center);
// constraints
for(i = 0; i < segments; ++i) {
composite.constraints.push(new Verlet.DistanceConstraint(composite.particles[i], composite.particles[(i + 1) % segments], treadStiffness));
composite.constraints.push(new Verlet.DistanceConstraint(composite.particles[i], center, spokeStiffness));
composite.constraints.push(new Verlet.DistanceConstraint(composite.particles[i], composite.particles[(i + 5) % segments], treadStiffness));
}
this.composites.push(composite);
return composite;
};
VerletManager.prototype.update = function () {
if(this.composites.length == 0) {
return;
}
var i, j, c;
for(c in this.composites) {
for(i in this.composites[c].particles) {
var particles = this.composites[c].particles;
// calculate velocity
var velocity = particles[i].pos.sub(particles[i].lastPos).scale(this.friction);
// ground friction
if(particles[i].pos.y >= this.height - 1 && velocity.length2() > 0.000001) {
var m = velocity.length();
velocity.x /= m;
velocity.y /= m;
velocity.mutableScale(m * this.groundFriction);
}
// save last good state
particles[i].lastPos.mutableSet(particles[i].pos);
// gravity
particles[i].pos.mutableAdd(this.gravity);
// inertia
particles[i].pos.mutableAdd(velocity);
}
}
// handle dragging of entities
if(this.draggedEntity) {
this.draggedEntity.pos.mutableSet(new Phaser.Vector2(this._game.input.x, this._game.input.y));
}
// relax
var stepCoef = 1 / this.step;
for(c in this.composites) {
var constraints = this.composites[c].constraints;
for(i = 0; i < this.step; ++i) {
for(j in constraints) {
constraints[j].relax(stepCoef);
}
}
}
// bounds checking
for(c in this.composites) {
var particles = this.composites[c].particles;
for(i in particles) {
this.bounds(particles[i]);
}
}
};
VerletManager.prototype.mouseDownHandler = function () {
var nearest = this.nearestEntity();
if(nearest) {
this.draggedEntity = nearest;
}
};
VerletManager.prototype.mouseUpHandler = function () {
this.draggedEntity = null;
};
VerletManager.prototype.nearestEntity = function () {
var c, i;
var d2Nearest = 0;
var entity = null;
var constraintsNearest = null;
// find nearest point
for(c in this.composites) {
var particles = this.composites[c].particles;
for(i in particles) {
var d2 = particles[i].pos.dist2(new Phaser.Vector2(this._game.input.x, this._game.input.y));
if(d2 <= this.selectionRadius * this.selectionRadius && (entity == null || d2 < d2Nearest)) {
entity = particles[i];
constraintsNearest = this.composites[c].constraints;
d2Nearest = d2;
}
}
}
// search for pinned constraints for this entity
for(i in constraintsNearest) {
if(constraintsNearest[i] instanceof Verlet.PinConstraint && constraintsNearest[i].a == entity) {
entity = constraintsNearest[i];
}
}
return entity;
};
VerletManager.prototype.render = function () {
var i, c;
for(c in this.composites) {
// draw constraints
if(this.composites[c].drawConstraints) {
this.composites[c].drawConstraints(this.context, this.composites[c]);
} else {
var constraints = this.composites[c].constraints;
for(i in constraints) {
constraints[i].render(this.context);
}
}
// draw particles
if(this.composites[c].drawParticles) {
this.composites[c].drawParticles(this.context, this.composites[c]);
} else {
var particles = this.composites[c].particles;
for(i in particles) {
particles[i].render(this.context);
}
}
}
// highlight nearest / dragged entity
var nearest = this.draggedEntity || this.nearestEntity();
if(nearest) {
this.context.beginPath();
this.context.arc(nearest.pos.x, nearest.pos.y, 8, 0, 2 * Math.PI);
this.context.strokeStyle = this.highlightColor;
this.context.stroke();
}
};
return VerletManager;
})();
Verlet.VerletManager = VerletManager;
})(Phaser.Verlet || (Phaser.Verlet = {}));
var Verlet = Phaser.Verlet;
})(Phaser || (Phaser = {}));
/// <reference path="Game.ts" />
/**
* Phaser - World
@@ -14847,7 +15581,9 @@ var Phaser;
/// <reference path="Stage.ts" />
/// <reference path="Time.ts" />
/// <reference path="TweenManager.ts" />
/// <reference path="VerletManager.ts" />
/// <reference path="World.ts" />
/// <reference path="geom/Vector2.ts" />
/// <reference path="system/Device.ts" />
/// <reference path="system/RandomDataGenerator.ts" />
/// <reference path="system/RequestAnimationFrame.ts" />
@@ -15025,6 +15761,7 @@ var Phaser;
this.rnd = new Phaser.RandomDataGenerator([
(Date.now() * Math.random()).toString()
]);
this.verlet = new Phaser.Verlet.VerletManager(this, width, height);
this.framerate = 60;
this.isBooted = true;
this.input.start();
@@ -15075,6 +15812,7 @@ var Phaser;
this.tweens.update();
this.input.update();
this.stage.update();
this.verlet.update();
this._accumulator += this.time.delta;
if(this._accumulator > this._maxAccumulation) {
this._accumulator = this._maxAccumulation;