diff --git a/README.md b/README.md index 9b4e87ff..1841790b 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,8 @@ Version 1.1 * JSDoc is go! We've added jsdoc3 blocks to every property and function, in every file. * Brand new Example system (no more php!) and over 150 examples to learn from too. * New TypeScript definitions file generated (in the build folder). +* New Grunt based build system added for those that prefer Grunt over php (thanks to Florent Cailhol) + * Added World.postUpdate - all sprite position changes, as a result of physics, happen here before the render. * Complete overhaul of Physics.Arcade.Body - now significantly more stable and faster too. * Updated ArcadePhysics.separateX/Y to use new body system - much better results now. @@ -139,6 +141,15 @@ Version 1.1 * Fixed Issue 111 - calling Kill on a Phaser.Graphics instance causes error on undefined events. * Phaser.Group now automatically calls updateTransform on any child added to it (avoids temp. frame glitches when new objects are rendered on their first frame). * Phaser.Time physicsElapsed delta timer clamp added. Stops rogue iOS / slow mobile timer errors causing crazy high deltas. +* Animation.generateFrameNames can now work in reverse, so the start/stop values can create frames that increment or decrement respectively. +* Loader updated to use xhr.responseText when loading json, csv or text files. xhr.response is still used for Web Audio binary files (thanks bubba) +* Input.onDown and onUp events now dispatch the original event that triggered them (i.e. a MouseEvent or TouchEvent) as the 2nd parameter, after the Pointer (thanks rezoner) +* Game.destroy will now stop the raf from running as well as close down all input related event listeners (issue 92, thanks astrism) +* Fixed issue 105 where a dragged object that was destroyed would cause an Input error (thanks onedayitwillmake) +* Updated Sprite.crop significantly. Values are now cached, stopping constant Texture frame updates and you can do sprite.crop.width++ for example (thanks haden) +* Change: Sprite.crop needs to be enabled with sprite.cropEnabled = true. +* Added Rectangle.floorAll to floor all values in a Rectangle (x, y, width and height). +* Fixed Sound.resume so it now correctly resumes playback from the point it was paused (fixes issue 51, thanks Yora). Outstanding Tasks @@ -151,6 +162,7 @@ Outstanding Tasks * TODO: Sound.addMarker hh:mm:ss:ms * TODO: swap state (non-destructive shift) * TODO: rotation offset +* TODO: Look at HiDPI Canvas settings Requirements ------------ diff --git a/examples/_site/examples.json b/examples/_site/examples.json index 40ed7616..41646962 100644 --- a/examples/_site/examples.json +++ b/examples/_site/examples.json @@ -1,632 +1,192 @@ { - "animation": [ - { - "file": "change+texture+on+click.js", - "title": "change texture on click" - }, - { - "file": "local+json+object.js", - "title": "local json object" - }, - { - "file": "looped+animation.js", - "title": "looped animation" - }, - { - "file": "multiple+anims.js", - "title": "multiple anims" - }, - { - "file": "sprite+sheet.js", - "title": "sprite sheet" - }, - { - "file": "texture+packer+json+hash.js", - "title": "texture packer json hash" - } - ], - "audio": [ - { - "file": "loop.js", - "title": "loop" - }, - { - "file": "play+music.js", - "title": "play music" - } - ], - "basics": [ - { - "file": "01+-+load+an+image.js", - "title": "01 - load an image" - } - ], - "buttons": [ - { - "file": "action+on+click.js", - "title": "action on click" - }, - { - "file": "changing+the+frames.js", - "title": "changing the frames" - }, - { - "file": "rotated+buttons.js", - "title": "rotated buttons" - } - ], - "camera": [ - { - "file": "basic+follow.js", - "title": "basic follow" - }, - { - "file": "camera+cull.js", - "title": "camera cull" - }, - { - "file": "follow+styles.js", - "title": "follow styles" - }, - { - "file": "moving+the+camera.js", - "title": "moving the camera" - }, - { - "file": "world+sprite.js", - "title": "world sprite" - } - ], - "collision": [ - { - "file": "bounding+box.js", - "title": "bounding box" - }, - { - "file": "group+vs+group.js", - "title": "group vs group" - }, - { - "file": "larger+bounding+box.js", - "title": "larger bounding box" - }, - { - "file": "offset+bounding+box.js", - "title": "offset bounding box" - }, - { - "file": "sprite+tiles.js", - "title": "sprite tiles" - }, - { - "file": "sprite+vs+group.js", - "title": "sprite vs group" - }, - { - "file": "sprite+vs+sprite+custom.js", - "title": "sprite vs sprite custom" - }, - { - "file": "sprite+vs+sprite.js", - "title": "sprite vs sprite" - }, - { - "file": "transform.js", - "title": "transform" - }, - { - "file": "vertical+collision.js", - "title": "vertical collision" - } - ], - "display": [ - { - "file": "fullscreen.js", - "title": "fullscreen" - }, - { - "file": "graphics.js", - "title": "graphics" - }, - { - "file": "render+crisp.js", - "title": "render crisp" - } - ], - "games": [ - { - "file": "breakout.js", - "title": "breakout" - }, - { - "file": "invaders.js", - "title": "invaders" - }, - { - "file": "starstruck.js", - "title": "starstruck" - }, - { - "file": "tanks.js", - "title": "tanks" - } - ], - "geometry": [ - { - "file": "circle.js", - "title": "circle" - }, - { - "file": "line.js", - "title": "line" - }, - { - "file": "playing+with+points.js", - "title": "playing with points" - }, - { - "file": "rectangle.js", - "title": "rectangle" - }, - { - "file": "rotate+point.js", - "title": "rotate point" - } - ], - "groups": [ - { - "file": "add+a+sprite+to+group.js", - "title": "add a sprite to group" - }, - { - "file": "bring+a+child+to+top.js", - "title": "bring a child to top" - }, - { - "file": "bring+a+group+to+top.js", - "title": "bring a group to top" - }, - { - "file": "call+all.js", - "title": "call all" - }, - { - "file": "create+group.js", - "title": "create group" - }, - { - "file": "create+sprite+in+a+group.js", - "title": "create sprite in a group" - }, - { - "file": "display+order.js", - "title": "display order" - }, - { - "file": "for+each.js", - "title": "for each" - }, - { - "file": "get+first.js", - "title": "get first" - }, - { - "file": "group+as+layer.js", - "title": "group as layer" - }, - { - "file": "group+transform+-+rotate.js", - "title": "group transform - rotate" - }, - { - "file": "group+transform+-+tween.js", - "title": "group transform - tween" - }, - { - "file": "group+transform.js", - "title": "group transform" - }, - { - "file": "recyling.js", - "title": "recyling" - }, - { - "file": "remove.js", - "title": "remove" - }, - { - "file": "replace.js", - "title": "replace" - }, - { - "file": "set+All.js", - "title": "set All" - }, - { - "file": "sub+groups+-+group+length.js", - "title": "sub groups - group length" - }, - { - "file": "swap+children+in+a+group.js", - "title": "swap children in a group" - } - ], - "input": [ - { - "file": "cursor+key+movement.js", - "title": "cursor key movement" - }, - { - "file": "drag+several+sprites.js", - "title": "drag several sprites" - }, - { - "file": "drag.js", - "title": "drag" - }, - { - "file": "drop+limitation.js", - "title": "drop limitation" - }, - { - "file": "follow+mouse.js", - "title": "follow mouse" - }, - { - "file": "game+scale.js", - "title": "game scale" - }, - { - "file": "key.js", - "title": "key" - }, - { - "file": "keyboard+hotkeys.js", - "title": "keyboard hotkeys" - }, - { - "file": "keyboard+justpressed.js", - "title": "keyboard justpressed" - }, - { - "file": "keyboard.js", - "title": "keyboard" - }, - { - "file": "motion+lock+-+horizontal.js", - "title": "motion lock - horizontal" - }, - { - "file": "motion+lock+-+vertical.js", - "title": "motion lock - vertical" - }, - { - "file": "multi+touch.js", - "title": "multi touch" - }, - { - "file": "override+default+controls.js", - "title": "override default controls" - }, - { - "file": "pixel+perfect+click+detection.js", - "title": "pixel perfect click detection" - }, - { - "file": "pixelpick+-+scrolling+effect.js", - "title": "pixelpick - scrolling effect" - }, - { - "file": "pixelpick+-+spritesheet.js", - "title": "pixelpick - spritesheet" - }, - { - "file": "snap+on+drag.js", - "title": "snap on drag" - } - ], - "loader": [ - { - "file": "pick+images+from+cache.js", - "title": "pick images from cache" - } - ], - "misc": [ - { - "file": "net.js", - "title": "net" - }, - { - "file": "random+generators.js", - "title": "random generators" - }, - { - "file": "repeatable+random+numbers.js", - "title": "repeatable random numbers" - } - ], - "particles": [ - { - "file": "click+burst.js", - "title": "click burst" - }, - { - "file": "collision.js", - "title": "collision" - }, - { - "file": "diamond+burst.js", - "title": "diamond burst" - }, - { - "file": "no+rotation.js", - "title": "no rotation" - }, - { - "file": "random+sprite.js", - "title": "random sprite" - }, - { - "file": "when+particles+collide.js", - "title": "when particles collide" - }, - { - "file": "zero+gravity.js", - "title": "zero gravity" - } - ], - "physics": [ - { - "file": "accelerate+to+pointer.js", - "title": "accelerate to pointer" - }, - { - "file": "angle+between.js", - "title": "angle between" - }, - { - "file": "angle+to+pointer.js", - "title": "angle to pointer" - }, - { - "file": "angular+acceleration.js", - "title": "angular acceleration" - }, - { - "file": "angular+velocity.js", - "title": "angular velocity" - }, - { - "file": "mass+velocity+test.js", - "title": "mass velocity test" - }, - { - "file": "move+towards+object.js", - "title": "move towards object" - }, - { - "file": "multi+angle+to+pointer.js", - "title": "multi angle to pointer" - }, - { - "file": "quadtree+-+collision+infos.js", - "title": "quadtree - collision infos" - }, - { - "file": "quadtree+-+ids.js", - "title": "quadtree - ids" - }, - { - "file": "shoot+the+pointer.js", - "title": "shoot the pointer" - }, - { - "file": "sprite+bounds.js", - "title": "sprite bounds" - } - ], - "sprites": [ - { - "file": "add+a+sprite.js", - "title": "add a sprite" - }, - { - "file": "add+several+sprites.js", - "title": "add several sprites" - }, - { - "file": "collide+world+bounds.js", - "title": "collide world bounds" - }, - { - "file": "destroy.js", - "title": "destroy" - }, - { - "file": "dynamic+crop.js", - "title": "dynamic crop" - }, - { - "file": "extending+sprite+demo+1.js", - "title": "extending sprite demo 1" - }, - { - "file": "extending+sprite+demo+2.js", - "title": "extending sprite demo 2" - }, - { - "file": "horizontal+crop.js", - "title": "horizontal crop" - }, - { - "file": "move+a+sprite.js", - "title": "move a sprite" - }, - { - "file": "out+of+bounds.js", - "title": "out of bounds" - }, - { - "file": "scale+a+sprite.js", - "title": "scale a sprite" - }, - { - "file": "shared+sprite+textures.js", - "title": "shared sprite textures" - }, - { - "file": "sprite+rotation.js", - "title": "sprite rotation" - }, - { - "file": "spritesheet.js", - "title": "spritesheet" - }, - { - "file": "vertical+crop.js", - "title": "vertical crop" - } - ], - "text": [ - { - "file": "bitmap+fonts.js", - "title": "bitmap fonts" - }, - { - "file": "hello+arial.js", - "title": "hello arial" - }, - { - "file": "kern+of+duty.js", - "title": "kern of duty" - }, - { - "file": "remove+text.js", - "title": "remove text" - }, - { - "file": "text+stroke.js", - "title": "text stroke" - } - ], - "tile sprites": [ - { - "file": "animated+tiling+sprite.js", - "title": "animated tiling sprite" - }, - { - "file": "tiling+sprite.js", - "title": "tiling sprite" - } - ], - "tilemaps": [ - { - "file": "fill+tiles.js", - "title": "fill tiles" - }, - { - "file": "mapcollide.js", - "title": "mapcollide" - }, - { - "file": "mario.js", - "title": "mario" - }, - { - "file": "mariotogether.js", - "title": "mariotogether" - }, - { - "file": "paint+tiles.js", - "title": "paint tiles" - }, - { - "file": "randomise+tiles.js", - "title": "randomise tiles" - }, - { - "file": "replace+tiles.js", - "title": "replace tiles" - }, - { - "file": "sci+fly.js", - "title": "sci fly" - }, - { - "file": "supermario.js", - "title": "supermario" - }, - { - "file": "supermario2.js", - "title": "supermario2" - }, - { - "file": "swap+tiles.js", - "title": "swap tiles" - }, - { - "file": "wip1.js", - "title": "wip1" - }, - { - "file": "wip2.js", - "title": "wip2" - }, - { - "file": "wip3.js", - "title": "wip3" - }, - { - "file": "wip4.js", - "title": "wip4" - } - ], - "tweens": [ - { - "file": "bounce.js", - "title": "bounce" - }, - { - "file": "bubbles.js", - "title": "bubbles" - }, - { - "file": "chained+tweens.js", - "title": "chained tweens" - }, - { - "file": "combined+tweens.js", - "title": "combined tweens" - }, - { - "file": "easing+spritesheets.js", - "title": "easing spritesheets" - }, - { - "file": "easing.js", - "title": "easing" - }, - { - "file": "fading+in+a+sprite.js", - "title": "fading in a sprite" - }, - { - "file": "pause+tween.js", - "title": "pause tween" - }, - { - "file": "tween+several+properties.js", - "title": "tween several properties" - } - ], - "world": [ - { - "file": "fixed+to+camera.js", - "title": "fixed to camera" - }, - { - "file": "move+around+world.js", - "title": "move around world" - } - ] +"basics": [ + { "file": "01+-+load+an+image.js", "title": "01 - load an image" } +], +"games": [ + { "file": "breakout.js", "title": "breakout" }, + { "file": "invaders.js", "title": "invaders" }, + { "file": "starstruck.js", "title": "starstruck" }, + { "file": "tanks.js", "title": "tanks" } +], +"animation": [ + { "file": "change+texture+on+click.js", "title": "change texture on click" }, + { "file": "local+json+object.js", "title": "local json object" }, + { "file": "looped+animation.js", "title": "looped animation" }, + { "file": "multiple+anims.js", "title": "multiple anims" }, + { "file": "sprite+sheet.js", "title": "sprite sheet" }, + { "file": "texture+packer+json+hash.js", "title": "texture packer json hash" } +], +"audio": [ + { "file": "loop.js", "title": "loop" }, + { "file": "pause+and+resume.js", "title": "pause and resume" }, + { "file": "play+music.js", "title": "play music" } +], +"buttons": [ + { "file": "action+on+click.js", "title": "action on click" }, + { "file": "changing+the+frames.js", "title": "changing the frames" }, + { "file": "rotated+buttons.js", "title": "rotated buttons" } +], +"camera": [ + { "file": "basic+follow.js", "title": "basic follow" }, + { "file": "camera+cull.js", "title": "camera cull" }, + { "file": "follow+styles.js", "title": "follow styles" }, + { "file": "moving+the+camera.js", "title": "moving the camera" }, + { "file": "world+sprite.js", "title": "world sprite" } +], +"collision": [ + { "file": "bounding+box.js", "title": "bounding box" }, + { "file": "group+vs+group.js", "title": "group vs group" }, + { "file": "larger+bounding+box.js", "title": "larger bounding box" }, + { "file": "offset+bounding+box.js", "title": "offset bounding box" }, + { "file": "sprite+tiles.js", "title": "sprite tiles" }, + { "file": "sprite+vs+group.js", "title": "sprite vs group" }, + { "file": "sprite+vs+sprite+custom.js", "title": "sprite vs sprite custom" }, + { "file": "sprite+vs+sprite.js", "title": "sprite vs sprite" }, + { "file": "transform.js", "title": "transform" }, + { "file": "vertical+collision.js", "title": "vertical collision" } +], +"display": [ + { "file": "fullscreen.js", "title": "fullscreen" }, + { "file": "graphics.js", "title": "graphics" }, + { "file": "render+crisp.js", "title": "render crisp" } +], +"geometry": [ + { "file": "circle.js", "title": "circle" }, + { "file": "line.js", "title": "line" }, + { "file": "playing+with+points.js", "title": "playing with points" }, + { "file": "rectangle.js", "title": "rectangle" }, + { "file": "rotate+point.js", "title": "rotate point" } +], +"groups": [ + { "file": "add+a+sprite+to+group.js", "title": "add a sprite to group" }, + { "file": "bring+a+child+to+top.js", "title": "bring a child to top" }, + { "file": "bring+a+group+to+top.js", "title": "bring a group to top" }, + { "file": "call+all.js", "title": "call all" }, + { "file": "create+group.js", "title": "create group" }, + { "file": "create+sprite+in+a+group.js", "title": "create sprite in a group" }, + { "file": "display+order.js", "title": "display order" }, + { "file": "for+each.js", "title": "for each" }, + { "file": "get+first.js", "title": "get first" }, + { "file": "group+as+layer.js", "title": "group as layer" }, + { "file": "group+transform+-+rotate.js", "title": "group transform - rotate" }, + { "file": "group+transform+-+tween.js", "title": "group transform - tween" }, + { "file": "group+transform.js", "title": "group transform" }, + { "file": "recyling.js", "title": "recyling" }, + { "file": "remove.js", "title": "remove" }, + { "file": "replace.js", "title": "replace" }, + { "file": "set+All.js", "title": "set All" }, + { "file": "sub+groups+-+group+length.js", "title": "sub groups - group length" }, + { "file": "swap+children+in+a+group.js", "title": "swap children in a group" } +], +"input": [ + { "file": "cursor+key+movement.js", "title": "cursor key movement" }, + { "file": "drag+several+sprites.js", "title": "drag several sprites" }, + { "file": "drag.js", "title": "drag" }, + { "file": "drop+limitation.js", "title": "drop limitation" }, + { "file": "follow+mouse.js", "title": "follow mouse" }, + { "file": "game+scale.js", "title": "game scale" }, + { "file": "key.js", "title": "key" }, + { "file": "keyboard+hotkeys.js", "title": "keyboard hotkeys" }, + { "file": "keyboard+justpressed.js", "title": "keyboard justpressed" }, + { "file": "keyboard.js", "title": "keyboard" }, + { "file": "motion+lock+-+horizontal.js", "title": "motion lock - horizontal" }, + { "file": "motion+lock+-+vertical.js", "title": "motion lock - vertical" }, + { "file": "multi+touch.js", "title": "multi touch" }, + { "file": "override+default+controls.js", "title": "override default controls" }, + { "file": "pixel+perfect+click+detection.js", "title": "pixel perfect click detection" }, + { "file": "pixelpick+-+scrolling+effect.js", "title": "pixelpick - scrolling effect" }, + { "file": "pixelpick+-+spritesheet.js", "title": "pixelpick - spritesheet" }, + { "file": "snap+on+drag.js", "title": "snap on drag" } +], +"loader": [ + { "file": "pick+images+from+cache.js", "title": "pick images from cache" } +], +"misc": [ + { "file": "net.js", "title": "net" }, + { "file": "random+generators.js", "title": "random generators" }, + { "file": "repeatable+random+numbers.js", "title": "repeatable random numbers" } +], +"particles": [ + { "file": "click+burst.js", "title": "click burst" }, + { "file": "collision.js", "title": "collision" }, + { "file": "diamond+burst.js", "title": "diamond burst" }, + { "file": "no+rotation.js", "title": "no rotation" }, + { "file": "random+sprite.js", "title": "random sprite" }, + { "file": "when+particles+collide.js", "title": "when particles collide" }, + { "file": "zero+gravity.js", "title": "zero gravity" } +], +"physics": [ + { "file": "accelerate+to+pointer.js", "title": "accelerate to pointer" }, + { "file": "angle+between.js", "title": "angle between" }, + { "file": "angle+to+pointer.js", "title": "angle to pointer" }, + { "file": "angular+acceleration.js", "title": "angular acceleration" }, + { "file": "angular+velocity.js", "title": "angular velocity" }, + { "file": "mass+velocity+test.js", "title": "mass velocity test" }, + { "file": "move+towards+object.js", "title": "move towards object" }, + { "file": "multi+angle+to+pointer.js", "title": "multi angle to pointer" }, + { "file": "quadtree+-+collision+infos.js", "title": "quadtree - collision infos" }, + { "file": "quadtree+-+ids.js", "title": "quadtree - ids" }, + { "file": "shoot+the+pointer.js", "title": "shoot the pointer" }, + { "file": "sprite+bounds.js", "title": "sprite bounds" } +], +"sprites": [ + { "file": "add+a+sprite.js", "title": "add a sprite" }, + { "file": "add+several+sprites.js", "title": "add several sprites" }, + { "file": "collide+world+bounds.js", "title": "collide world bounds" }, + { "file": "destroy.js", "title": "destroy" }, + { "file": "dynamic+crop.js", "title": "dynamic crop" }, + { "file": "extending+sprite+demo+1.js", "title": "extending sprite demo 1" }, + { "file": "extending+sprite+demo+2.js", "title": "extending sprite demo 2" }, + { "file": "horizontal+crop.js", "title": "horizontal crop" }, + { "file": "move+a+sprite.js", "title": "move a sprite" }, + { "file": "out+of+bounds.js", "title": "out of bounds" }, + { "file": "scale+a+sprite.js", "title": "scale a sprite" }, + { "file": "shared+sprite+textures.js", "title": "shared sprite textures" }, + { "file": "sprite+rotation.js", "title": "sprite rotation" }, + { "file": "spritesheet.js", "title": "spritesheet" }, + { "file": "vertical+crop.js", "title": "vertical crop" } +], +"text": [ + { "file": "bitmap+fonts.js", "title": "bitmap fonts" }, + { "file": "hello+arial.js", "title": "hello arial" }, + { "file": "kern+of+duty.js", "title": "kern of duty" }, + { "file": "remove+text.js", "title": "remove text" }, + { "file": "text+stroke.js", "title": "text stroke" } +], +"tile sprites": [ + { "file": "animated+tiling+sprite.js", "title": "animated tiling sprite" }, + { "file": "tiling+sprite.js", "title": "tiling sprite" } +], +"tilemaps": [ + { "file": "fill+tiles.js", "title": "fill tiles" }, + { "file": "mapcollide.js", "title": "mapcollide" }, + { "file": "mario.js", "title": "mario" }, + { "file": "mariotogether.js", "title": "mariotogether" }, + { "file": "paint+tiles.js", "title": "paint tiles" }, + { "file": "randomise+tiles.js", "title": "randomise tiles" }, + { "file": "replace+tiles.js", "title": "replace tiles" }, + { "file": "sci+fly.js", "title": "sci fly" }, + { "file": "supermario.js", "title": "supermario" }, + { "file": "supermario2.js", "title": "supermario2" }, + { "file": "swap+tiles.js", "title": "swap tiles" }, + { "file": "wip1.js", "title": "wip1" }, + { "file": "wip2.js", "title": "wip2" }, + { "file": "wip3.js", "title": "wip3" }, + { "file": "wip4.js", "title": "wip4" } +], +"tweens": [ + { "file": "bounce.js", "title": "bounce" }, + { "file": "bubbles.js", "title": "bubbles" }, + { "file": "chained+tweens.js", "title": "chained tweens" }, + { "file": "combined+tweens.js", "title": "combined tweens" }, + { "file": "easing+spritesheets.js", "title": "easing spritesheets" }, + { "file": "easing.js", "title": "easing" }, + { "file": "fading+in+a+sprite.js", "title": "fading in a sprite" }, + { "file": "pause+tween.js", "title": "pause tween" }, + { "file": "tween+several+properties.js", "title": "tween several properties" } +], +"world": [ + { "file": "fixed+to+camera.js", "title": "fixed to camera" }, + { "file": "move+around+world.js", "title": "move around world" } +] } \ No newline at end of file diff --git a/examples/audio/pause and resume.js b/examples/audio/pause and resume.js new file mode 100644 index 00000000..bc9ef2b9 --- /dev/null +++ b/examples/audio/pause and resume.js @@ -0,0 +1,51 @@ + +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render }); + +function preload() { + + game.load.image('disk', 'assets/sprites/ra_dont_crack_under_pressure.png'); + + // Firefox doesn't support mp3 files, so use ogg + game.load.audio('boden', ['assets/audio/bodenstaendig_2000_in_rock_4bit.mp3', 'assets/audio/bodenstaendig_2000_in_rock_4bit.ogg']); + +} + +var s; +var music; + +function create() { + + game.stage.backgroundColor = '#182d3b'; + game.input.touch.preventDefault = false; + + music = game.add.audio('boden'); + music.play(); + + s = game.add.sprite(game.world.centerX, game.world.centerY, 'disk'); + s.anchor.setTo(0.5, 0.5); + + game.input.onDown.add(changeVolume, this); + +} + +function changeVolume(pointer) { + + if (pointer.y < 300) + { + music.pause(); + } + else + { + music.resume(); + } + +} + +function update() { + s.rotation += 0.01; +} + +function render() { + game.debug.renderSoundInfo(music, 20, 32); +} + diff --git a/examples/sprites/dynamic crop.js b/examples/sprites/dynamic crop.js index 7707aedc..9922d0a0 100644 --- a/examples/sprites/dynamic crop.js +++ b/examples/sprites/dynamic crop.js @@ -1,29 +1,35 @@ -var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update }); +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render }); function preload() { game.load.image('trsi', 'assets/pics/trsipic1_lazur.jpg'); } -var r; var pic; function create() { pic = game.add.sprite(0, 0, 'trsi'); - r = new Phaser.Rectangle(0, 0, 200, 200); + pic.cropEnabled = true; + + pic.crop.width = 128; + pic.crop.height = 128; } function update() { - r.x = game.input.x; - r.y = game.input.y; pic.x = game.input.x; pic.y = game.input.y; - // Apply the new crop Rectangle to the sprite - pic.crop = r; + pic.crop.x = game.input.x; + pic.crop.y = game.input.y; + +} + +function render() { + + game.debug.renderText('x: ' + game.input.x + ' y: ' + game.input.y, 32, 32); } diff --git a/examples/sprites/horizontal crop.js b/examples/sprites/horizontal crop.js index 74dcdd02..77f66dc7 100644 --- a/examples/sprites/horizontal crop.js +++ b/examples/sprites/horizontal crop.js @@ -1,27 +1,23 @@ -var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update }); +var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create }); function preload() { game.load.image('trsi', 'assets/pics/trsipic1_lazur.jpg'); } -var r; -var pic; - function create() { - pic = game.add.sprite(game.world.centerX, 550, 'trsi'); + var pic = game.add.sprite(game.world.centerX, 550, 'trsi'); + pic.anchor.setTo(0.5, 1); + + // By default Sprites ignore the crop setting, you have to explicitly enable it like this: + pic.cropEnabled = true; - r = new Phaser.Rectangle(0, 0, 200, pic.height); + // Set the crop rect width to zero + pic.crop.width = 0; - game.add.tween(r).to( { x: pic.width - 200 }, 3000, Phaser.Easing.Bounce.Out, true, 0, 1000, true); - -} - -function update() { - - // Apply the new crop Rectangle to the sprite - pic.crop = r; + // Here we'll tween the crop rect, from a width of zero to full width, and back again + game.add.tween(pic.crop).to( { width: pic.width }, 3000, Phaser.Easing.Bounce.Out, true, 0, 1000, true); } diff --git a/examples/sprites/vertical crop.js b/examples/sprites/vertical crop.js index 83590cc1..09bd2887 100644 --- a/examples/sprites/vertical crop.js +++ b/examples/sprites/vertical crop.js @@ -1,27 +1,23 @@ -var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update }); +var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create }); function preload() { game.load.image('trsi', 'assets/pics/trsipic1_lazur.jpg'); } -var r; -var pic; - function create() { - pic = game.add.sprite(game.world.centerX, 550, 'trsi'); + var pic = game.add.sprite(game.world.centerX, 550, 'trsi'); + pic.anchor.setTo(0.5, 1); - r = new Phaser.Rectangle(0, 0, pic.width, 0); + // By default Sprites ignore the crop setting, you have to explicitly enable it like this: + pic.cropEnabled = true; - game.add.tween(r).to( { height: pic.height }, 3000, Phaser.Easing.Bounce.Out, true, 0, 1000, true); - -} - -function update() { - - // Apply the new crop Rectangle to the sprite - pic.crop = r; + // Set the crop rect height to zero + pic.crop.height = 0; + + // Here we'll tween the crop rect, from a height of zero to full height, and back again + game.add.tween(pic.crop).to( { height: pic.height }, 3000, Phaser.Easing.Bounce.Out, true, 0, 1000, true); } diff --git a/examples/wip/crop.js b/examples/wip/crop.js new file mode 100644 index 00000000..f6f846a0 --- /dev/null +++ b/examples/wip/crop.js @@ -0,0 +1,24 @@ + +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update }); + +function preload() { + + game.load.image('atari1', 'assets/sprites/atari130xe.png'); + +} + +var atari; + +function create() { + + atari = game.add.sprite(300, 300, 'atari1'); + + // atari.crop = new Phaser.Rectangle(0, 0, 10, atari.height); + +} + +function update() { + + atari.crop.width -= 1; + +} diff --git a/examples/wip/input active.js b/examples/wip/input active.js new file mode 100644 index 00000000..71e00e67 --- /dev/null +++ b/examples/wip/input active.js @@ -0,0 +1,39 @@ + +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create }); + +function preload() { + + game.load.image('atari1', 'assets/sprites/atari130xe.png'); + game.load.image('coke', 'assets/sprites/cokecan.png'); + game.load.image('mushroom', 'assets/sprites/mushroom2.png'); + +} + +var dropper; + +function create() { + + dropper = game.add.sprite(200, 400, 'mushroom'); + dropper.inputEnabled = true; + dropper.input.enableDrag(); + dropper.events.onDragStart.add(prepareToKill, this); + +} + +function prepareToKill() { + + console.log('3 sec warning'); + + var t = { time: 0 }; + + var tween = game.add.tween(t).to({time: 1}, 3000, Phaser.Easing.Linear.None, true); + tween.onComplete.add(nukeIt, this); + +} + +function nukeIt() { + + console.log('nuked'); + dropper.destroy(); + +} diff --git a/src/animation/Animation.js b/src/animation/Animation.js index 1620b38a..ff95fd72 100644 --- a/src/animation/Animation.js +++ b/src/animation/Animation.js @@ -406,33 +406,55 @@ Object.defineProperty(Phaser.Animation.prototype, "frame", { * * @method Phaser.Animation.generateFrameNames * @param {string} prefix - The start of the filename. If the filename was 'explosion_0001-large' the prefix would be 'explosion_'. -* @param {number} min - The number to start sequentially counting from. If your frames are named 'explosion_0001' to 'explosion_0034' the min is 1. -* @param {number} max - The number to count up to. If your frames are named 'explosion_0001' to 'explosion_0034' the max is 34. +* @param {number} start - The number to start sequentially counting from. If your frames are named 'explosion_0001' to 'explosion_0034' the start is 1. +* @param {number} stop - The number to count to. If your frames are named 'explosion_0001' to 'explosion_0034' the stop value is 34. * @param {string} [suffix=''] - The end of the filename. If the filename was 'explosion_0001-large' the prefix would be '-large'. * @param {number} [zeroPad=0] - The number of zeroes to pad the min and max values with. If your frames are named 'explosion_0001' to 'explosion_0034' then the zeroPad is 4. */ -Phaser.Animation.generateFrameNames = function (prefix, min, max, suffix, zeroPad) { +Phaser.Animation.generateFrameNames = function (prefix, start, stop, suffix, zeroPad) { if (typeof suffix == 'undefined') { suffix = ''; } var output = []; var frame = ''; - for (var i = min; i <= max; i++) + if (start < stop) { - if (typeof zeroPad == 'number') + for (var i = start; i <= stop; i++) { - // str, len, pad, dir - frame = Phaser.Utils.pad(i.toString(), zeroPad, '0', 1); + if (typeof zeroPad == 'number') + { + // str, len, pad, dir + frame = Phaser.Utils.pad(i.toString(), zeroPad, '0', 1); + } + else + { + frame = i.toString(); + } + + frame = prefix + frame + suffix; + + output.push(frame); } - else + } + else + { + for (var i = start; i >= stop; i--) { - frame = i.toString(); + if (typeof zeroPad == 'number') + { + // str, len, pad, dir + frame = Phaser.Utils.pad(i.toString(), zeroPad, '0', 1); + } + else + { + frame = i.toString(); + } + + frame = prefix + frame + suffix; + + output.push(frame); } - - frame = prefix + frame + suffix; - - output.push(frame); } return output; diff --git a/src/core/Game.js b/src/core/Game.js index 83d0e0de..02b40049 100644 --- a/src/core/Game.js +++ b/src/core/Game.js @@ -426,6 +426,10 @@ Phaser.Game.prototype = { */ destroy: function () { + this.raf.stop(); + + this.input.destroy(); + this.state.destroy(); this.state = null; diff --git a/src/gameobjects/Sprite.js b/src/gameobjects/Sprite.js index f5203ded..2b468454 100644 --- a/src/gameobjects/Sprite.js +++ b/src/gameobjects/Sprite.js @@ -144,20 +144,6 @@ Phaser.Sprite = function (game, x, y, key, frame) { */ this.anchor = new Phaser.Point(); - /** - * @property {Description} _cropUUID - Description. - * @private - * @default - */ - this._cropUUID = null; - - /** - * @property {Description} _cropUUID - Description. - * @private - * @default - */ - this._cropRect = null; - /** * @property {number} x - Description. */ @@ -225,7 +211,10 @@ Phaser.Sprite = function (game, x, y, key, frame) { boundsX: 0, boundsY: 0, // If this sprite visible to the camera (regardless of being set to visible or not) - cameraVisible: true + cameraVisible: true, + + // Crop cache + cropX: 0, cropY: 0, cropWidth: this.currentFrame.sourceSizeW, cropHeight: this.currentFrame.sourceSizeH }; @@ -305,6 +294,9 @@ Phaser.Sprite = function (game, x, y, key, frame) { */ this.fixedToCamera = false; + this.crop = new Phaser.Rectangle(0, 0, this._cache.width, this._cache.height); + this.cropEnabled = false; + }; // Needed to keep the PIXI.Sprite constructor in the prototype chain (as the core pixi renderer uses an instanceof check sadly) @@ -352,6 +344,11 @@ Phaser.Sprite.prototype.preUpdate = function() { this.updateCache(); this.updateAnimation(); + if (this.cropEnabled) + { + this.updateCrop(); + } + // Re-run the camera visibility check if (this._cache.dirty) { @@ -436,6 +433,37 @@ Phaser.Sprite.prototype.updateAnimation = function() { } +Phaser.Sprite.prototype.updateCrop = function() { + + // This only runs if crop is enabled + if (this.crop.width != this._cache.cropWidth || this.crop.height != this._cache.cropHeight || this.crop.x != this._cache.cropX || this.crop.y != this._cache.cropY) + { + this.crop.floorAll(); + + this._cache.cropX = this.crop.x; + this._cache.cropY = this.crop.y; + this._cache.cropWidth = this.crop.width; + this._cache.cropHeight = this.crop.height; + + this.texture.frame = this.crop; + this.texture.width = this.crop.width; + this.texture.height = this.crop.height; + + this.texture.updateFrame = true; + + PIXI.Texture.frameUpdates.push(this.texture); + } + +} + +Phaser.Sprite.prototype.resetCrop = function() { + + this.crop = new Phaser.Rectangle(0, 0, this._cache.width, this._cache.height); + this.texture.setFrame(this.crop); + this.cropEnabled = false; + +} + Phaser.Sprite.prototype.postUpdate = function() { if (this.exists) @@ -586,9 +614,20 @@ Phaser.Sprite.prototype.destroy = function() { this.group.remove(this); } - this.input.destroy(); - this.events.destroy(); - this.animations.destroy(); + if (this.input) + { + this.input.destroy(); + } + + if (this.events) + { + this.events.destroy(); + } + + if (this.animations) + { + this.animations.destroy(); + } this.alive = false; this.exists = false; @@ -847,56 +886,39 @@ Object.defineProperty(Phaser.Sprite.prototype, "inCamera", { }); /** -* Get the input enabled state of this Sprite. -* @returns {Description} -*//** -* Set the ability for this sprite to receive input events. -* @param {Description} value - Description -*/ -Object.defineProperty(Phaser.Sprite.prototype, "crop", { - - get: function () { - - return this._cropRect; + * The width of the sprite, setting this will actually modify the scale to acheive the value set + * + * @property width + * @type Number + */ +Object.defineProperty(Phaser.Sprite.prototype, 'width', { + get: function() { + return this.scale.x * this.currentFrame.width; }, - set: function (value) { + set: function(value) { + this.scale.x = value / this.currentFrame.width + this._width = value; + } - if (value instanceof Phaser.Rectangle) - { - if (this._cropUUID == null) - { - this._cropUUID = this.game.rnd.uuid(); +}); - PIXI.TextureCache[this._cropUUID] = new PIXI.Texture(PIXI.BaseTextureCache[this.key], { - x: Math.floor(value.x), - y: Math.floor(value.y), - width: Math.floor(value.width), - height: Math.floor(value.height) - }); - } - else - { - PIXI.TextureCache[this._cropUUID].frame = value; - } +/** + * The height of the sprite, setting this will actually modify the scale to acheive the value set + * + * @property height + * @type Number + */ +Object.defineProperty(Phaser.Sprite.prototype, 'height', { - this._cropRect = value; - this.setTexture(PIXI.TextureCache[this._cropUUID]); - } - else - { - this._cropRect = null; + get: function() { + return this.scale.y * this.currentFrame.height; + }, - if (this.animations.isLoaded) - { - this.animations.refreshFrame(); - } - else - { - this.setTexture(PIXI.TextureCache[this.key]); - } - } + set: function(value) { + this.scale.y = value / this.currentFrame.height + this._height = value; } }); diff --git a/src/geom/Rectangle.js b/src/geom/Rectangle.js index 5b63e421..6890a2a8 100644 --- a/src/geom/Rectangle.js +++ b/src/geom/Rectangle.js @@ -103,6 +103,19 @@ Phaser.Rectangle.prototype = { }, + /** + * Runs Math.floor() on the x, y, width and height values of this Rectangle. + * @method Phaser.Rectangle#floorAll + **/ + floorAll: function () { + + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.width = Math.floor(this.width); + this.height = Math.floor(this.height); + + }, + /** * Copies the x, y, width and height properties from any given object to this Rectangle. * @method Phaser.Rectangle#copyFrom diff --git a/src/input/Input.js b/src/input/Input.js index efe1f7b0..acc9cda9 100644 --- a/src/input/Input.js +++ b/src/input/Input.js @@ -395,6 +395,19 @@ Phaser.Input.prototype = { this.mspointer.start(); this.mousePointer.active = true; + }, + + /** + * Stops all of the Input Managers from running. + * @method Phaser.Input#destroy + */ + destroy: function () { + + this.mouse.stop(); + this.keyboard.stop(); + this.touch.stop(); + this.mspointer.stop(); + }, /** @@ -681,28 +694,6 @@ Phaser.Input.prototype = { return null; - }, - - /** - * Get the distance between two Pointer objects. - * @method Phaser.Input#getDistance - * @param {Pointer} pointer1 - * @param {Pointer} pointer2 - * @return {Description} Description. - */ - getDistance: function (pointer1, pointer2) { - // return Phaser.Vec2Utils.distance(pointer1.position, pointer2.position); - }, - - /** - * Get the angle between two Pointer objects. - * @method Phaser.Input#getAngle - * @param {Pointer} pointer1 - * @param {Pointer} pointer2 - * @return {Description} Description. - */ - getAngle: function (pointer1, pointer2) { - // return Phaser.Vec2Utils.angle(pointer1.position, pointer2.position); } }; diff --git a/src/input/InputHandler.js b/src/input/InputHandler.js index 985f8af1..cd2b0178 100644 --- a/src/input/InputHandler.js +++ b/src/input/InputHandler.js @@ -306,10 +306,13 @@ Phaser.InputHandler.prototype = { if (this.enabled) { + this.enabled = false; + + this.game.input.interactiveItems.remove(this); + this.stop(); - // Null everything + this.sprite = null; - // etc } }, @@ -615,7 +618,10 @@ Phaser.InputHandler.prototype = { this.game.stage.canvas.style.cursor = "default"; } - this.sprite.events.onInputOut.dispatch(this.sprite, pointer); + if (this.sprite && this.sprite.events) + { + this.sprite.events.onInputOut.dispatch(this.sprite, pointer); + } }, diff --git a/src/input/Pointer.js b/src/input/Pointer.js index 950c8bf6..2558d1a7 100644 --- a/src/input/Pointer.js +++ b/src/input/Pointer.js @@ -281,7 +281,7 @@ Phaser.Pointer.prototype = { this.game.input.x = this.x * this.game.input.scale.x; this.game.input.y = this.y * this.game.input.scale.y; this.game.input.position.setTo(this.x, this.y); - this.game.input.onDown.dispatch(this); + this.game.input.onDown.dispatch(this, event); this.game.input.resetSpeed(this.x, this.y); } @@ -506,7 +506,7 @@ Phaser.Pointer.prototype = { if (this.game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this.game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this.game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this.game.input.currentPointers == 0)) { - this.game.input.onUp.dispatch(this); + this.game.input.onUp.dispatch(this, event); // Was it a tap? if (this.duration >= 0 && this.duration <= this.game.input.tapRate) diff --git a/src/loader/Loader.js b/src/loader/Loader.js index 4402f1ac..dabdcb50 100644 --- a/src/loader/Loader.js +++ b/src/loader/Loader.js @@ -161,6 +161,7 @@ Phaser.Loader.prototype = { } sprite.crop = this.preloadSprite.crop; + sprite.cropEnabled = true; }, @@ -935,7 +936,7 @@ Phaser.Loader.prototype = { break; case 'text': - file.data = this._xhr.response; + file.data = this._xhr.responseText; this.game.cache.addText(file.key, file.url, file.data); break; } @@ -955,7 +956,7 @@ Phaser.Loader.prototype = { */ jsonLoadComplete: function (key) { - var data = JSON.parse(this._xhr.response); + var data = JSON.parse(this._xhr.responseText); var file = this._fileList[key]; if (file.type == 'tilemap') @@ -979,7 +980,7 @@ Phaser.Loader.prototype = { */ csvLoadComplete: function (key) { - var data = this._xhr.response; + var data = this._xhr.responseText; var file = this._fileList[key]; this.game.cache.addTilemap(file.key, file.url, data, file.format); @@ -1014,7 +1015,7 @@ Phaser.Loader.prototype = { */ xmlLoadComplete: function (key) { - var data = this._xhr.response; + var data = this._xhr.responseText; var xml; try diff --git a/src/sound/Sound.js b/src/sound/Sound.js index bbd5948d..32193c09 100644 --- a/src/sound/Sound.js +++ b/src/sound/Sound.js @@ -118,8 +118,7 @@ Phaser.Sound = function (game, key, volume, loop) { /** * Description. - * @property {number} autoplay - * @default + * @property {number} stopTime */ this.stopTime = 0; @@ -130,6 +129,18 @@ Phaser.Sound = function (game, key, volume, loop) { */ this.paused = false; + /** + * Description. + * @property {number} pausedPosition + */ + this.pausedPosition = 0; + + /** + * Description. + * @property {number} pausedTime + */ + this.pausedTime = 0; + /** * Description. * @property {boolean} isPlaying @@ -627,10 +638,13 @@ Phaser.Sound.prototype = { this.stop(); this.isPlaying = false; this.paused = true; + this.pausedPosition = this.currentTime; + this.pausedTime = this.game.time.now; this.onPause.dispatch(this); } }, + /** * Resumes the sound * @method Phaser.Sound#resume @@ -641,14 +655,20 @@ Phaser.Sound.prototype = { { if (this.usingWebAudio) { + var p = this.position + (this.pausedPosition / 1000); + + this._sound = this.context.createBufferSource(); + this._sound.buffer = this._buffer; + this._sound.connect(this.gainNode); + if (typeof this._sound.start === 'undefined') { - this._sound.noteGrainOn(0, this.position, this.duration); + this._sound.noteGrainOn(0, p, this.duration); //this._sound.noteOn(0); // the zero is vitally important, crashes iOS6 without it } else { - this._sound.start(0, this.position, this.duration); + this._sound.start(0, p, this.duration); } } else @@ -658,6 +678,7 @@ Phaser.Sound.prototype = { this.isPlaying = true; this.paused = false; + this.startTime += (this.game.time.now - this.pausedTime); this.onResume.dispatch(this); }