Lots of renderTexture updates and examples added

This commit is contained in:
Richard Davey 2013-11-13 06:49:24 +00:00
parent e4faa34908
commit 6a24d6116b
14 changed files with 486 additions and 44 deletions

View file

@ -41,6 +41,10 @@ Change Log
Version 1.1.3 - in build
* New: RenderTexture.render now takes a Phaser.Group. Also added renderXY for when you don't want to make a new Point object.
* New: Implementing PluginManager.remove, added PluginManager.removeAll (thanks crazysam)
* New: Added scrollFactorX/scrollFactorY to TilemapLayers (thanks jcd-as)
* New: Phaser.Game parent can now be a HTMLElement (thanks beeglebug)
* New: Updated to use the latest version of Pixi.js - which means you can now use all the sexy new WebGL filters they added :)
* New: Sprite.animations.getAnimation will return an animation instance which was added by name.
* New: Added Mouse.button which is set to the button that was pressed: Phaser.Mouse.LEFT_BUTTON, MIDDLE_BUTTON or RIGHT_BUTTON (thanks wKLV)
@ -50,14 +54,23 @@ Version 1.1.3 - in build
* New: Polygon class & drawPolygon method added to Graphics (thanks rjimenezda)
* New: Added Group.iterate, a powerful way to count or return child that match a certain criteria. Refactored Group to use iterate, lots of repeated code cut.
* New: Added Group.sort. You can now sort the Group based on any given numeric property (x, y, health), finally you can do depth-sorting :) Example created to show.
* New: Enhanced renderTexture so it can accept a Phaser.Group object and improved documentation and examples.
* Fixed: Tilemap commands use specified layer when one given (thanks Izzimach)
* Fixed: Mouse.stop now uses the true useCapture, which means the event listeners stop listening correctly (thanks beeglebug)
* Fixed: Input Keyboard example fix (thanks Atrodilla)
* Fixed: BitmapText.destroy now checks if it has a canvas before calling parentNode on it.
* Fixed: Group.swap had a hellish to find bug that only manifested when B-A upward swaps occured. Hours of debugging later = bug crushed.
* Fixed: Point.rotate asDegrees fixed (thanks BorisKozo)
* Updated: ArcadePhysics.updateMotion applies the dt to the velocity calculations as well as position now (thanks jcs)
* Updated: RequestAnimationFrame now retains the callbackID which is passed to cancelRequestAnimationFrame.
* Updated: Button now goes back to over state when setFrames used in action (thanks beeglebug)
* Updated: plugins now have a postUpdate callback (thanks cocoademon)
* Updated: Tided up the Graphics object (thanks BorisKozo)
* Updated: If running in Canvas mode and you have a render function it will save the context and reset the transform before running your render function
* Updated: Sprite will now check the exists property of the Group it is in, if the Group.exists = false the Sprite won't update.
* Updated: Lots of small documentation tweaks across various files such as Pointer.
You can view the complete Change Log for all previous versions at https://github.com/photonstorm/phaser/changelog.md
@ -184,12 +197,14 @@ Learn By Example
Phaser comes with an ever growing suite of Examples. Personally I feel that we learn better by looking at small refined code examples, so we created over 150 of them and create new ones to test every new feature added. Inside the `examples` folder you'll find the current set. If you write a particularly good example then please send it to us.
The examples need running through a local web server (to avoid file access permission errors from your browser).
The examples need to be run through a local web server (in order to avoid file access permission errors from your browser). You can use your own web server, or start the included web server using grunt.
Browse to the examples folder via your web server.
Using a locally installed web server browse to the examples folder:
examples/index.html
Alternatively in order to start the included web server, after you've cloned the repo, run npm install to install all dependencies, then run grunt connect to start a local server. After running this command, you should be able to access your local webserver at `http://127.0.0.1:8000`. Then browse to the examples folder: `http://127.0.0.1:8000/examples/index.html`
There is a new 'Side View' example viewer as well. This loads all the examples into a left-hand frame for faster navigation.
You can also browse all [Phaser Examples](http://gametest.mobi/phaser/) online.

View file

@ -0,0 +1,35 @@
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update });
function preload() {
game.load.image('ball', 'assets/sprites/pangball.png');
}
var ball;
var texture;
function create() {
// Here we'll create a renderTexture the same size as our game
texture = game.add.renderTexture('mousetrail', 800, 600);
// This is the sprite that will be drawn to the texture, we set it to visible false as we only need its texture data
ball = game.add.sprite(0, 0, 'ball');
ball.visible = false;
ball.anchor.setTo(0.5, 0.5);
// This is the sprite that is drawn to the display. We've given it the renderTexture as its texture.
game.add.sprite(0, 0, texture);
}
function update() {
// This time we'll draw the ball sprite twice, in a mirror effect
texture.renderXY(ball, game.input.activePointer.x, game.input.activePointer.y, false);
texture.renderXY(ball, game.input.activePointer.x, 600 - game.input.activePointer.y, false);
}

View file

@ -0,0 +1,81 @@
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update });
function preload() {
game.load.image('star', 'assets/sprites/bullet.png');
}
var star;
var texture1;
var texture2;
var texture3;
var stars = [];
function create() {
// This is the sprite that will be drawn to the texture, we set it to visible false as we only need its texture data.
star = game.add.sprite(0, 0, 'star');
star.visible = false;
// For this effect we'll create a vertical scrolling starfield with 300 stars split across 3 layers.
// This will use only 3 textures / sprites in total.
texture1 = game.add.renderTexture('texture1', 800, 600);
texture2 = game.add.renderTexture('texture2', 800, 600);
texture3 = game.add.renderTexture('texture3', 800, 600);
game.add.sprite(0, 0, texture1);
game.add.sprite(0, 0, texture2);
game.add.sprite(0, 0, texture3);
var t = texture1;
var s = 4;
// 100 sprites per layer
for (var i = 0; i < 300; i++)
{
if (i == 100)
{
// With each 100 stars we ramp up the speed a little and swap to the next texture
s = 6;
t = texture2;
}
else if (i == 200)
{
s = 7;
t = texture3;
}
stars.push( { x: game.world.randomX, y: game.world.randomY, speed: s, texture: t });
}
}
function update() {
for (var i = 0; i < 300; i++)
{
// Update the stars y position based on its speed
stars[i].y += stars[i].speed;
if (stars[i].y > 600)
{
// Off the bottom of the screen? Then wrap around to the top
stars[i].x = game.world.randomX;
stars[i].y = -32;
}
if (i == 0 || i == 100 || i == 200)
{
// If it's the first star of the layer then we clear the texture
stars[i].texture.renderXY(star, stars[i].x, stars[i].y, true);
}
else
{
// Otherwise just draw the star sprite where we need it
stars[i].texture.renderXY(star, stars[i].x, stars[i].y, false);
}
}
}

View file

@ -0,0 +1,34 @@
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update });
function preload() {
game.load.image('mushroom', 'assets/sprites/mushroom2.png');
}
var mushroom;
var texture;
function create() {
// Here we'll create a renderTexture the same size as our game
texture = game.add.renderTexture('mousetrail', 800, 600);
// This is the sprite that will be drawn to the texture, we set it to visible false as we only need its texture data
mushroom = game.add.sprite(0, 0, 'mushroom');
mushroom.visible = false;
mushroom.anchor.setTo(0.5, 0.5);
// This is the sprite that is drawn to the display. We've given it the renderTexture as its texture.
game.add.sprite(0, 0, texture);
}
function update() {
// Here we draw the mushroom sprite to the renderTexture at the pointer coordinates.
// The 'false' parameter at the end tells it not to clear itself, causing the trail effect you see.
texture.render(mushroom, game.input.activePointer.position, false);
}

View file

@ -15,7 +15,7 @@ var cursors;
function create() {
// Modify the world and camera bounds
game.world.setBounds(-1000, -1000, 2000, 2000);
game.world.setBounds(-1000, -1000, 1000, 1000);
for (var i = 0; i < 100; i++)
{

View file

@ -0,0 +1,38 @@
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update });
function preload() {
game.load.spritesheet('veggies', 'assets/sprites/fruitnveg32wh37.png', 32, 32);
}
var group;
var texture;
function create() {
group = game.add.group();
group.create(0, 0, 'veggies', 0);
group.create(32, 0, 'veggies', 1);
group.create(0, 32, 'veggies', 2);
group.create(32, 32, 'veggies', 3);
group.visible = false;
texture = game.add.renderTexture('texture', 800, 600);
game.add.sprite(0, 0, texture);
}
function update() {
var clear = false;
for (var i = 0; i < 60; i++)
{
clear = (i == 0);
texture.renderXY(group, game.world.randomX, game.world.randomY, clear);
}
}

View file

@ -18,7 +18,7 @@ var logo2;
function create() {
// Modify the world and camera bounds
game.world.setBounds(-1000, -1000, 2000, 2000);
game.world.setBounds(-1000, -1000, 1000, 1000);
for (var i = 0; i < 200; i++)
{

View file

@ -16,7 +16,7 @@ var d;
function create() {
// Modify the world and camera bounds
game.world.setBounds(-1000, -1000, 2000, 2000);
game.world.setBounds(-1000, -1000, 1000, 1000);
for (var i = 0; i < 100; i++)
{

View file

@ -484,7 +484,18 @@ Phaser.StateManager.prototype = {
if (this._created && this.onRenderCallback)
{
if (this.game.renderType === Phaser.CANVAS)
{
this.game.context.save();
this.game.context.setTransform(1, 0, 0, 1, 0, 0);
}
this.onRenderCallback.call(this.callbackContext, this.game);
if (this.game.renderType === Phaser.CANVAS)
{
this.game.context.restore();
}
}
else
{

View file

@ -25,6 +25,9 @@ Phaser.Graphics = function (game, x, y) {
*/
this.type = Phaser.GRAPHICS;
this.position.x = x;
this.position.y = y;
};
Phaser.Graphics.prototype = Object.create(PIXI.Graphics.prototype);
@ -56,10 +59,14 @@ Phaser.Graphics.prototype.destroy = function() {
Phaser.Graphics.prototype.drawPolygon = function (poly) {
graphics.moveTo(poly.points[0].x, poly.points[0].y);
for (var i = 1; i < poly.points.length; i += 1) {
for (var i = 1; i < poly.points.length; i += 1)
{
graphics.lineTo(poly.points[i].x, poly.points[i].y);
}
graphics.lineTo(poly.points[0].x, poly.points[0].y);
}
Object.defineProperty(Phaser.Graphics.prototype, 'angle', {

View file

@ -5,7 +5,7 @@
*/
/**
* A dynamic initially blank canvas to which images can be drawn
* A RenderTexture is a special texture that allows any displayObject to be rendered to it.
* @class Phaser.RenderTexture
* @constructor
* @param {Phaser.Game} game - Current game instance.
@ -25,7 +25,7 @@ Phaser.RenderTexture = function (game, key, width, height) {
*/
this.name = key;
PIXI.EventTarget.call( this );
PIXI.EventTarget.call(this);
/**
* @property {number} width - the width.
@ -38,22 +38,22 @@ Phaser.RenderTexture = function (game, key, width, height) {
this.height = height || 100;
/**
* I know this has a typo in it, but it's because the PIXI.RenderTexture does and we need to pair-up with it
* once they update pixi to fix the typo, we'll fix it here too :)
* @property {Description} indetityMatrix - Description.
* @property {PIXI.mat3} indetityMatrix - Matrix object.
*/
this.indetityMatrix = PIXI.mat3.create();
/**
* @property {Description} frame - Description.
* @property {PIXI.Rectangle} frame - The frame for this texture.
*/
this.frame = new PIXI.Rectangle(0, 0, this.width, this.height);
/**
* @property {Description} type - Description.
* @property {number} type - Base Phaser object type.
*/
this.type = Phaser.RENDERTEXTURE;
this._tempPoint = { x: 0, y: 0 };
if (PIXI.gl)
{
this.initWebGL();
@ -65,5 +65,247 @@ Phaser.RenderTexture = function (game, key, width, height) {
};
Phaser.RenderTexture.prototype = Phaser.Utils.extend(true, PIXI.RenderTexture.prototype);
Phaser.RenderTexture.prototype.constructor = Phaser.RenderTexture;
Phaser.RenderTexture.prototype = Object.create(PIXI.Texture.prototype);
Phaser.RenderTexture.prototype.constructor = PIXI.RenderTexture;
/**
* This function will draw the display object to the texture. If the display object is a Group or has children it will
* draw all children as well.
*
* @method render
* @param {DisplayObject} displayObject - The display object to render this texture on.
* @param {Phaser.Point} [position] - Where to draw the display object.
* @param {boolean} [clear=false] - If true the texture will be cleared before the displayObject is drawn.
*/
Phaser.RenderTexture.prototype.render = function(displayObject, position, clear) {
if (typeof position === 'undefined') { position = false; }
if (typeof clear === 'undefined') { clear = false; }
if (displayObject instanceof Phaser.Group)
{
displayObject = displayObject._container;
}
if (PIXI.gl)
{
this.renderWebGL(displayObject, position, clear);
}
else
{
this.renderCanvas(displayObject, position, clear);
}
}
/**
* This function will draw the display object to the texture at the given x/y coordinates.
* If the display object is a Group or has children it will draw all children as well.
*
* @method renderXY
* @param {DisplayObject} displayObject - The display object to render this texture on.
* @param {number} x - The x coordinate to draw the display object at.
* @param {number} y - The y coordinate to draw the display object at.
* @param {boolean} [clear=false] - If true the texture will be cleared before the displayObject is drawn.
*/
Phaser.RenderTexture.prototype.renderXY = function(displayObject, x, y, clear) {
this._tempPoint.x = x;
this._tempPoint.y = y;
this.render(displayObject, this._tempPoint, clear);
}
/**
* Initializes the webgl data for this texture
*
* @method initWebGL
* @private
*/
Phaser.RenderTexture.prototype.initWebGL = function()
{
var gl = PIXI.gl;
this.glFramebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer );
this.glFramebuffer.width = this.width;
this.glFramebuffer.height = this.height;
this.baseTexture = new PIXI.BaseTexture();
this.baseTexture.width = this.width;
this.baseTexture.height = this.height;
this.baseTexture._glTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
this.baseTexture.isRender = true;
gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer );
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0);
// create a projection matrix..
this.projection = new PIXI.Point(this.width/2 , -this.height/2);
// set the correct render function..
// this.render = this.renderWebGL;
}
Phaser.RenderTexture.prototype.resize = function(width, height)
{
this.width = width;
this.height = height;
if(PIXI.gl)
{
this.projection.x = this.width/2
this.projection.y = -this.height/2;
var gl = PIXI.gl;
gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
}
else
{
this.frame.width = this.width
this.frame.height = this.height;
this.renderer.resize(this.width, this.height);
}
}
/**
* Initializes the canvas data for this texture
*
* @method initCanvas
* @private
*/
Phaser.RenderTexture.prototype.initCanvas = function()
{
this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0);
this.baseTexture = new PIXI.BaseTexture(this.renderer.view);
this.frame = new PIXI.Rectangle(0, 0, this.width, this.height);
// this.render = this.renderCanvas;
}
/**
* This function will draw the display object to the texture.
*
* @method renderWebGL
* @param displayObject {DisplayObject} The display object to render this texture on
* @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn
* @private
*/
Phaser.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear)
{
var gl = PIXI.gl;
// enable the alpha color mask..
gl.colorMask(true, true, true, true);
gl.viewport(0, 0, this.width, this.height);
gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer );
if(clear)
{
gl.clearColor(0,0,0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
}
// THIS WILL MESS WITH HIT TESTING!
var children = displayObject.children;
//TODO -? create a new one??? dont think so!
var originalWorldTransform = displayObject.worldTransform;
displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix;
// modify to flip...
displayObject.worldTransform[4] = -1;
displayObject.worldTransform[5] = this.projection.y * -2;
if(position)
{
displayObject.worldTransform[2] = position.x;
displayObject.worldTransform[5] -= position.y;
}
PIXI.visibleCount++;
displayObject.vcount = PIXI.visibleCount;
for(var i=0,j=children.length; i<j; i++)
{
children[i].updateTransform();
}
var renderGroup = displayObject.__renderGroup;
if(renderGroup)
{
if(displayObject == renderGroup.root)
{
renderGroup.render(this.projection, this.glFramebuffer);
}
else
{
renderGroup.renderSpecific(displayObject, this.projection, this.glFramebuffer);
}
}
else
{
if(!this.renderGroup)this.renderGroup = new PIXI.WebGLRenderGroup(gl);
this.renderGroup.setRenderable(displayObject);
this.renderGroup.render(this.projection, this.glFramebuffer);
}
displayObject.worldTransform = originalWorldTransform;
}
/**
* This function will draw the display object to the texture.
*
* @method renderCanvas
* @param displayObject {DisplayObject} The display object to render this texture on
* @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn
* @private
*/
Phaser.RenderTexture.prototype.renderCanvas = function(displayObject, position, clear)
{
var children = displayObject.children;
displayObject.worldTransform = PIXI.mat3.create();
if(position)
{
displayObject.worldTransform[2] = position.x;
displayObject.worldTransform[5] = position.y;
}
for(var i=0,j=children.length; i<j; i++)
{
children[i].updateTransform();
}
if(clear)this.renderer.context.clearRect(0,0, this.width, this.height);
this.renderer.renderDisplayObject(displayObject);
this.renderer.context.setTransform(1,0,0,1,0,0);
// PIXI.texturesToUpdate.push(this.baseTexture);
}

View file

@ -352,7 +352,7 @@ Phaser.Sprite.prototype.constructor = Phaser.Sprite;
*/
Phaser.Sprite.prototype.preUpdate = function() {
if (!this.exists)
if (!this.exists || !this.group.exists)
{
this.renderOrderID = -1;
return;

View file

@ -426,7 +426,7 @@ Phaser.Point.rotate = function (a, x, y, angle, asDegrees, distance) {
if (asDegrees)
{
angle = Phaser.Math.radToDeg(angle);
angle = Phaser.Math.degToRad(angle);
}
// Get distance from origin (cx/cy) to this point

View file

@ -56,28 +56,6 @@ Phaser.Pointer = function (game, id) {
*/
this._stateReset = false;
/**
* A Vector object containing the initial position when the Pointer was engaged with the screen.
* @property {Vec2} positionDown
* @default
**/
this.positionDown = null;
/**
* A Vector object containing the current position of the Pointer on the screen.
* @property {Vec2} position
* @default
**/
this.position = null;
/**
* A Circle object centered on the x/y screen coordinates of the Pointer.
* Default size of 44px (Apple's recommended "finger tip" size).
* @property {Circle} circle
* @default
**/
this.circle = null;
/**
* Description.
* @property {boolean} withinGame
@ -204,26 +182,27 @@ Phaser.Pointer = function (game, id) {
this.targetObject = null;
/**
* Description.
* @property {boolean} isDown - Description.
* An active pointer is one that is currently pressed down on the display. A Mouse is always active.
* @property {boolean} active
* @default
*/
this.active = false;
/**
* Description
* A Phaser.Point object containing the current x/y values of the pointer on the display.
* @property {Phaser.Point} position
*/
this.position = new Phaser.Point();
/**
* Description
* A Phaser.Point object containing the x/y values of the pointer when it was last in a down state on the display.
* @property {Phaser.Point} positionDown
*/
this.positionDown = new Phaser.Point();
/**
* Description
* A Phaser.Circle that is centered on the x/y coordinates of this pointer, useful for hit detection.
* The Circle size is 44px (Apples recommended "finger tip" size).
* @property {Phaser.Circle} circle
*/
this.circle = new Phaser.Circle(0, 0, 44);