mirror of
https://github.com/photonstorm/phaser
synced 2024-11-23 13:13:43 +00:00
840 lines
22 KiB
JavaScript
840 lines
22 KiB
JavaScript
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @author Mat Groves (@Doormat23)
|
|
* @author Rovanion Luckey
|
|
* @copyright 2016 Photon Storm Ltd, Richard Davey
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* A Rope is a Sprite that has a repeating texture.
|
|
*
|
|
* The texture will automatically wrap on the edges as it moves.
|
|
*
|
|
* Please note that Ropes cannot have an input handler.
|
|
*
|
|
* @class Phaser.GameObject.Rope
|
|
* @constructor
|
|
* @extends PIXI.DisplayObjectContainer
|
|
* @extends Phaser.Component.Core
|
|
* @extends Phaser.Component.Angle
|
|
* @extends Phaser.Component.Animation
|
|
* @extends Phaser.Component.AutoCull
|
|
* @extends Phaser.Component.Bounds
|
|
* @extends Phaser.Component.BringToTop
|
|
* @extends Phaser.Component.Crop
|
|
* @extends Phaser.Component.Delta
|
|
* @extends Phaser.Component.Destroy
|
|
* @extends Phaser.Component.FixedToCamera
|
|
* @extends Phaser.Component.InWorld
|
|
* @extends Phaser.Component.LifeSpan
|
|
* @extends Phaser.Component.LoadTexture
|
|
* @extends Phaser.Component.Overlap
|
|
* @extends Phaser.Component.PhysicsBody
|
|
* @extends Phaser.Component.Reset
|
|
* @extends Phaser.Component.ScaleMinMax
|
|
* @extends Phaser.Component.Smoothed
|
|
* @param {Phaser.Game} game - A reference to the currently running game.
|
|
* @param {number} x - The x coordinate (in world space) to position the Rope at.
|
|
* @param {number} y - The y coordinate (in world space) to position the Rope at.
|
|
* @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the Rope during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
|
|
* @param {string|number} frame - If this Rope is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
|
|
* @param {Array} points - An array of {Phaser.Point}.
|
|
*/
|
|
Phaser.GameObject.Rope = function (game, x, y, key, frame, points) {
|
|
|
|
this.points = [];
|
|
this.points = points;
|
|
this._hasUpdateAnimation = false;
|
|
this._updateAnimationCallback = null;
|
|
x = x || 0;
|
|
y = y || 0;
|
|
key = key || null;
|
|
frame = frame || null;
|
|
|
|
/**
|
|
* @property {number} type - The const type of this object.
|
|
* @readonly
|
|
*/
|
|
this.type = Phaser.ROPE;
|
|
|
|
this.points = points;
|
|
|
|
PIXI.DisplayObjectContainer.call(this);
|
|
|
|
this.texture = Phaser.Cache.DEFAULT;
|
|
|
|
// set up the main bits..
|
|
this.uvs = new Float32Array([0, 1,
|
|
1, 1,
|
|
1, 0,
|
|
0, 1]);
|
|
|
|
this.vertices = new Float32Array([0, 0,
|
|
100, 0,
|
|
100, 100,
|
|
0, 100]);
|
|
|
|
this.colors = new Float32Array([1, 1, 1, 1]);
|
|
|
|
this.indices = new Uint16Array([0, 1, 2, 3]);
|
|
|
|
if (points)
|
|
{
|
|
this.vertices = new Float32Array(points.length * 4);
|
|
this.uvs = new Float32Array(points.length * 4);
|
|
this.colors = new Float32Array(points.length * 2);
|
|
this.indices = new Uint16Array(points.length * 2);
|
|
}
|
|
|
|
/**
|
|
* Whether the strip is dirty or not
|
|
*
|
|
* @property dirty
|
|
* @type Boolean
|
|
*/
|
|
this.dirty = true;
|
|
|
|
/**
|
|
* Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other.
|
|
*
|
|
* @property canvasPadding
|
|
* @type Number
|
|
*/
|
|
this.canvasPadding = 0;
|
|
|
|
this.drawMode = Phaser.GameObject.Rope.TRIANGLE_STRIP;
|
|
|
|
Phaser.Component.Core.init.call(this, game, x, y, key, frame);
|
|
|
|
this.refresh();
|
|
|
|
};
|
|
|
|
Phaser.GameObject.Rope.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
|
|
Phaser.GameObject.Rope.prototype.constructor = Phaser.GameObject.Rope;
|
|
|
|
Phaser.Component.Core.install.call(Phaser.GameObject.Rope.prototype, [
|
|
'Angle',
|
|
'Animation',
|
|
'AutoCull',
|
|
'Bounds',
|
|
'BringToTop',
|
|
'Crop',
|
|
'Delta',
|
|
'Destroy',
|
|
'FixedToCamera',
|
|
'InWorld',
|
|
'LifeSpan',
|
|
'LoadTexture',
|
|
'Overlap',
|
|
'PhysicsBody',
|
|
'Reset',
|
|
'ScaleMinMax',
|
|
'Smoothed'
|
|
]);
|
|
|
|
Phaser.GameObject.Rope.prototype.preUpdatePhysics = Phaser.Component.PhysicsBody.preUpdate;
|
|
Phaser.GameObject.Rope.prototype.preUpdateLifeSpan = Phaser.Component.LifeSpan.preUpdate;
|
|
Phaser.GameObject.Rope.prototype.preUpdateInWorld = Phaser.Component.InWorld.preUpdate;
|
|
Phaser.GameObject.Rope.prototype.preUpdateCore = Phaser.Component.Core.preUpdate;
|
|
|
|
Phaser.GameObject.Rope.TRIANGLE_STRIP = 0;
|
|
Phaser.GameObject.Rope.TRIANGLES = 1;
|
|
|
|
/**
|
|
* Automatically called by World.preUpdate.
|
|
*
|
|
* @method Phaser.GameObject.Rope#preUpdate
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype.preUpdate = function () {
|
|
|
|
if (!this.preUpdatePhysics() || !this.preUpdateLifeSpan() || !this.preUpdateInWorld())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return this.preUpdateCore();
|
|
|
|
};
|
|
|
|
/**
|
|
* Override and use this function in your own custom objects to handle any update requirements you may have.
|
|
*
|
|
* @method Phaser.GameObject.Rope#update
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype.update = function() {
|
|
|
|
if (this._hasUpdateAnimation)
|
|
{
|
|
this.updateAnimation.call(this);
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* Resets the Rope. This places the Rope at the given x/y world coordinates and then
|
|
* sets alive, exists, visible and renderable all to true. Also resets the outOfBounds state.
|
|
* If the Rope has a physics body that too is reset.
|
|
*
|
|
* @method Phaser.GameObject.Rope#reset
|
|
* @memberof Phaser.GameObject.Rope
|
|
* @param {number} x - The x coordinate (in world space) to position the Sprite at.
|
|
* @param {number} y - The y coordinate (in world space) to position the Sprite at.
|
|
* @return {Phaser.GameObject.Rope} This instance.
|
|
*/
|
|
Phaser.GameObject.Rope.prototype.reset = function (x, y) {
|
|
|
|
Phaser.Component.Reset.prototype.reset.call(this, x, y);
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
/*
|
|
* Refreshes the rope texture and UV coordinates.
|
|
*
|
|
* @method Phaser.GameObject.Rope#refresh
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype.refresh = function () {
|
|
|
|
var points = this.points;
|
|
|
|
if (points.length < 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var uvs = this.uvs;
|
|
|
|
var indices = this.indices;
|
|
var colors = this.colors;
|
|
|
|
this.count -= 0.2;
|
|
|
|
uvs[0] = 0;
|
|
uvs[1] = 0;
|
|
uvs[2] = 0;
|
|
uvs[3] = 1;
|
|
|
|
colors[0] = 1;
|
|
colors[1] = 1;
|
|
|
|
indices[0] = 0;
|
|
indices[1] = 1;
|
|
|
|
var total = points.length;
|
|
var index;
|
|
var amount;
|
|
|
|
for (var i = 1; i < total; i++)
|
|
{
|
|
index = i * 4;
|
|
|
|
// time to do some smart drawing!
|
|
amount = i / (total - 1);
|
|
|
|
if (i % 2)
|
|
{
|
|
uvs[index] = amount;
|
|
uvs[index + 1] = 0;
|
|
|
|
uvs[index + 2] = amount;
|
|
uvs[index + 3] = 1;
|
|
}
|
|
else
|
|
{
|
|
uvs[index] = amount;
|
|
uvs[index + 1] = 0;
|
|
|
|
uvs[index + 2] = amount;
|
|
uvs[index + 3] = 1;
|
|
}
|
|
|
|
index = i * 2;
|
|
colors[index] = 1;
|
|
colors[index + 1] = 1;
|
|
|
|
index = i * 2;
|
|
indices[index] = index;
|
|
indices[index + 1] = index + 1;
|
|
}
|
|
|
|
};
|
|
|
|
/*
|
|
* Updates the Ropes transform ready for rendering.
|
|
*
|
|
* @method Phaser.GameObject.Rope#updateTransform
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype.updateTransform = function () {
|
|
|
|
var points = this.points;
|
|
|
|
if (points.length < 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var lastPoint = points[0];
|
|
var nextPoint;
|
|
var perp = { x:0, y:0 };
|
|
|
|
this.count -= 0.2;
|
|
|
|
var vertices = this.vertices;
|
|
var total = points.length;
|
|
var point;
|
|
var index;
|
|
var ratio;
|
|
var perpLength;
|
|
var num;
|
|
|
|
for (var i = 0; i < total; i++)
|
|
{
|
|
point = points[i];
|
|
index = i * 4;
|
|
|
|
if(i < points.length - 1)
|
|
{
|
|
nextPoint = points[i + 1];
|
|
}
|
|
else
|
|
{
|
|
nextPoint = point;
|
|
}
|
|
|
|
perp.y = -(nextPoint.x - lastPoint.x);
|
|
perp.x = nextPoint.y - lastPoint.y;
|
|
|
|
ratio = (1 - (i / (total - 1))) * 10;
|
|
|
|
if (ratio > 1)
|
|
{
|
|
ratio = 1;
|
|
}
|
|
|
|
perpLength = Math.sqrt((perp.x * perp.x) + (perp.y * perp.y));
|
|
num = this.texture.height / 2;
|
|
perp.x /= perpLength;
|
|
perp.y /= perpLength;
|
|
|
|
perp.x *= num;
|
|
perp.y *= num;
|
|
|
|
vertices[index] = point.x + perp.x;
|
|
vertices[index + 1] = point.y + perp.y;
|
|
vertices[index + 2] = point.x - perp.x;
|
|
vertices[index + 3] = point.y - perp.y;
|
|
|
|
lastPoint = point;
|
|
}
|
|
|
|
PIXI.DisplayObjectContainer.prototype.updateTransform.call(this);
|
|
|
|
};
|
|
|
|
/*
|
|
* Sets the Texture this Rope uses for rendering.
|
|
*
|
|
* @method Phaser.GameObject.Rope#setTexture
|
|
* @memberof Phaser.GameObject.Rope
|
|
* @param {Texture} texture - The texture that will be used.
|
|
*/
|
|
Phaser.GameObject.Rope.prototype.setTexture = function (texture) {
|
|
|
|
this.texture = texture;
|
|
|
|
};
|
|
|
|
/*
|
|
* Renders the Rope to WebGL.
|
|
*
|
|
* @private
|
|
* @method Phaser.GameObject.Rope#_renderWebGL
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype._renderWebGL = function (renderSession) {
|
|
|
|
if (!this.visible || this.alpha <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
renderSession.spriteBatch.stop();
|
|
|
|
if (!this._vertexBuffer)
|
|
{
|
|
this._initWebGL(renderSession);
|
|
}
|
|
|
|
renderSession.shaderManager.setShader(renderSession.shaderManager.stripShader);
|
|
|
|
this._renderStrip(renderSession);
|
|
|
|
renderSession.spriteBatch.start();
|
|
|
|
};
|
|
|
|
/*
|
|
* Builds the Strip.
|
|
*
|
|
* @private
|
|
* @method Phaser.GameObject.Rope#_initWebGL
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype._initWebGL = function (renderSession) {
|
|
|
|
// build the strip!
|
|
var gl = renderSession.gl;
|
|
|
|
this._vertexBuffer = gl.createBuffer();
|
|
this._indexBuffer = gl.createBuffer();
|
|
this._uvBuffer = gl.createBuffer();
|
|
this._colorBuffer = gl.createBuffer();
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW);
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, this.uvs, gl.STATIC_DRAW);
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this._colorBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, this.colors, gl.STATIC_DRAW);
|
|
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
|
|
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
|
|
|
|
};
|
|
|
|
/*
|
|
* Renders the Strip to WebGL.
|
|
*
|
|
* @private
|
|
* @method Phaser.GameObject.Rope#_renderStrip
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype._renderStrip = function (renderSession) {
|
|
|
|
var gl = renderSession.gl;
|
|
var projection = renderSession.projection;
|
|
var offset = renderSession.offset;
|
|
var shader = renderSession.shaderManager.stripShader;
|
|
|
|
var drawMode = (this.drawMode === Phaser.GameObject.Rope.TRIANGLE_STRIP) ? gl.TRIANGLE_STRIP : gl.TRIANGLES;
|
|
|
|
renderSession.blendModeManager.setBlendMode(this.blendMode);
|
|
|
|
// set uniforms
|
|
gl.uniformMatrix3fv(shader.translationMatrix, false, this.worldTransform.toArray(true));
|
|
gl.uniform2f(shader.projectionVector, projection.x, -projection.y);
|
|
gl.uniform2f(shader.offsetVector, -offset.x, -offset.y);
|
|
gl.uniform1f(shader.alpha, this.worldAlpha);
|
|
|
|
if (!this.dirty)
|
|
{
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
|
|
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices);
|
|
gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
|
|
|
|
// update the uvs
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
|
|
gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
|
|
|
|
gl.activeTexture(gl.TEXTURE0);
|
|
|
|
// check if a texture is dirty..
|
|
if (this.texture.baseTexture._dirty[gl.id])
|
|
{
|
|
renderSession.renderer.updateTexture(this.texture.baseTexture);
|
|
}
|
|
else
|
|
{
|
|
// bind the current texture
|
|
gl.bindTexture(gl.TEXTURE_2D, this.texture.baseTexture._glTextures);
|
|
}
|
|
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
|
|
}
|
|
else
|
|
{
|
|
this.dirty = false;
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.STATIC_DRAW);
|
|
gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
|
|
|
|
// update the uvs
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, this.uvs, gl.STATIC_DRAW);
|
|
gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
|
|
|
|
gl.activeTexture(gl.TEXTURE0);
|
|
|
|
// check if a texture is dirty..
|
|
if (this.texture.baseTexture._dirty[gl.id])
|
|
{
|
|
renderSession.renderer.updateTexture(this.texture.baseTexture);
|
|
}
|
|
else
|
|
{
|
|
gl.bindTexture(gl.TEXTURE_2D, this.texture.baseTexture._glTextures);
|
|
}
|
|
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
|
|
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
|
|
}
|
|
|
|
gl.drawElements(drawMode, this.indices.length, gl.UNSIGNED_SHORT, 0);
|
|
|
|
};
|
|
|
|
/*
|
|
* Renders the Strip to Canvas.
|
|
*
|
|
* @private
|
|
* @method Phaser.GameObject.Rope#_renderCanvas
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype._renderCanvas = function (renderSession) {
|
|
|
|
var context = renderSession.context;
|
|
|
|
var transform = this.worldTransform;
|
|
|
|
var tx = (transform.tx * renderSession.resolution) + renderSession.shakeX;
|
|
var ty = (transform.ty * renderSession.resolution) + renderSession.shakeY;
|
|
|
|
if (renderSession.roundPixels)
|
|
{
|
|
context.setTransform(transform.a, transform.b, transform.c, transform.d, tx | 0, ty | 0);
|
|
}
|
|
else
|
|
{
|
|
context.setTransform(transform.a, transform.b, transform.c, transform.d, tx, ty);
|
|
}
|
|
|
|
if (this.drawMode === Phaser.GameObject.Rope.TRIANGLE_STRIP)
|
|
{
|
|
this._renderCanvasTriangleStrip(context);
|
|
}
|
|
else
|
|
{
|
|
this._renderCanvasTriangles(context);
|
|
}
|
|
|
|
};
|
|
|
|
/*
|
|
* Renders a Triangle Strip to Canvas.
|
|
*
|
|
* @private
|
|
* @method Phaser.GameObject.Rope#_renderCanvasTriangleStrip
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype._renderCanvasTriangleStrip = function (context) {
|
|
|
|
// draw triangles!!
|
|
var vertices = this.vertices;
|
|
var uvs = this.uvs;
|
|
|
|
var length = vertices.length / 2;
|
|
|
|
this.count++;
|
|
|
|
for (var i = 0; i < length - 2; i++)
|
|
{
|
|
var index = i * 2;
|
|
this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4));
|
|
}
|
|
|
|
};
|
|
|
|
/*
|
|
* Renders a Triangle to Canvas.
|
|
*
|
|
* @private
|
|
* @method Phaser.GameObject.Rope#_renderCanvasTriangles
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype._renderCanvasTriangles = function (context) {
|
|
|
|
var vertices = this.vertices;
|
|
var uvs = this.uvs;
|
|
var indices = this.indices;
|
|
|
|
var length = indices.length;
|
|
|
|
this.count++;
|
|
|
|
for (var i = 0; i < length; i += 3)
|
|
{
|
|
var index0 = indices[i] * 2;
|
|
var index1 = indices[i + 1] * 2;
|
|
var index2 = indices[i + 2] * 2;
|
|
|
|
this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2);
|
|
}
|
|
|
|
};
|
|
|
|
/*
|
|
* Renders a Triangle to Canvas.
|
|
*
|
|
* @private
|
|
* @method Phaser.GameObject.Rope#_renderCanvasDrawTriangle
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) {
|
|
|
|
var textureSource = this.texture.baseTexture.source;
|
|
var textureWidth = this.texture.width;
|
|
var textureHeight = this.texture.height;
|
|
|
|
var x0 = vertices[index0];
|
|
var x1 = vertices[index1];
|
|
var x2 = vertices[index2];
|
|
var y0 = vertices[index0 + 1];
|
|
var y1 = vertices[index1 + 1];
|
|
var y2 = vertices[index2 + 1];
|
|
|
|
var u0 = uvs[index0] * textureWidth;
|
|
var u1 = uvs[index1] * textureWidth;
|
|
var u2 = uvs[index2] * textureWidth;
|
|
var v0 = uvs[index0 + 1] * textureHeight;
|
|
var v1 = uvs[index1 + 1] * textureHeight;
|
|
var v2 = uvs[index2 + 1] * textureHeight;
|
|
|
|
if (this.canvasPadding > 0)
|
|
{
|
|
var paddingX = this.canvasPadding / this.worldTransform.a;
|
|
var paddingY = this.canvasPadding / this.worldTransform.d;
|
|
var centerX = (x0 + x1 + x2) / 3;
|
|
var centerY = (y0 + y1 + y2) / 3;
|
|
|
|
var normX = x0 - centerX;
|
|
var normY = y0 - centerY;
|
|
|
|
var dist = Math.sqrt((normX * normX) + (normY * normY));
|
|
x0 = centerX + (normX / dist) * (dist + paddingX);
|
|
y0 = centerY + (normY / dist) * (dist + paddingY);
|
|
|
|
normX = x1 - centerX;
|
|
normY = y1 - centerY;
|
|
|
|
dist = Math.sqrt((normX * normX) + (normY * normY));
|
|
x1 = centerX + (normX / dist) * (dist + paddingX);
|
|
y1 = centerY + (normY / dist) * (dist + paddingY);
|
|
|
|
normX = x2 - centerX;
|
|
normY = y2 - centerY;
|
|
|
|
dist = Math.sqrt((normX * normX) + (normY * normY));
|
|
x2 = centerX + (normX / dist) * (dist + paddingX);
|
|
y2 = centerY + (normY / dist) * (dist + paddingY);
|
|
}
|
|
|
|
context.save();
|
|
context.beginPath();
|
|
|
|
context.moveTo(x0, y0);
|
|
context.lineTo(x1, y1);
|
|
context.lineTo(x2, y2);
|
|
|
|
context.closePath();
|
|
|
|
context.clip();
|
|
|
|
// Compute matrix transform
|
|
var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2);
|
|
var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2);
|
|
var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2);
|
|
var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2);
|
|
var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2);
|
|
var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2);
|
|
var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2);
|
|
|
|
context.transform(
|
|
deltaA / delta,
|
|
deltaD / delta,
|
|
deltaB / delta,
|
|
deltaE / delta,
|
|
deltaC / delta,
|
|
deltaF / delta);
|
|
|
|
context.drawImage(textureSource, 0, 0);
|
|
context.restore();
|
|
|
|
};
|
|
|
|
/*
|
|
* Renders a flat strip.
|
|
*
|
|
* @method Phaser.GameObject.Rope#renderStripFlat
|
|
* @memberof Phaser.GameObject.Rope
|
|
*/
|
|
Phaser.GameObject.Rope.prototype.renderStripFlat = function (strip) {
|
|
|
|
var context = this.context;
|
|
var vertices = strip.vertices;
|
|
|
|
var length = vertices.length / 2;
|
|
|
|
this.count++;
|
|
|
|
context.beginPath();
|
|
|
|
for (var i = 1; i < length - 2; i++)
|
|
{
|
|
// draw some triangles!
|
|
var index = i * 2;
|
|
|
|
var x0 = vertices[index];
|
|
var x1 = vertices[index + 2];
|
|
var x2 = vertices[index + 4];
|
|
var y0 = vertices[index + 1];
|
|
var y1 = vertices[index + 3];
|
|
var y2 = vertices[index + 5];
|
|
|
|
context.moveTo(x0, y0);
|
|
context.lineTo(x1, y1);
|
|
context.lineTo(x2, y2);
|
|
}
|
|
|
|
context.fillStyle = '#FF0000';
|
|
context.fill();
|
|
context.closePath();
|
|
|
|
};
|
|
|
|
/*
|
|
* Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account.
|
|
*
|
|
* @method Phaser.GameObject.Rope#getBounds
|
|
* @memberof Phaser.GameObject.Rope
|
|
* @param {Matrix} matrix - The transformation matrix of the Sprite.
|
|
* @return {Rectangle} The framing rectangle.
|
|
*/
|
|
Phaser.GameObject.Rope.prototype.getBounds = function (matrix) {
|
|
|
|
var worldTransform = matrix || this.worldTransform;
|
|
|
|
var a = worldTransform.a;
|
|
var b = worldTransform.b;
|
|
var c = worldTransform.c;
|
|
var d = worldTransform.d;
|
|
var tx = worldTransform.tx;
|
|
var ty = worldTransform.ty;
|
|
|
|
var maxX = -Infinity;
|
|
var maxY = -Infinity;
|
|
|
|
var minX = Infinity;
|
|
var minY = Infinity;
|
|
|
|
var vertices = this.vertices;
|
|
|
|
for (var i = 0; i < vertices.length; i += 2)
|
|
{
|
|
var rawX = vertices[i];
|
|
var rawY = vertices[i + 1];
|
|
var x = (a * rawX) + (c * rawY) + tx;
|
|
var y = (d * rawY) + (b * rawX) + ty;
|
|
|
|
minX = x < minX ? x : minX;
|
|
minY = y < minY ? y : minY;
|
|
|
|
maxX = x > maxX ? x : maxX;
|
|
maxY = y > maxY ? y : maxY;
|
|
}
|
|
|
|
if (minX === -Infinity || maxY === Infinity)
|
|
{
|
|
return Phaser.EmptyRectangle;
|
|
}
|
|
|
|
var bounds = this._bounds;
|
|
|
|
bounds.x = minX;
|
|
bounds.width = maxX - minX;
|
|
|
|
bounds.y = minY;
|
|
bounds.height = maxY - minY;
|
|
|
|
// Store a reference so that if this function gets called again in the render cycle we do not have to recalculate
|
|
this._currentBounds = bounds;
|
|
|
|
return bounds;
|
|
|
|
};
|
|
|
|
/**
|
|
* A Rope will call its updateAnimation function on each update loop if it has one.
|
|
*
|
|
* @name Phaser.GameObject.Rope#updateAnimation
|
|
* @property {function} updateAnimation - Set to a function if you'd like the rope to animate during the update phase. Set to false or null to remove it.
|
|
*/
|
|
Object.defineProperty(Phaser.GameObject.Rope.prototype, "updateAnimation", {
|
|
|
|
get: function () {
|
|
|
|
return this._updateAnimation;
|
|
|
|
},
|
|
|
|
set: function (value) {
|
|
|
|
if (value && typeof value === 'function')
|
|
{
|
|
this._hasUpdateAnimation = true;
|
|
this._updateAnimation = value;
|
|
}
|
|
else
|
|
{
|
|
this._hasUpdateAnimation = false;
|
|
this._updateAnimation = null;
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
/**
|
|
* The segments that make up the rope body as an array of Phaser.Rectangles
|
|
*
|
|
* @name Phaser.GameObject.Rope#segments
|
|
* @property {Phaser.Rectangles[]} updateAnimation - Returns an array of Phaser.Rectangles that represent the segments of the given rope
|
|
*/
|
|
Object.defineProperty(Phaser.GameObject.Rope.prototype, "segments", {
|
|
|
|
get: function () {
|
|
|
|
var segments = [];
|
|
var index, x1, y1, x2, y2, width, height, rect;
|
|
|
|
for (var i = 0; i < this.points.length; i++)
|
|
{
|
|
index = i * 4;
|
|
|
|
x1 = this.vertices[index] * this.scale.x;
|
|
y1 = this.vertices[index + 1] * this.scale.y;
|
|
x2 = this.vertices[index + 4] * this.scale.x;
|
|
y2 = this.vertices[index + 3] * this.scale.y;
|
|
|
|
width = Phaser.Math.difference(x1, x2);
|
|
height = Phaser.Math.difference(y1, y2);
|
|
|
|
x1 += this.world.x;
|
|
y1 += this.world.y;
|
|
rect = new Phaser.Rectangle(x1, y1, width, height);
|
|
segments.push(rect);
|
|
}
|
|
|
|
return segments;
|
|
}
|
|
|
|
});
|