diff --git a/Phaser.sublime-workspace b/Phaser.sublime-workspace
index 6161cc60..5c8d6953 100644
--- a/Phaser.sublime-workspace
+++ b/Phaser.sublime-workspace
@@ -3,6 +3,70 @@
{
"selected_items":
[
+ [
+ "bot",
+ "bottomLeft"
+ ],
+ [
+ "be",
+ "beginPath"
+ ],
+ [
+ "show",
+ "showBounds"
+ ],
+ [
+ "cam",
+ "cameraVisible"
+ ],
+ [
+ "fr",
+ "frameHeight (variable)"
+ ],
+ [
+ "bott",
+ "bottomRight (variable)"
+ ],
+ [
+ "up",
+ "updateBounds"
+ ],
+ [
+ "top",
+ "topRight"
+ ],
+ [
+ "bottom",
+ "bottomLeft"
+ ],
+ [
+ "renderp",
+ "renderPoint"
+ ],
+ [
+ "ren",
+ "renderRectangle (function)"
+ ],
+ [
+ "sc",
+ "scaleY"
+ ],
+ [
+ "scal",
+ "scaleX"
+ ],
+ [
+ "frame",
+ "frameIndex"
+ ],
+ [
+ "_p",
+ "_py"
+ ],
+ [
+ "upda",
+ "updateOnVisible"
+ ],
[
"scale",
"scale1Y"
@@ -23,10 +87,6 @@
"displ",
"displayObject"
],
- [
- "bott",
- "bottomRight"
- ],
[
"off",
"offset"
@@ -175,10 +235,6 @@
"onpause",
"onPausedCallback"
],
- [
- "upda",
- "updateSetTimeout"
- ],
[
"inter",
"intersectsRaw"
@@ -395,18 +451,10 @@
"let",
"letter1"
],
- [
- "sc",
- "scanIt"
- ],
[
"pro",
"progressFill"
],
- [
- "up",
- "update"
- ],
[
"deli",
"delivery1"
@@ -466,100 +514,11 @@
[
"scr",
"scrollUp"
- ],
- [
- "shad",
- "shadowFloatY"
- ],
- [
- "pau",
- "pauseScreen"
- ],
- [
- "ne",
- "nextRound"
- ],
- [
- "sha",
- "shadow"
- ],
- [
- "flo",
- "floatOff"
- ],
- [
- "pip",
- "piplin1"
- ],
- [
- "tw",
- "tween"
- ],
- [
- "rou",
- "round"
- ],
- [
- "time",
- "timeToShine"
- ],
- [
- "shado",
- "shadowY"
- ],
- [
- "shi",
- "shine"
- ],
- [
- "shin",
- "shineY"
]
]
},
"buffers":
[
- {
- "file": "src/gameobjects/Sprite.js",
- "settings":
- {
- "buffer_size": 9442,
- "line_ending": "Windows"
- }
- },
- {
- "file": "src/core/World.js",
- "settings":
- {
- "buffer_size": 2868,
- "line_ending": "Windows"
- }
- },
- {
- "file": "TS Source/math/QuadTree.js",
- "settings":
- {
- "buffer_size": 18663,
- "line_ending": "Windows"
- }
- },
- {
- "file": "src/math/QuadTree.js",
- "settings":
- {
- "buffer_size": 1014,
- "line_ending": "Windows",
- "name": "Phaser.QuadTree = function () {"
- }
- },
- {
- "file": "src/pixi/display/Sprite.js",
- "settings":
- {
- "buffer_size": 4817,
- "line_ending": "Windows"
- }
- }
],
"build_system": "",
"command_palette":
@@ -589,23 +548,29 @@
},
"file_history":
[
+ "/D/wamp/www/phaser/src/math/QuadTree.js",
+ "/D/wamp/www/phaser/TS Source/math/QuadTree.js",
+ "/D/wamp/www/phaser/src/animation/AnimationManager.js",
+ "/D/wamp/www/phaser/src/gameobjects/Sprite.js",
+ "/D/wamp/www/phaser/src/utils/Debug.js",
+ "/D/wamp/www/phaser/src/core/World.js",
+ "/D/wamp/www/phaser/src/pixi/display/Stage.js",
+ "/D/wamp/www/phaser/examples/camera_cull1.php",
+ "/D/wamp/www/phaser/src/pixi/renderers/canvas/CanvasRenderer.js",
+ "/D/wamp/www/phaser/src/pixi/display/DisplayObjectContainer.js",
+ "/D/wamp/www/phaser/src/pixi/display/DisplayObject.js",
+ "/D/wamp/www/phaser/src/pixi/display/Sprite.js",
+ "/D/wamp/www/bbc-wolfblood/assets/1024/help/help_titles.json",
"/D/wamp/www/phaser/src/math/LinkedList.js",
"/D/wamp/www/phaser/TS Source/math/LinkedList.js",
- "/D/wamp/www/phaser/src/pixi/display/DisplayObject.js",
- "/D/wamp/www/phaser/src/pixi/display/DisplayObjectContainer.js",
- "/D/wamp/www/phaser/src/pixi/display/Sprite.js",
- "/D/wamp/www/phaser/src/animation/AnimationManager.js",
"/D/wamp/www/phaser/src/animation/Frame.js",
"/D/wamp/www/phaser/src/animation/Parser.js",
"/D/wamp/www/phaser/examples/camera4.php",
"/D/wamp/www/phaser/src/core/Game.js",
"/D/wamp/www/phaser/examples/sprite3.php",
"/D/wamp/www/phaser/examples/camera5.php",
- "/D/wamp/www/phaser/src/utils/Debug.js",
"/D/wamp/www/phaser/src/pixi/InteractionManager.js",
"/D/wamp/www/pixi.js/examples/example 6 - Interactivity/index.html",
- "/D/wamp/www/phaser/src/pixi/renderers/canvas/CanvasRenderer.js",
- "/D/wamp/www/phaser/src/core/World.js",
"/D/wamp/www/phaser/src/math/Math.js",
"/D/wamp/www/phaser/src/geom/Point.js",
"/D/wamp/www/phaser/src/input/Input.js",
@@ -629,7 +594,6 @@
"/D/wamp/www/phaser/TS Source/input/Pointer.js",
"/D/wamp/www/phaser/TS Source/input/Touch.js",
"/D/wamp/www/phaser/TS Source/input/MSPointer.js",
- "/D/wamp/www/phaser/src/gameobjects/Sprite.js",
"/D/wamp/www/phaser/TS Source/cameras/Camera.js",
"/D/wamp/www/phaser/examples/camera1.php",
"/D/wamp/www/phaser/TS Source/input/Mouse.js",
@@ -677,7 +641,6 @@
"/D/wamp/www/phaser/TS Source/World.js",
"/D/wamp/www/phaser/src/Game.js",
"/D/wamp/www/phaser/src/Stage.js",
- "/D/wamp/www/phaser/src/pixi/display/Stage.js",
"/D/wamp/www/phaser/examples/pixi 1.html",
"/D/wamp/www/phaser/src/system/Canvas.js",
"/D/wamp/www/phaser/src/Phaser.js",
@@ -712,11 +675,7 @@
"/D/wamp/www/phaser/src/time/Time.js",
"/D/wamp/www/phaser/src/pixi/utils/Utils.js",
"/D/wamp/www/phaser/TS Source/system/RequestAnimationFrame.ts",
- "/D/wamp/www/phaser/todo/Tween.js",
- "/D/wamp/www/phaser/TS Source/tweens/TweenManager.js",
- "/D/wamp/www/phaser/TS Source/utils/RectangleUtils.js",
- "/D/wamp/www/phaser/TS Source/geom/Rectangle.js",
- "/D/wamp/www/phaser/examples/point.html"
+ "/D/wamp/www/phaser/todo/Tween.js"
],
"find":
{
@@ -724,7 +683,7 @@
},
"find_in_files":
{
- "height": 0.0,
+ "height": 90.0,
"where_history":
[
"D:\\wamp\\www\\phaser\\src\\pixi",
@@ -752,6 +711,25 @@
"case_sensitive": false,
"find_history":
[
+ "game.camera",
+ "\n ",
+ "moveTo",
+ "showText",
+ "sh",
+ "sw",
+ "this._dirty",
+ "X",
+ "x",
+ "X",
+ "x",
+ "this._",
+ "this._y",
+ "this._x",
+ "x",
+ "updateOnVisible",
+ "updateTransform",
+ "worldTransform",
+ "world",
"s.",
"actual",
"worldTransform",
@@ -860,26 +838,7 @@
"public ",
"startSt",
"_this",
- "Phaser.Math",
- "_raf",
- "raf",
- "delta",
- "_raf",
- "RequestAnimationFrame.prototype.",
- "TweenManager.prototype.",
- "Phaser.Rectangle.",
- "a.",
- "RectangleUtils",
- "defineProperty(Rectangle.prototype",
- "});",
- "x",
- "Rectangle.prototype.",
- "this.android",
- "dest",
- "this",
- "a",
- "*",
- "Point.prototype."
+ "Phaser.Math"
],
"highlight": true,
"in_selection": false,
@@ -887,6 +846,9 @@
"regex": false,
"replace_history":
[
+ "this._cache.dirty",
+ "this.y",
+ "this.x",
"Phaser.MSPointer",
"Phaser.Pointer",
"Phaser.Touch",
@@ -948,660 +910,8 @@
"groups":
[
{
- "selected": 2,
"sheets":
[
- {
- "buffer": 0,
- "file": "src/gameobjects/Sprite.js",
- "settings":
- {
- "buffer_size": 9442,
- "regions":
- {
- },
- "selection":
- [
- [
- 0,
- 0
- ]
- ],
- "settings":
- {
- "codeintel": true,
- "codeintel_config":
- {
- "JavaScript":
- {
- "codeintel_max_recursive_dir_depth": 2,
- "codeintel_scan_files_in_project": false,
- "javascriptExtraPaths":
- [
- ]
- },
- "PHP":
- {
- "codeintel_max_recursive_dir_depth": 5,
- "codeintel_scan_files_in_project": false,
- "phpExtraPaths":
- [
- ]
- },
- "Python":
- {
- "env":
- {
- }
- }
- },
- "codeintel_enabled_languages":
- [
- "JavaScript",
- "Mason",
- "XBL",
- "XUL",
- "RHTML",
- "SCSS",
- "Python",
- "HTML",
- "Ruby",
- "Python3",
- "XML",
- "Sass",
- "XSLT",
- "Django",
- "HTML5",
- "Perl",
- "CSS",
- "Twig",
- "Less",
- "Smarty",
- "Node.js",
- "Tcl",
- "TemplateToolkit",
- "PHP"
- ],
- "codeintel_live": true,
- "codeintel_live_enabled_languages":
- [
- "JavaScript",
- "Mason",
- "XBL",
- "XUL",
- "RHTML",
- "SCSS",
- "Python",
- "HTML",
- "Ruby",
- "Python3",
- "XML",
- "Sass",
- "XSLT",
- "Django",
- "HTML5",
- "Perl",
- "CSS",
- "Twig",
- "Less",
- "Smarty",
- "Node.js",
- "Tcl",
- "TemplateToolkit",
- "PHP"
- ],
- "codeintel_max_recursive_dir_depth": 10,
- "codeintel_scan_exclude_dir":
- {
- "JavaScript":
- [
- "/build/",
- "/min/"
- ]
- },
- "codeintel_scan_files_in_project": true,
- "codeintel_selected_catalogs":
- [
- "PyWin32",
- "jQuery",
- "Rails"
- ],
- "codeintel_snippets": true,
- "codeintel_syntax_map":
- {
- "Python Django": "Python"
- },
- "sublime_auto_complete": true,
- "syntax": "Packages/JavaScript/JavaScript.tmLanguage",
- "tab_size": 4,
- "translate_tabs_to_spaces": true
- },
- "translation.x": 0.0,
- "translation.y": 0.0,
- "zoom_level": 1.0
- },
- "type": "text"
- },
- {
- "buffer": 1,
- "file": "src/core/World.js",
- "settings":
- {
- "buffer_size": 2868,
- "regions":
- {
- },
- "selection":
- [
- [
- 149,
- 149
- ]
- ],
- "settings":
- {
- "codeintel": true,
- "codeintel_config":
- {
- "JavaScript":
- {
- "codeintel_max_recursive_dir_depth": 2,
- "codeintel_scan_files_in_project": false,
- "javascriptExtraPaths":
- [
- ]
- },
- "PHP":
- {
- "codeintel_max_recursive_dir_depth": 5,
- "codeintel_scan_files_in_project": false,
- "phpExtraPaths":
- [
- ]
- },
- "Python":
- {
- "env":
- {
- }
- }
- },
- "codeintel_enabled_languages":
- [
- "JavaScript",
- "Mason",
- "XBL",
- "XUL",
- "RHTML",
- "SCSS",
- "Python",
- "HTML",
- "Ruby",
- "Python3",
- "XML",
- "Sass",
- "XSLT",
- "Django",
- "HTML5",
- "Perl",
- "CSS",
- "Twig",
- "Less",
- "Smarty",
- "Node.js",
- "Tcl",
- "TemplateToolkit",
- "PHP"
- ],
- "codeintel_live": true,
- "codeintel_live_enabled_languages":
- [
- "JavaScript",
- "Mason",
- "XBL",
- "XUL",
- "RHTML",
- "SCSS",
- "Python",
- "HTML",
- "Ruby",
- "Python3",
- "XML",
- "Sass",
- "XSLT",
- "Django",
- "HTML5",
- "Perl",
- "CSS",
- "Twig",
- "Less",
- "Smarty",
- "Node.js",
- "Tcl",
- "TemplateToolkit",
- "PHP"
- ],
- "codeintel_max_recursive_dir_depth": 10,
- "codeintel_scan_exclude_dir":
- {
- "JavaScript":
- [
- "/build/",
- "/min/"
- ]
- },
- "codeintel_scan_files_in_project": true,
- "codeintel_selected_catalogs":
- [
- "PyWin32",
- "jQuery",
- "Rails"
- ],
- "codeintel_snippets": true,
- "codeintel_syntax_map":
- {
- "Python Django": "Python"
- },
- "sublime_auto_complete": true,
- "syntax": "Packages/JavaScript/JavaScript.tmLanguage"
- },
- "translation.x": 0.0,
- "translation.y": 0.0,
- "zoom_level": 1.0
- },
- "type": "text"
- },
- {
- "buffer": 2,
- "file": "TS Source/math/QuadTree.js",
- "settings":
- {
- "buffer_size": 18663,
- "regions":
- {
- },
- "selection":
- [
- [
- 1291,
- 1583
- ]
- ],
- "settings":
- {
- "codeintel": true,
- "codeintel_config":
- {
- "JavaScript":
- {
- "codeintel_max_recursive_dir_depth": 2,
- "codeintel_scan_files_in_project": false,
- "javascriptExtraPaths":
- [
- ]
- },
- "PHP":
- {
- "codeintel_max_recursive_dir_depth": 5,
- "codeintel_scan_files_in_project": false,
- "phpExtraPaths":
- [
- ]
- },
- "Python":
- {
- "env":
- {
- }
- }
- },
- "codeintel_enabled_languages":
- [
- "JavaScript",
- "Mason",
- "XBL",
- "XUL",
- "RHTML",
- "SCSS",
- "Python",
- "HTML",
- "Ruby",
- "Python3",
- "XML",
- "Sass",
- "XSLT",
- "Django",
- "HTML5",
- "Perl",
- "CSS",
- "Twig",
- "Less",
- "Smarty",
- "Node.js",
- "Tcl",
- "TemplateToolkit",
- "PHP"
- ],
- "codeintel_live": true,
- "codeintel_live_enabled_languages":
- [
- "JavaScript",
- "Mason",
- "XBL",
- "XUL",
- "RHTML",
- "SCSS",
- "Python",
- "HTML",
- "Ruby",
- "Python3",
- "XML",
- "Sass",
- "XSLT",
- "Django",
- "HTML5",
- "Perl",
- "CSS",
- "Twig",
- "Less",
- "Smarty",
- "Node.js",
- "Tcl",
- "TemplateToolkit",
- "PHP"
- ],
- "codeintel_max_recursive_dir_depth": 10,
- "codeintel_scan_exclude_dir":
- {
- "JavaScript":
- [
- "/build/",
- "/min/"
- ]
- },
- "codeintel_scan_files_in_project": true,
- "codeintel_selected_catalogs":
- [
- "PyWin32",
- "jQuery",
- "Rails"
- ],
- "codeintel_snippets": true,
- "codeintel_syntax_map":
- {
- "Python Django": "Python"
- },
- "sublime_auto_complete": true,
- "syntax": "Packages/JavaScript/JavaScript.tmLanguage",
- "tab_size": 4,
- "translate_tabs_to_spaces": true
- },
- "translation.x": 0.0,
- "translation.y": 0.0,
- "zoom_level": 1.0
- },
- "type": "text"
- },
- {
- "buffer": 3,
- "file": "src/math/QuadTree.js",
- "settings":
- {
- "buffer_size": 1014,
- "regions":
- {
- },
- "selection":
- [
- [
- 829,
- 829
- ]
- ],
- "settings":
- {
- "auto_name": "Phaser.QuadTree = function () {",
- "codeintel": true,
- "codeintel_config":
- {
- "JavaScript":
- {
- "codeintel_max_recursive_dir_depth": 2,
- "codeintel_scan_files_in_project": false,
- "javascriptExtraPaths":
- [
- ]
- },
- "PHP":
- {
- "codeintel_max_recursive_dir_depth": 5,
- "codeintel_scan_files_in_project": false,
- "phpExtraPaths":
- [
- ]
- },
- "Python":
- {
- "env":
- {
- }
- }
- },
- "codeintel_enabled_languages":
- [
- "JavaScript",
- "Mason",
- "XBL",
- "XUL",
- "RHTML",
- "SCSS",
- "Python",
- "HTML",
- "Ruby",
- "Python3",
- "XML",
- "Sass",
- "XSLT",
- "Django",
- "HTML5",
- "Perl",
- "CSS",
- "Twig",
- "Less",
- "Smarty",
- "Node.js",
- "Tcl",
- "TemplateToolkit",
- "PHP"
- ],
- "codeintel_live": true,
- "codeintel_live_enabled_languages":
- [
- "JavaScript",
- "Mason",
- "XBL",
- "XUL",
- "RHTML",
- "SCSS",
- "Python",
- "HTML",
- "Ruby",
- "Python3",
- "XML",
- "Sass",
- "XSLT",
- "Django",
- "HTML5",
- "Perl",
- "CSS",
- "Twig",
- "Less",
- "Smarty",
- "Node.js",
- "Tcl",
- "TemplateToolkit",
- "PHP"
- ],
- "codeintel_max_recursive_dir_depth": 10,
- "codeintel_scan_exclude_dir":
- {
- "JavaScript":
- [
- "/build/",
- "/min/"
- ]
- },
- "codeintel_scan_files_in_project": true,
- "codeintel_selected_catalogs":
- [
- "PyWin32",
- "jQuery",
- "Rails"
- ],
- "codeintel_snippets": true,
- "codeintel_syntax_map":
- {
- "Python Django": "Python"
- },
- "sublime_auto_complete": true,
- "syntax": "Packages/JavaScript/JavaScript.tmLanguage"
- },
- "translation.x": 0.0,
- "translation.y": 0.0,
- "zoom_level": 1.0
- },
- "type": "text"
- },
- {
- "buffer": 4,
- "file": "src/pixi/display/Sprite.js",
- "settings":
- {
- "buffer_size": 4817,
- "regions":
- {
- },
- "selection":
- [
- [
- 1861,
- 1861
- ]
- ],
- "settings":
- {
- "codeintel": true,
- "codeintel_config":
- {
- "JavaScript":
- {
- "codeintel_max_recursive_dir_depth": 2,
- "codeintel_scan_files_in_project": false,
- "javascriptExtraPaths":
- [
- ]
- },
- "PHP":
- {
- "codeintel_max_recursive_dir_depth": 5,
- "codeintel_scan_files_in_project": false,
- "phpExtraPaths":
- [
- ]
- },
- "Python":
- {
- "env":
- {
- }
- }
- },
- "codeintel_enabled_languages":
- [
- "JavaScript",
- "Mason",
- "XBL",
- "XUL",
- "RHTML",
- "SCSS",
- "Python",
- "HTML",
- "Ruby",
- "Python3",
- "XML",
- "Sass",
- "XSLT",
- "Django",
- "HTML5",
- "Perl",
- "CSS",
- "Twig",
- "Less",
- "Smarty",
- "Node.js",
- "Tcl",
- "TemplateToolkit",
- "PHP"
- ],
- "codeintel_live": true,
- "codeintel_live_enabled_languages":
- [
- "JavaScript",
- "Mason",
- "XBL",
- "XUL",
- "RHTML",
- "SCSS",
- "Python",
- "HTML",
- "Ruby",
- "Python3",
- "XML",
- "Sass",
- "XSLT",
- "Django",
- "HTML5",
- "Perl",
- "CSS",
- "Twig",
- "Less",
- "Smarty",
- "Node.js",
- "Tcl",
- "TemplateToolkit",
- "PHP"
- ],
- "codeintel_max_recursive_dir_depth": 10,
- "codeintel_scan_exclude_dir":
- {
- "JavaScript":
- [
- "/build/",
- "/min/"
- ]
- },
- "codeintel_scan_files_in_project": true,
- "codeintel_selected_catalogs":
- [
- "PyWin32",
- "jQuery",
- "Rails"
- ],
- "codeintel_snippets": true,
- "codeintel_syntax_map":
- {
- "Python Django": "Python"
- },
- "sublime_auto_complete": true,
- "syntax": "Packages/JavaScript/JavaScript.tmLanguage",
- "translate_tabs_to_spaces": false
- },
- "translation.x": 0.0,
- "translation.y": 900.0,
- "zoom_level": 1.0
- },
- "type": "text"
- }
]
}
],
diff --git a/examples/js.php b/examples/js.php
index dfab7fa2..9b85d154 100644
--- a/examples/js.php
+++ b/examples/js.php
@@ -92,6 +92,9 @@
+
+
+
diff --git a/examples/sound1.php b/examples/sound1.php
new file mode 100644
index 00000000..794a9d5d
--- /dev/null
+++ b/examples/sound1.php
@@ -0,0 +1,56 @@
+
+
+
+ phaser.js - a new beginning
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/core/Game.js b/src/core/Game.js
index 9f8b9fdb..1f08c8e7 100644
--- a/src/core/Game.js
+++ b/src/core/Game.js
@@ -295,7 +295,7 @@ Phaser.Game.prototype = {
this.time = new Phaser.Time(this);
this.tweens = new Phaser.TweenManager(this);
this.input = new Phaser.Input(this);
- // this.sound = new Phaser.SoundManager(this);
+ this.sound = new Phaser.SoundManager(this);
// this.physics = new Phaser.Physics.PhysicsManager(this);
this.plugins = new Phaser.PluginManager(this, this);
this.net = new Phaser.Net(this);
@@ -379,7 +379,7 @@ Phaser.Game.prototype = {
this.input.update();
this.tweens.update();
// this.stage.update();
- // this.sound.update();
+ this.sound.update();
// this.physics.update();
this.world.update();
this.state.update();
diff --git a/src/gameobjects/GameObjectFactory.js b/src/gameobjects/GameObjectFactory.js
index b58b3342..0e8ee585 100644
--- a/src/gameobjects/GameObjectFactory.js
+++ b/src/gameobjects/GameObjectFactory.js
@@ -41,6 +41,16 @@ Phaser.GameObjectFactory.prototype = {
return this.game.tweens.create(obj, localReference);
+ },
+
+ audio: function (key, volume, loop) {
+
+ volume = volume || 1;
+ loop = loop || false;
+
+ return this.game.sound.add(key, volume, loop);
+
}
+
};
\ No newline at end of file
diff --git a/src/sound/Sound.js b/src/sound/Sound.js
new file mode 100644
index 00000000..3d1cf13e
--- /dev/null
+++ b/src/sound/Sound.js
@@ -0,0 +1,542 @@
+Phaser.Sound = function (game, key, volume, loop) {
+
+ volume = volume || 1;
+ loop = loop || false;
+
+ this.game = game;
+ this.key = key;
+ this._volume = volume;
+ this.loop = loop;
+
+ this.usingWebAudio = this.game.sound.usingWebAudio;
+ this.usingAudioTag = this.game.sound.usingAudioTag;
+
+ if (this.usingWebAudio)
+ {
+ this.context = this.game.sound.context;
+ this.masterGainNode = this.game.sound.masterGain;
+
+ if (typeof this.context.createGain === 'undefined')
+ {
+ this.gainNode = this.context.createGainNode();
+ }
+ else
+ {
+ this.gainNode = this.context.createGain();
+ }
+
+ this.gainNode.gain.value = volume * this.game.sound.volume;
+ this.gainNode.connect(this.masterGainNode);
+ }
+ else
+ {
+ if (this.game.cache.getSound(key) && this.game.cache.getSound(key).locked == false)
+ {
+ this._sound = this.game.cache.getSoundData(key);
+ this.totalDuration = this._sound.duration;
+ }
+ else
+ {
+ this.game.cache.onSoundUnlock.add(this.soundHasUnlocked, this);
+ }
+ }
+
+ this.onDecoded = new Phaser.Signal;
+ this.onPlay = new Phaser.Signal;
+ this.onPause = new Phaser.Signal;
+ this.onResume = new Phaser.Signal;
+ this.onLoop = new Phaser.Signal;
+ this.onStop = new Phaser.Signal;
+ this.onMute = new Phaser.Signal;
+ this.onMarkerComplete = new Phaser.Signal;
+
+};
+
+Phaser.Sound.prototype = {
+
+ game: null,
+
+ /**
+ * Reference to AudioContext instance.
+ */
+ context: null,
+
+ /**
+ * Decoded data buffer / Audio tag.
+ */
+ _buffer: null,
+
+ _muted: false,
+
+ key: '',
+ name: '',
+ markers: {},
+
+ usingWebAudio: false,
+ usingAudioTag: false,
+ autoplay: false,
+ totalDuration: 0,
+ startTime: 0,
+ currentTime: 0,
+ duration: 0,
+ stopTime: 0,
+ paused: false,
+ loop: false,
+ isPlaying: false,
+ currentMarker: '',
+ pendingPlayback: false,
+ override: false,
+
+ onDecoded: null,
+ onPlay: null,
+ onPause: null,
+ onResume: null,
+ onLoop: null,
+ onStop: null,
+ onMute: null,
+ onMarkerComplete: null,
+
+ soundHasUnlocked: function (key) {
+
+ if (key == this.key)
+ {
+ this._sound = this.game.cache.getSoundData(this.key);
+ this.totalDuration = this._sound.duration;
+ console.log('sound has unlocked', this._sound);
+ }
+
+ },
+
+ addMarker: function (name, start, stop, volume, loop) {
+
+ volume = volume || 1;
+ loop = loop || false;
+
+ this.markers[name] = {
+ name: name,
+ start: start,
+ stop: stop,
+ volume: volume,
+ duration: stop - start,
+ loop: loop
+ };
+
+ },
+
+ removeMarker: function (name) {
+
+ delete this.markers[name];
+
+ },
+
+ update: function () {
+
+ if (this.pendingPlayback && this.game.cache.isSoundReady(this.key))
+ {
+ this.pendingPlayback = false;
+ this.play(this._tempMarker, this._tempPosition, this._tempVolume, this._tempLoop);
+ }
+
+ if (this.isPlaying)
+ {
+ this.currentTime = this.game.time.now - this.startTime;
+
+ if (this.currentTime >= this.duration)
+ {
+ //console.log(this.currentMarker, 'has hit duration');
+ if (this.usingWebAudio)
+ {
+ if (this.loop)
+ {
+ //console.log('loop1');
+ // won't work with markers, needs to reset the position
+ this.onLoop.dispatch(this);
+
+ if (this.currentMarker == '')
+ {
+ //console.log('loop2');
+ this.currentTime = 0;
+ this.startTime = this.game.time.now;
+ }
+ else
+ {
+ //console.log('loop3');
+ this.play(this.currentMarker, 0, this.volume, true, true);
+ }
+ }
+ else
+ {
+ //console.log('stopping, no loop for marker');
+ this.stop();
+ }
+ }
+ else
+ {
+ if (this.loop)
+ {
+ this.onLoop.dispatch(this);
+ this.play(this.currentMarker, 0, this.volume, true, true);
+ }
+ else
+ {
+ this.stop();
+ }
+ }
+ }
+ }
+ },
+
+ /**
+ * Play this sound, or a marked section of it.
+ * @param marker {string} Assets key of the sound you want to play.
+ * @param [volume] {number} volume of the sound you want to play.
+ * @param [loop] {bool} loop when it finished playing? (Default to false)
+ * @return {Sound} The playing sound object.
+ */
+ play: function (marker, position, volume, loop, forceRestart) {
+
+ marker = marker || '';
+ position = position || 0;
+ volume = volume || 1;
+ loop = loop || false;
+ forceRestart = forceRestart || false;
+
+ console.log('play', marker, 'current is', this.currentMarker);
+
+ if (this.isPlaying == true && forceRestart == false && this.override == false)
+ {
+ // Use Restart instead
+ return;
+ }
+
+ if (this.isPlaying && this.override)
+ {
+ //console.log('asked to play', marker, 'but already playing', this.currentMarker);
+
+ if (this.usingWebAudio)
+ {
+ if (typeof this._sound.stop === 'undefined')
+ {
+ this._sound.noteOff(0);
+ }
+ else
+ {
+ this._sound.stop(0);
+ }
+ }
+ else if (this.usingAudioTag)
+ {
+ this._sound.pause();
+ this._sound.currentTime = 0;
+ }
+ }
+
+ this.currentMarker = marker;
+
+ if (marker !== '' && this.markers[marker])
+ {
+ this.position = this.markers[marker].start;
+ this.volume = this.markers[marker].volume;
+ this.loop = this.markers[marker].loop;
+ this.duration = this.markers[marker].duration * 1000;
+
+ //console.log('marker info loaded', this.loop, this.duration);
+ this._tempMarker = marker;
+ this._tempPosition = this.position;
+ this._tempVolume = this.volume;
+ this._tempLoop = this.loop;
+ }
+ else
+ {
+ this.position = position;
+ this.volume = volume;
+ this.loop = loop;
+ this.duration = 0;
+
+ this._tempMarker = marker;
+ this._tempPosition = position;
+ this._tempVolume = volume;
+ this._tempLoop = loop;
+ }
+
+ if (this.usingWebAudio)
+ {
+ // Does the sound need decoding?
+ if (this.game.cache.isSoundDecoded(this.key))
+ {
+ // Do we need to do this every time we play? How about just if the buffer is empty?
+ if (this._buffer == null)
+ {
+ this._buffer = this.game.cache.getSoundData(this.key);
+ }
+
+ this._sound = this.context.createBufferSource();
+ this._sound.buffer = this._buffer;
+ this._sound.connect(this.gainNode);
+ this.totalDuration = this._sound.buffer.duration;
+
+ if (this.duration == 0)
+ {
+ this.duration = this.totalDuration * 1000;
+ }
+
+ if (this.loop && marker == '')
+ {
+ this._sound.loop = true;
+ }
+
+ // Useful to cache this somewhere perhaps?
+ if (typeof this._sound.start === 'undefined')
+ {
+ this._sound.noteGrainOn(0, this.position, this.duration / 1000);
+ //this._sound.noteOn(0); // the zero is vitally important, crashes iOS6 without it
+ }
+ else
+ {
+ this._sound.start(0, this.position, this.duration / 1000);
+ }
+
+ this.isPlaying = true;
+ this.startTime = this.game.time.now;
+ this.currentTime = 0;
+ this.stopTime = this.startTime + this.duration;
+ this.onPlay.dispatch(this);
+
+ //console.log('playing, start', this.startTime, 'stop');
+ }
+ else
+ {
+ this.pendingPlayback = true;
+
+ if (this.game.cache.getSound(this.key) && this.game.cache.getSound(this.key).isDecoding == false)
+ {
+ this.game.sound.decode(this.key, this);
+ }
+ }
+ }
+ else
+ {
+ //console.log('Sound play Audio');
+ if (this.game.cache.getSound(this.key) && this.game.cache.getSound(this.key).locked)
+ {
+ //console.log('tried playing locked sound, pending set, reload started');
+ this.game.cache.reloadSound(this.key);
+ this.pendingPlayback = true;
+ }
+ else
+ {
+ //console.log('sound not locked, state?', this._sound.readyState);
+ if (this._sound && this._sound.readyState == 4)
+ {
+ if (this.duration == 0)
+ {
+ this.duration = this.totalDuration * 1000;
+ }
+
+ //console.log('playing', this._sound);
+ this._sound.currentTime = this.position;
+ this._sound.muted = this._muted;
+
+ if (this._muted)
+ {
+ this._sound.volume = 0;
+ }
+ else
+ {
+ this._sound.volume = this._volume;
+ }
+
+ this._sound.play();
+ this.isPlaying = true;
+ this.startTime = this.game.time.now;
+ this.currentTime = 0;
+ this.stopTime = this.startTime + this.duration;
+ this.onPlay.dispatch(this);
+ }
+ else
+ {
+ this.pendingPlayback = true;
+ }
+ }
+ }
+ },
+
+ restart: function (marker, position, volume, loop) {
+
+ marker = marker || '';
+ position = position || 0;
+ volume = volume || 1;
+ loop = loop || false;
+
+ this.play(marker, position, volume, loop, true);
+
+ },
+
+ pause: function () {
+
+ if (this.isPlaying && this._sound)
+ {
+ this.stop();
+ this.isPlaying = false;
+ this.paused = true;
+ this.onPause.dispatch(this);
+ }
+
+ },
+
+ resume: function () {
+
+ if (this.paused && this._sound)
+ {
+ if (this.usingWebAudio)
+ {
+ if (typeof this._sound.start === 'undefined')
+ {
+ this._sound.noteGrainOn(0, this.position, this.duration);
+ //this._sound.noteOn(0); // the zero is vitally important, crashes iOS6 without it
+ }
+ else
+ {
+ this._sound.start(0, this.position, this.duration);
+ }
+ }
+ else
+ {
+ this._sound.play();
+ }
+
+ this.isPlaying = true;
+ this.paused = false;
+ this.onResume.dispatch(this);
+ }
+
+ },
+
+ /**
+ * Stop playing this sound.
+ */
+ stop: function () {
+
+ if (this.isPlaying && this._sound)
+ {
+ if (this.usingWebAudio)
+ {
+ if (typeof this._sound.stop === 'undefined')
+ {
+ this._sound.noteOff(0);
+ }
+ else
+ {
+ this._sound.stop(0);
+ }
+ }
+ else if(this.usingAudioTag)
+ {
+ this._sound.pause();
+ this._sound.currentTime = 0;
+ }
+ }
+
+ this.isPlaying = false;
+ var prevMarker = this.currentMarker;
+
+ this.currentMarker = '';
+ this.onStop.dispatch(this, prevMarker);
+
+ }
+
+};
+
+Object.defineProperty(Phaser.Sound.prototype, "isDecoding", {
+
+ get: function () {
+ return this.game.cache.getSound(this.key).isDecoding;
+ },
+
+ enumerable: true,
+ configurable: true
+});
+
+Object.defineProperty(Phaser.Sound.prototype, "isDecoded", {
+
+ get: function () {
+ return this.game.cache.isSoundDecoded(this.key);
+ },
+
+ enumerable: true,
+ configurable: true
+});
+
+Object.defineProperty(Phaser.Sound.prototype, "mute", {
+
+ /**
+ * Mute sounds.
+ */
+ get: function () {
+ return this._muted;
+ },
+
+ set: function (value) {
+
+ value = value || null;
+
+ if (value)
+ {
+ this._muted = true;
+
+ if (this.usingWebAudio)
+ {
+ this._muteVolume = this.gainNode.gain.value;
+ this.gainNode.gain.value = 0;
+ }
+ else if (this.usingAudioTag && this._sound)
+ {
+ this._muteVolume = this._sound.volume;
+ this._sound.volume = 0;
+ }
+ }
+ else
+ {
+ this._muted = false;
+
+ if (this.usingWebAudio)
+ {
+ this.gainNode.gain.value = this._muteVolume;
+ }
+ else if (this.usingAudioTag && this._sound)
+ {
+ this._sound.volume = this._muteVolume;
+ }
+ }
+
+ this.onMute.dispatch(this);
+
+ },
+
+ enumerable: true,
+ configurable: true
+});
+
+Object.defineProperty(Phaser.Sound.prototype, "volume", {
+
+ get: function () {
+ return this._volume;
+ },
+
+ set: function (value) {
+
+ this._volume = value;
+
+ if (this.usingWebAudio)
+ {
+ this.gainNode.gain.value = value;
+ }
+ else if(this.usingAudioTag && this._sound)
+ {
+ this._sound.volume = value;
+ }
+ },
+
+ enumerable: true,
+ configurable: true
+});
diff --git a/src/sound/SoundManager.js b/src/sound/SoundManager.js
new file mode 100644
index 00000000..ed21d3b3
--- /dev/null
+++ b/src/sound/SoundManager.js
@@ -0,0 +1,351 @@
+/**
+* Phaser - SoundManager
+*
+*/
+Phaser.SoundManager = function (game) {
+
+ this.game = game;
+
+ this.onSoundDecode = new Phaser.Signal;
+
+ if (this.game.device.iOS && this.game.device.webAudio == false)
+ {
+ this.channels = 1;
+ }
+
+ if (game.device.iOS || (window['PhaserGlobal'] && window['PhaserGlobal'].fakeiOSTouchLock))
+ {
+ this.game.input.touch.callbackContext = this;
+ this.game.input.touch.touchStartCallback = this.unlock;
+ this.game.input.mouse.callbackContext = this;
+ this.game.input.mouse.mouseDownCallback = this.unlock;
+ this.touchLocked = true;
+ }
+ else
+ {
+ // What about iOS5?
+ this.touchLocked = false;
+ }
+
+ if (window['PhaserGlobal'])
+ {
+ // Check to see if all audio playback is disabled (i.e. handled by a 3rd party class)
+ if (window['PhaserGlobal'].disableAudio == true)
+ {
+ this.usingWebAudio = false;
+ this.noAudio = true;
+ return;
+ }
+
+ // Check if the Web Audio API is disabled (for testing Audio Tag playback during development)
+ if (window['PhaserGlobal'].disableWebAudio == true)
+ {
+ this.usingWebAudio = false;
+ this.usingAudioTag = true;
+ this.noAudio = false;
+ return;
+ }
+ }
+
+ if (!!window['AudioContext'])
+ {
+ this.context = new window['AudioContext']();
+ }
+ else if(!!window['webkitAudioContext'])
+ {
+ this.context = new window['webkitAudioContext']();
+ }
+ else if(!!window['Audio'])
+ {
+ this.usingWebAudio = false;
+ this.usingAudioTag = true;
+ }
+ else
+ {
+ this.usingWebAudio = false;
+ this.noAudio = true;
+ }
+
+ if (this.context !== null)
+ {
+ if (typeof this.context.createGain === 'undefined')
+ {
+ this.masterGain = this.context.createGainNode();
+ }
+ else
+ {
+ this.masterGain = this.context.createGain();
+ }
+
+ this.masterGain.gain.value = 1;
+ this.masterGain.connect(this.context.destination);
+ }
+
+};
+
+Phaser.SoundManager.prototype = {
+
+ game: null,
+
+ _muted: false,
+ _unlockSource: null,
+ _volume: 1,
+ _muted: false,
+ _sounds: [],
+
+ context: null,
+ usingWebAudio: true,
+ usingAudioTag: false,
+ noAudio: false,
+
+ touchLocked: false,
+ onSoundDecode: null,
+
+ channels: 32,
+
+ unlock: function () {
+
+ if (this.touchLocked == false)
+ {
+ return;
+ }
+
+ console.log('SoundManager touch unlocked');
+
+ if (this.game.device.webAudio && (window['PhaserGlobal'] && window['PhaserGlobal'].disableWebAudio == false))
+ {
+ // Create empty buffer and play it
+ var buffer = this.context.createBuffer(1, 1, 22050);
+ this._unlockSource = this.context.createBufferSource();
+ this._unlockSource.buffer = buffer;
+ this._unlockSource.connect(this.context.destination);
+ this._unlockSource.noteOn(0);
+ }
+ else
+ {
+ // Create an Audio tag?
+ this.touchLocked = false;
+ this._unlockSource = null;
+ this.game.input.touch.callbackContext = null;
+ this.game.input.touch.touchStartCallback = null;
+ this.game.input.mouse.callbackContext = null;
+ this.game.input.mouse.mouseDownCallback = null;
+ }
+
+ },
+
+ stopAll: function () {
+
+ for (var i = 0; i < this._sounds.length; i++)
+ {
+ if (this._sounds[i])
+ {
+ this._sounds[i].stop();
+ }
+ }
+
+ },
+
+ pauseAll: function () {
+
+ for (var i = 0; i < this._sounds.length; i++)
+ {
+ if (this._sounds[i])
+ {
+ this._sounds[i].pause();
+ }
+ }
+
+ },
+
+ resumeAll: function () {
+
+ for (var i = 0; i < this._sounds.length; i++)
+ {
+ if (this._sounds[i])
+ {
+ this._sounds[i].resume();
+ }
+ }
+
+ },
+
+ /**
+ * Decode a sound with its assets key.
+ * @param key {string} Assets key of the sound to be decoded.
+ * @param [sound] {Sound} its bufer will be set to decoded data.
+ */
+ decode: function (key, sound) {
+
+ sound = sound || null;
+
+ var soundData = this.game.cache.getSoundData(key);
+
+ if (soundData)
+ {
+ if (this.game.cache.isSoundDecoded(key) === false)
+ {
+ this.game.cache.updateSound(key, 'isDecoding', true);
+
+ var that = this;
+
+ this.context.decodeAudioData(soundData, function (buffer) {
+ that.game.cache.decodedSound(key, buffer);
+ if (sound)
+ {
+ that.onSoundDecode.dispatch(sound);
+ }
+ });
+ }
+ }
+
+ },
+
+ update: function () {
+
+ if (this.touchLocked)
+ {
+ if (this.game.device.webAudio && this._unlockSource !== null)
+ {
+ if ((this._unlockSource.playbackState === this._unlockSource.PLAYING_STATE || this._unlockSource.playbackState === this._unlockSource.FINISHED_STATE))
+ {
+ this.touchLocked = false;
+ this._unlockSource = null;
+ this.game.input.touch.callbackContext = null;
+ this.game.input.touch.touchStartCallback = null;
+ }
+ }
+ }
+
+ for (var i = 0; i < this._sounds.length; i++)
+ {
+ this._sounds[i].update();
+ }
+
+ },
+
+ add: function (key, volume, loop) {
+
+ volume = volume || 1;
+ loop = loop || false;
+
+ var sound = new Phaser.Sound(this.game, key, volume, loop);
+
+ this._sounds.push(sound);
+
+ return sound;
+
+ }
+
+};
+
+Object.defineProperty(Phaser.SoundManager.prototype, "mute", {
+
+ /**
+ * A global audio mute toggle.
+ */
+ get: function () {
+
+ return this._muted;
+
+ },
+
+ set: function (value) {
+
+ value = value || null;
+
+ if (value)
+ {
+ if (this._muted)
+ {
+ return;
+ }
+
+ this._muted = true;
+
+ if (this.usingWebAudio)
+ {
+ this._muteVolume = this.masterGain.gain.value;
+ this.masterGain.gain.value = 0;
+ }
+
+ // Loop through sounds
+ for (var i = 0; i < this._sounds.length; i++)
+ {
+ if (this._sounds[i].usingAudioTag)
+ {
+ this._sounds[i].mute = true;
+ }
+ }
+ }
+ else
+ {
+ if (this._muted == false)
+ {
+ return;
+ }
+
+ this._muted = false;
+
+ if (this.usingWebAudio)
+ {
+ this.masterGain.gain.value = this._muteVolume;
+ }
+
+ // Loop through sounds
+ for (var i = 0; i < this._sounds.length; i++)
+ {
+ if (this._sounds[i].usingAudioTag)
+ {
+ this._sounds[i].mute = false;
+ }
+ }
+ }
+ },
+
+ enumerable: true,
+ configurable: true
+});
+
+Object.defineProperty(Phaser.SoundManager.prototype, "volume", {
+
+ get: function () {
+
+ if (this.usingWebAudio)
+ {
+ return this.masterGain.gain.value;
+ }
+ else
+ {
+ return this._volume;
+ }
+
+ },
+
+ /**
+ * The global audio volume. A value between 0 (silence) and 1 (full volume)
+ */
+ set: function (value) {
+
+ value = this.game.math.clamp(value, 1, 0);
+
+ this._volume = value;
+
+ if (this.usingWebAudio)
+ {
+ this.masterGain.gain.value = value;
+ }
+
+ // Loop through the sound cache and change the volume of all html audio tags
+ for (var i = 0; i < this._sounds.length; i++)
+ {
+ if (this._sounds[i].usingAudioTag)
+ {
+ this._sounds[i].volume = this._sounds[i].volume * value;
+ }
+ }
+
+ },
+ enumerable: true,
+ configurable: true
+});
diff --git a/src/utils/Debug.js b/src/utils/Debug.js
index db3b67f7..9dc49737 100644
--- a/src/utils/Debug.js
+++ b/src/utils/Debug.js
@@ -186,6 +186,8 @@ Phaser.Utils.Debug.prototype = {
this.line('Position: ' + sound.position);
}
+ this.stop();
+
},
/**