diff --git a/Phaser/Game.ts b/Phaser/Game.ts index c2e373ac..e53a1409 100644 --- a/Phaser/Game.ts +++ b/Phaser/Game.ts @@ -8,6 +8,7 @@ /// /// /// +/// /// /// /// @@ -208,6 +209,12 @@ module Phaser { */ public motion: Motion; + /** + * Reference to the network class. + * @type {Net} + */ + public net: Net; + /** * Reference to the sound manager. * @type {SoundManager} @@ -294,6 +301,7 @@ module Phaser { else { this.device = new Device(); + this.net = new Net(this); this.motion = new Motion(this); this.math = new GameMath(this); this.stage = new Stage(this, parent, width, height); diff --git a/Phaser/Phaser.csproj b/Phaser/Phaser.csproj index 9c479ee7..d3187e44 100644 --- a/Phaser/Phaser.csproj +++ b/Phaser/Phaser.csproj @@ -64,6 +64,10 @@ + + + CSS3Filters.ts + Debug.ts @@ -178,6 +182,10 @@ Motion.ts + + + Net.ts + Body.ts diff --git a/Phaser/Stage.ts b/Phaser/Stage.ts index 7b61d44c..1d925d4f 100644 --- a/Phaser/Stage.ts +++ b/Phaser/Stage.ts @@ -1,5 +1,6 @@ /// /// +/// /// /// /// @@ -52,6 +53,8 @@ module Phaser { this.context = this.canvas.getContext('2d'); + this.css3 = new Phaser.Components.CSS3Filters(this.canvas); + this.scaleMode = StageScaleMode.NO_SCALE; this.scale = new StageScaleMode(this._game, width, height); @@ -97,6 +100,12 @@ module Phaser { */ public orientationScreen; + /** + * Controls the CSS3 Filters applied to the Stages canvas object. + * @type {Phaser.Components.CSS3Filters} + */ + public css3: Phaser.Components.CSS3Filters; + /** * Bound of this stage. * @type {Rectangle} diff --git a/Phaser/components/CSS3Filters.ts b/Phaser/components/CSS3Filters.ts new file mode 100644 index 00000000..235d2ad7 --- /dev/null +++ b/Phaser/components/CSS3Filters.ts @@ -0,0 +1,170 @@ +/// + +/** +* Phaser - Components - CSS3Filters +* +* Allows for easy addition and modification of CSS3 Filters on DOM objects (typically the Game.Stage.canvas). +*/ + +module Phaser.Components { + + export class CSS3Filters { + + /** + * Creates a new CSS3 Filter component + * @param parent The DOM object to apply the filters to. + */ + constructor(parent) { + this.parent = parent; + } + + /** + * Reference to the parent DOM object (stage.canvas for example) + */ + public parent; + + private _blur: number = 0; + private _grayscale: number = 0; + private _sepia: number = 0; + private _brightness: number = 0; + private _contrast: number = 0; + private _hueRotate: number = 0; + private _invert: number = 0; + private _opacity: number = 0; + private _saturate: number = 0; + + private setFilter(local: string, prefix: string, value: number, unit: string) { + + this[local] = value; + + if (this.parent) + { + this.parent.style['-webkit-filter'] = prefix + '(' + value + unit + ')'; + } + + } + + /** + * Applies a Gaussian blur to the DOM element. The value of ‘radius’ defines the value of the standard deviation to the Gaussian function, + * or how many pixels on the screen blend into each other, so a larger value will create more blur. + * If no parameter is provided, then a value 0 is used. The parameter is specified as a CSS length, but does not accept percentage values. + */ + public set blur(radius?: number = 0) { + this.setFilter('_blur', 'blur', radius, 'px'); + } + + public get blur(): number { + return this._blur; + } + + /** + * Converts the input image to grayscale. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely grayscale. A value of 0% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public set grayscale(amount?: number = 100) { + this.setFilter('_grayscale', 'grayscale', amount, '%'); + } + + public get grayscale(): number { + return this._grayscale; + } + + /** + * Converts the input image to sepia. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely sepia. A value of 0 leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public set sepia(amount?: number = 100) { + this.setFilter('_sepia', 'sepia', amount, '%'); + } + + public get sepia(): number { + return this._sepia; + } + + /** + * Applies a linear multiplier to input image, making it appear more or less bright. + * A value of 0% will create an image that is completely black. A value of 100% leaves the input unchanged. + * Other values are linear multipliers on the effect. Values of an amount over 100% are allowed, providing brighter results. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public set brightness(amount?: number = 100) { + this.setFilter('_brightness', 'brightness', amount, '%'); + } + + public get brightness(): number { + return this._brightness; + } + + /** + * Adjusts the contrast of the input. A value of 0% will create an image that is completely black. + * A value of 100% leaves the input unchanged. Values of amount over 100% are allowed, providing results with less contrast. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public set contrast(amount?: number = 100) { + this.setFilter('_contrast', 'contrast', amount, '%'); + } + + public get contrast(): number { + return this._contrast; + } + + /** + * Applies a hue rotation on the input image. The value of ‘angle’ defines the number of degrees around the color circle + * the input samples will be adjusted. A value of 0deg leaves the input unchanged. If the ‘angle’ parameter is missing, + * a value of 0deg is used. Maximum value is 360deg. + */ + public set hueRotate(angle?: number = 0) { + this.setFilter('_hueRotate', 'hue-rotate', angle, 'deg'); + } + + public get hueRotate(): number { + return this._hueRotate; + } + + /** + * Inverts the samples in the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely inverted. A value of 0% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public set invert(value?: number = 100) { + this.setFilter('_invert', 'invert', value, '%'); + } + + public get invert(): number { + return this._invert; + } + + /** + * Applies transparency to the samples in the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 0% is completely transparent. A value of 100% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. This is equivalent to multiplying the input image samples by amount. + * If the ‘amount’ parameter is missing, a value of 100% is used. + * This function is similar to the more established opacity property; the difference is that with filters, some browsers provide hardware acceleration for better performance. + */ + public set opacity(value?: number = 100) { + this.setFilter('_opacity', 'opacity', value, '%'); + } + + public get opacity(): number { + return this._opacity; + } + + /** + * Saturates the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 0% is completely un-saturated. A value of 100% leaves the input unchanged. + * Other values are linear multipliers on the effect. Values of amount over 100% are allowed, providing super-saturated results. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public set saturate(value?: number = 100) { + this.setFilter('_saturate', 'saturate', value, '%'); + } + + public get saturate(): number { + return this._saturate; + } + + } + +} \ No newline at end of file diff --git a/Phaser/components/sprite/Input.ts b/Phaser/components/sprite/Input.ts index 94bbd9ca..0816a341 100644 --- a/Phaser/components/sprite/Input.ts +++ b/Phaser/components/sprite/Input.ts @@ -311,6 +311,7 @@ module Phaser.Components.Sprite { if (this.enabled == false || this._parent.visible == false) { + this._pointerOutHandler(pointer); return false; } diff --git a/Phaser/gameobjects/DynamicTexture.ts b/Phaser/gameobjects/DynamicTexture.ts index 579eadcd..2f325e71 100644 --- a/Phaser/gameobjects/DynamicTexture.ts +++ b/Phaser/gameobjects/DynamicTexture.ts @@ -34,6 +34,8 @@ module Phaser { this.canvas.height = height; this.context = this.canvas.getContext('2d'); + this.css3 = new Phaser.Components.CSS3Filters(this.canvas); + this.bounds = new Rectangle(0, 0, width, height); } @@ -59,6 +61,13 @@ module Phaser { // Input / Output nodes? + /** + * Controls the CSS3 Filters applied to the textures canvas object. + * Only really useful if you attach this canvas to the DOM. + * @type {Phaser.Components.CSS3Filters} + */ + public css3: Phaser.Components.CSS3Filters; + /** * Bound of this texture with width and height info. * @type {Rectangle} diff --git a/Phaser/net/Net.ts b/Phaser/net/Net.ts new file mode 100644 index 00000000..e100a5d9 --- /dev/null +++ b/Phaser/net/Net.ts @@ -0,0 +1,135 @@ +/// + +/** +* Phaser - Net +* +* +*/ + +module Phaser { + + export class Net { + + /** + * Net constructor + */ + constructor(game: Game) { + + this.game = game; + + } + + /** + * Local reference to the current Phaser.Game. + */ + public game: Game; + + /** + * Compares the given domain name against the hostname of the browser containing the game. + * If the domain name is found it returns true. + * You can specify a part of a domain, for example 'google' would match 'google.com', 'google.co.uk', etc. + * Do not include 'http://' at the start. + */ + public checkDomainName(domain: string): bool { + return window.location.hostname.indexOf(domain) !== -1; + } + + /** + * Updates a value on the Query String and returns it in full. + * If the value doesn't already exist it is set. + * If the value exists it is replaced with the new value given. If you don't provide a new value it is removed from the query string. + * Optionally you can redirect to the new url, or just return it as a string. + */ + public updateQueryString(key: string, value: string, redirect?:bool = false, url?: string = ''):string { + + if (url == '') + { + url = window.location.href; + } + + var output: string = ''; + + var re:RegExp = new RegExp("([?|&])" + key + "=.*?(&|#|$)(.*)", "gi"); + + if (re.test(url)) + { + if (typeof value !== 'undefined' && value !== null) + { + output = url.replace(re, '$1' + key + "=" + value + '$2$3'); + } + else + { + output = url.replace(re, '$1$3').replace(/(&|\?)$/, ''); + } + } + else + { + if (typeof value !== 'undefined' && value !== null) + { + var separator = url.indexOf('?') !== -1 ? '&' : '?'; + var hash = url.split('#'); + + url = hash[0] + separator + key + '=' + value; + + if (hash[1]) + { + url += '#' + hash[1]; + } + + output = url; + } + else + { + output = url; + } + } + + if (redirect) + { + window.location.href = output; + } + else + { + return output; + } + + } + + /** + * Returns the Query String as an object. + * If you specify a parameter it will return just the value of that parameter, should it exist. + */ + public getQueryString(parameter?: string = '') { + + var output = {}; + var keyValues = location.search.substring(1).split('&'); + + for (var i in keyValues) + { + var key = keyValues[i].split('='); + + if (key.length > 1) + { + if (parameter && parameter == this.decodeURI(key[0])) + { + return this.decodeURI(key[1]); + } + else + { + output[this.decodeURI(key[0])] = this.decodeURI(key[1]); + } + } + } + + return output; + + } + + private decodeURI(value: string): string { + return decodeURIComponent(value.replace(/\+/g, " ")); + } + + + } + +} diff --git a/Phaser/sound/SoundManager.ts b/Phaser/sound/SoundManager.ts index 835f5282..2e036234 100644 --- a/Phaser/sound/SoundManager.ts +++ b/Phaser/sound/SoundManager.ts @@ -4,7 +4,6 @@ /** * Phaser - SoundManager * -* This is an embroyonic web audio sound management class. There is a lot of work still to do here. */ module Phaser { diff --git a/README.md b/README.md index 7cba62fe..cb82869d 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,6 @@ TODO: * Investigate bug re: tilemap collision and animation frames * Update tests that use arrow keys and include touch/mouse support (FlxControlHandler style) * Texture Repeat doesn't scroll, because it's part of the camera not the world, need to think about this more -* Stage CSS3 transforms!!! Color tints, sepia, greyscale, all of those cool things :) * Add JSON Texture Atlas object support. * Pointer.getWorldX(camera) needs to take camera scale into consideration * If stage.clear set to false and game pauses, when it unpauses you still see the pause arrow - resolve this @@ -56,11 +55,10 @@ TODO: * Tilemap.render - move layers length to var * Camera control method (touch/keyboard) * Tilemap.destroy needs doing -* Look at the input targetObject - it doesn't seem to get cleared down all the time, maybe just a priority/alpha issue (check vis/alpha?) * Sprite.transform.bottomRight/Left doesn't seem to take origin into account -* When you toggle visible of a button that is over, it doesn't disable that 'over' state (should it? probably yes) * Stage.opaqueBackground = 'rgb()' or null, alpha, blendMode, filters, mask, rotation+XYZ,scaleXYZ,visible - +* Stage CSS3 Transforms? +* Ability to layer another DOM object and have it controlled by the game somehow. Can then do stacked canvas effects. * Stage lost to mute @@ -157,6 +155,8 @@ V1.0.0 * SoundManager will now automatically handle iOS touch unlocking. * Added TilemapLayer.putTileWorldXY to place a tile based on pixel values, and putTile based on tile map coordinates. * Dropped the StageScaleMode.setScreenSize iterations count from 40 down to 10 and document min body height to 2000px. +* Added Phaser.Net for browser and network specific functions, currently includes query string parsing and updating methods. +* Added a new CSS3 Filters component. Apply blur, grayscale, sepia, brightness, contrast, hue rotation, invert, opacity and saturate filters to the games stage. diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index bd659391..e35c5c8c 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -242,6 +242,34 @@ origin 5.ts + + + blur filter.ts + + + + + brightness filter.ts + + + + contrast filter.ts + + + + grayscale filter.ts + + + + hue rotate filter.ts + + + sepia filter.ts + + + + filter test.ts + csv tilemap.ts diff --git a/Tests/phaser.js b/Tests/phaser.js index 163996cf..ff65ffdd 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -1,4 +1,4 @@ -/// +/// /** * Phaser - Point * @@ -2004,6 +2004,7 @@ var Phaser; this.canvas.width = width; this.canvas.height = height; this.context = this.canvas.getContext('2d'); + this.css3 = new Phaser.Components.CSS3Filters(this.canvas); this.bounds = new Phaser.Rectangle(0, 0, width, height); } DynamicTexture.prototype.getPixel = /** @@ -3607,6 +3608,7 @@ var Phaser; */ function (pointer) { if(this.enabled == false || this._parent.visible == false) { + this._pointerOutHandler(pointer); return false; } if(this.draggable && this._draggedPointerID == pointer.id) { @@ -9461,6 +9463,97 @@ var Phaser; })(Phaser || (Phaser = {})); /// /** +* Phaser - Net +* +* +*/ +var Phaser; +(function (Phaser) { + var Net = (function () { + /** + * Net constructor + */ + function Net(game) { + this.game = game; + } + Net.prototype.checkDomainName = /** + * Compares the given domain name against the hostname of the browser containing the game. + * If the domain name is found it returns true. + * You can specify a part of a domain, for example 'google' would match 'google.com', 'google.co.uk', etc. + * Do not include 'http://' at the start. + */ + function (domain) { + return window.location.hostname.indexOf(domain) !== -1; + }; + Net.prototype.updateQueryString = /** + * Updates a value on the Query String and returns it in full. + * If the value doesn't already exist it is set. + * If the value exists it is replaced with the new value given. If you don't provide a new value it is removed from the query string. + * Optionally you can redirect to the new url, or just return it as a string. + */ + function (key, value, redirect, url) { + if (typeof redirect === "undefined") { redirect = false; } + if (typeof url === "undefined") { url = ''; } + if(url == '') { + url = window.location.href; + } + var output = ''; + var re = new RegExp("([?|&])" + key + "=.*?(&|#|$)(.*)", "gi"); + if(re.test(url)) { + if(typeof value !== 'undefined' && value !== null) { + output = url.replace(re, '$1' + key + "=" + value + '$2$3'); + } else { + output = url.replace(re, '$1$3').replace(/(&|\?)$/, ''); + } + } else { + if(typeof value !== 'undefined' && value !== null) { + var separator = url.indexOf('?') !== -1 ? '&' : '?'; + var hash = url.split('#'); + url = hash[0] + separator + key + '=' + value; + if(hash[1]) { + url += '#' + hash[1]; + } + output = url; + } else { + output = url; + } + } + if(redirect) { + window.location.href = output; + } else { + return output; + } + }; + Net.prototype.getQueryString = /** + * Returns the Query String as an object. + * If you specify a parameter it will return just the value of that parameter, should it exist. + */ + function (parameter) { + if (typeof parameter === "undefined") { parameter = ''; } + var output = { + }; + var keyValues = location.search.substring(1).split('&'); + for(var i in keyValues) { + var key = keyValues[i].split('='); + if(key.length > 1) { + if(parameter && parameter == this.decodeURI(key[0])) { + return this.decodeURI(key[1]); + } else { + output[this.decodeURI(key[0])] = this.decodeURI(key[1]); + } + } + } + return output; + }; + Net.prototype.decodeURI = function (value) { + return decodeURIComponent(value.replace(/\+/g, " ")); + }; + return Net; + })(); + Phaser.Net = Net; +})(Phaser || (Phaser = {})); +/// +/** * Phaser - Cache * * A game only has one instance of a Cache and it is used to store all externally loaded assets such @@ -14349,7 +14442,7 @@ var Phaser; } } else { //console.log('Sound play Audio'); - if(this.game.cache.getSound(this.key).locked) { + 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; @@ -14362,7 +14455,11 @@ var Phaser; //console.log('playing', this._sound); this._sound.currentTime = this.position; this._sound.muted = this._muted; - this._sound.volume = this._volume; + 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; @@ -14503,7 +14600,6 @@ var Phaser; /** * Phaser - SoundManager * -* This is an embroyonic web audio sound management class. There is a lot of work still to do here. */ var Phaser; (function (Phaser) { @@ -14612,6 +14708,7 @@ var Phaser; return this._muted; }, set: function (value) { + console.log('SoundManager mute', value); if(value) { if(this._muted) { return; @@ -14623,7 +14720,7 @@ var Phaser; } // Loop through sounds for(var i = 0; i < this._sounds.length; i++) { - if(this._sounds[i]) { + if(this._sounds[i].usingAudioTag) { this._sounds[i].mute = true; } } @@ -14637,7 +14734,7 @@ var Phaser; } // Loop through sounds for(var i = 0; i < this._sounds.length; i++) { - if(this._sounds[i]) { + if(this._sounds[i].usingAudioTag) { this._sounds[i].mute = false; } } @@ -14761,6 +14858,192 @@ var Phaser; (function (Phaser) { Phaser.VERSION = 'Phaser version 1.0.0'; })(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /** + * Phaser - Components - CSS3Filters + * + * Allows for easy addition and modification of CSS3 Filters on DOM objects (typically the Game.Stage.canvas). + */ + (function (Components) { + var CSS3Filters = (function () { + /** + * Creates a new CSS3 Filter component + * @param parent The DOM object to apply the filters to. + */ + function CSS3Filters(parent) { + this._blur = 0; + this._grayscale = 0; + this._sepia = 0; + this._brightness = 0; + this._contrast = 0; + this._hueRotate = 0; + this._invert = 0; + this._opacity = 0; + this._saturate = 0; + this.parent = parent; + } + CSS3Filters.prototype.setFilter = function (local, prefix, value, unit) { + this[local] = value; + if(this.parent) { + this.parent.style['-webkit-filter'] = prefix + '(' + value + unit + ')'; + } + }; + Object.defineProperty(CSS3Filters.prototype, "blur", { + get: function () { + return this._blur; + }, + set: /** + * Applies a Gaussian blur to the DOM element. The value of ‘radius’ defines the value of the standard deviation to the Gaussian function, + * or how many pixels on the screen blend into each other, so a larger value will create more blur. + * If no parameter is provided, then a value 0 is used. The parameter is specified as a CSS length, but does not accept percentage values. + */ + function (radius) { + if (typeof radius === "undefined") { radius = 0; } + this.setFilter('_blur', 'blur', radius, 'px'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "grayscale", { + get: function () { + return this._grayscale; + }, + set: /** + * Converts the input image to grayscale. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely grayscale. A value of 0% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (amount) { + if (typeof amount === "undefined") { amount = 100; } + this.setFilter('_grayscale', 'grayscale', amount, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "sepia", { + get: function () { + return this._sepia; + }, + set: /** + * Converts the input image to sepia. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely sepia. A value of 0 leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (amount) { + if (typeof amount === "undefined") { amount = 100; } + this.setFilter('_sepia', 'sepia', amount, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "brightness", { + get: function () { + return this._brightness; + }, + set: /** + * Applies a linear multiplier to input image, making it appear more or less bright. + * A value of 0% will create an image that is completely black. A value of 100% leaves the input unchanged. + * Other values are linear multipliers on the effect. Values of an amount over 100% are allowed, providing brighter results. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (amount) { + if (typeof amount === "undefined") { amount = 100; } + this.setFilter('_brightness', 'brightness', amount, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "contrast", { + get: function () { + return this._contrast; + }, + set: /** + * Adjusts the contrast of the input. A value of 0% will create an image that is completely black. + * A value of 100% leaves the input unchanged. Values of amount over 100% are allowed, providing results with less contrast. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (amount) { + if (typeof amount === "undefined") { amount = 100; } + this.setFilter('_contrast', 'contrast', amount, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "hueRotate", { + get: function () { + return this._hueRotate; + }, + set: /** + * Applies a hue rotation on the input image. The value of ‘angle’ defines the number of degrees around the color circle + * the input samples will be adjusted. A value of 0deg leaves the input unchanged. If the ‘angle’ parameter is missing, + * a value of 0deg is used. Maximum value is 360deg. + */ + function (angle) { + if (typeof angle === "undefined") { angle = 0; } + this.setFilter('_hueRotate', 'hue-rotate', angle, 'deg'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "invert", { + get: function () { + return this._invert; + }, + set: /** + * Inverts the samples in the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely inverted. A value of 0% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (value) { + if (typeof value === "undefined") { value = 100; } + this.setFilter('_invert', 'invert', value, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "opacity", { + get: function () { + return this._opacity; + }, + set: /** + * Applies transparency to the samples in the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 0% is completely transparent. A value of 100% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. This is equivalent to multiplying the input image samples by amount. + * If the ‘amount’ parameter is missing, a value of 100% is used. + * This function is similar to the more established opacity property; the difference is that with filters, some browsers provide hardware acceleration for better performance. + */ + function (value) { + if (typeof value === "undefined") { value = 100; } + this.setFilter('_opacity', 'opacity', value, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "saturate", { + get: function () { + return this._saturate; + }, + set: /** + * Saturates the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 0% is completely un-saturated. A value of 100% leaves the input unchanged. + * Other values are linear multipliers on the effect. Values of amount over 100% are allowed, providing super-saturated results. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (value) { + if (typeof value === "undefined") { value = 100; } + this.setFilter('_saturate', 'saturate', value, '%'); + }, + enumerable: true, + configurable: true + }); + return CSS3Filters; + })(); + Components.CSS3Filters = CSS3Filters; + })(Phaser.Components || (Phaser.Components = {})); + var Components = Phaser.Components; +})(Phaser || (Phaser = {})); /// /** * Phaser - StageScaleMode @@ -14843,6 +15126,11 @@ var Phaser; * @type {number} */ this.height = 0; + /** + * The maximum number of times it will try to resize the canvas to fill the browser (default is 10) + * @type {number} + */ + this.maxIterations = 10; this._game = game; this.enterLandscape = new Phaser.Signal(); this.enterPortrait = new Phaser.Signal(); @@ -14994,8 +15282,8 @@ var Phaser; window.scrollTo(0, 0); } } - if(this._check == null) { - this._iterations = 10; + if(this._check == null && this.maxIterations > 0) { + this._iterations = this.maxIterations; this._check = window.setInterval(function () { return _this.setScreenSize(); }, 10); @@ -15348,6 +15636,7 @@ var Phaser; })(Phaser || (Phaser = {})); /// /// +/// /// /// /// @@ -15413,6 +15702,7 @@ var Phaser; event.preventDefault(); }; this.context = this.canvas.getContext('2d'); + this.css3 = new Phaser.Components.CSS3Filters(this.canvas); this.scaleMode = Phaser.StageScaleMode.NO_SCALE; this.scale = new Phaser.StageScaleMode(this._game, width, height); this.getOffset(this.canvas); @@ -15453,8 +15743,13 @@ var Phaser; function () { this.scale.update(); if(this.clear) { - // implement dirty rect? could take up more cpu time than it saves. needs benching. - this.context.clearRect(0, 0, this.width, this.height); + // A 'fix' for the horrendous Android stock browser bug: https://code.google.com/p/android/issues/detail?id=39247 + if(this._game.device.android && this._game.device.chrome == false) { + this.context.fillStyle = 'rgb(0,0,0)'; + this.context.fillRect(0, 0, this.width, this.height); + } else { + this.context.clearRect(0, 0, this.width, this.height); + } } if(this._game.paused && this.scale.incorrectOrientation) { this.orientationScreen.update(); @@ -19618,6 +19913,7 @@ var Phaser; /// /// /// +/// /// /// /// @@ -19790,6 +20086,7 @@ var Phaser; }, 13); } else { this.device = new Phaser.Device(); + this.net = new Phaser.Net(this); this.motion = new Phaser.Motion(this); this.math = new Phaser.GameMath(this); this.stage = new Phaser.Stage(this, parent, width, height); diff --git a/Tests/stage/blur filter.js b/Tests/stage/blur filter.js new file mode 100644 index 00000000..0fe9b70d --- /dev/null +++ b/Tests/stage/blur filter.js @@ -0,0 +1,26 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + function init() { + game.load.image('backdrop', 'assets/pics/remember-me.jpg'); + game.load.start(); + } + function create() { + game.world.setSize(1920, 1200); + game.add.sprite(0, 0, 'backdrop'); + // Apply a 4px blur to the entire game (this value can be tweened, modified in-game, etc) + game.stage.css3.blur = 4; + } + function update() { + if(game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + game.camera.x -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + game.camera.x += 4; + } + if(game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + game.camera.y -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + game.camera.y += 4; + } + } +})(); diff --git a/Tests/stage/blur filter.ts b/Tests/stage/blur filter.ts new file mode 100644 index 00000000..6a478d5c --- /dev/null +++ b/Tests/stage/blur filter.ts @@ -0,0 +1,47 @@ +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + + function init() { + + game.load.image('backdrop', 'assets/pics/remember-me.jpg'); + game.load.start(); + + } + + function create() { + + game.world.setSize(1920, 1200); + + game.add.sprite(0, 0, 'backdrop'); + + // Apply a 4px blur to the entire game (this value can be tweened, modified in-game, etc) + game.stage.css3.blur = 4; + + } + + function update() { + + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) + { + game.camera.x -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) + { + game.camera.x += 4; + } + + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) + { + game.camera.y -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) + { + game.camera.y += 4; + } + + } + +})(); diff --git a/Tests/stage/brightness filter.js b/Tests/stage/brightness filter.js new file mode 100644 index 00000000..6ff93d45 --- /dev/null +++ b/Tests/stage/brightness filter.js @@ -0,0 +1,26 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + function init() { + game.load.image('backdrop', 'assets/pics/remember-me.jpg'); + game.load.start(); + } + function create() { + game.world.setSize(1920, 1200); + game.add.sprite(0, 0, 'backdrop'); + // Apply a 150% brightness filter to the entire game (this value can be tweened, modified in-game, etc) + game.stage.css3.brightness = 150; + } + function update() { + if(game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + game.camera.x -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + game.camera.x += 4; + } + if(game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + game.camera.y -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + game.camera.y += 4; + } + } +})(); diff --git a/Tests/stage/brightness filter.ts b/Tests/stage/brightness filter.ts new file mode 100644 index 00000000..7b8f100b --- /dev/null +++ b/Tests/stage/brightness filter.ts @@ -0,0 +1,47 @@ +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + + function init() { + + game.load.image('backdrop', 'assets/pics/remember-me.jpg'); + game.load.start(); + + } + + function create() { + + game.world.setSize(1920, 1200); + + game.add.sprite(0, 0, 'backdrop'); + + // Apply a 150% brightness filter to the entire game (this value can be tweened, modified in-game, etc) + game.stage.css3.brightness = 150; + + } + + function update() { + + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) + { + game.camera.x -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) + { + game.camera.x += 4; + } + + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) + { + game.camera.y -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) + { + game.camera.y += 4; + } + + } + +})(); diff --git a/Tests/stage/contrast filter.js b/Tests/stage/contrast filter.js new file mode 100644 index 00000000..11b2fb22 --- /dev/null +++ b/Tests/stage/contrast filter.js @@ -0,0 +1,26 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + function init() { + game.load.image('backdrop', 'assets/pics/remember-me.jpg'); + game.load.start(); + } + function create() { + game.world.setSize(1920, 1200); + game.add.sprite(0, 0, 'backdrop'); + // Apply a 250% contrast filter to the entire game (this value can be tweened, modified in-game, etc) + game.stage.css3.contrast = 250; + } + function update() { + if(game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + game.camera.x -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + game.camera.x += 4; + } + if(game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + game.camera.y -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + game.camera.y += 4; + } + } +})(); diff --git a/Tests/stage/contrast filter.ts b/Tests/stage/contrast filter.ts new file mode 100644 index 00000000..43e55ec1 --- /dev/null +++ b/Tests/stage/contrast filter.ts @@ -0,0 +1,47 @@ +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + + function init() { + + game.load.image('backdrop', 'assets/pics/remember-me.jpg'); + game.load.start(); + + } + + function create() { + + game.world.setSize(1920, 1200); + + game.add.sprite(0, 0, 'backdrop'); + + // Apply a 250% contrast filter to the entire game (this value can be tweened, modified in-game, etc) + game.stage.css3.contrast = 250; + + } + + function update() { + + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) + { + game.camera.x -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) + { + game.camera.x += 4; + } + + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) + { + game.camera.y -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) + { + game.camera.y += 4; + } + + } + +})(); diff --git a/Tests/stage/grayscale filter.js b/Tests/stage/grayscale filter.js new file mode 100644 index 00000000..0e6ed430 --- /dev/null +++ b/Tests/stage/grayscale filter.js @@ -0,0 +1,26 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + function init() { + game.load.image('backdrop', 'assets/pics/remember-me.jpg'); + game.load.start(); + } + function create() { + game.world.setSize(1920, 1200); + game.add.sprite(0, 0, 'backdrop'); + // Apply a 100% contrast filter to the entire game (this value can be tweened, modified in-game, etc) + game.stage.css3.grayscale = 100; + } + function update() { + if(game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + game.camera.x -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + game.camera.x += 4; + } + if(game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + game.camera.y -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + game.camera.y += 4; + } + } +})(); diff --git a/Tests/stage/grayscale filter.ts b/Tests/stage/grayscale filter.ts new file mode 100644 index 00000000..2baeb0cd --- /dev/null +++ b/Tests/stage/grayscale filter.ts @@ -0,0 +1,47 @@ +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + + function init() { + + game.load.image('backdrop', 'assets/pics/remember-me.jpg'); + game.load.start(); + + } + + function create() { + + game.world.setSize(1920, 1200); + + game.add.sprite(0, 0, 'backdrop'); + + // Apply a 100% contrast filter to the entire game (this value can be tweened, modified in-game, etc) + game.stage.css3.grayscale = 100; + + } + + function update() { + + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) + { + game.camera.x -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) + { + game.camera.x += 4; + } + + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) + { + game.camera.y -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) + { + game.camera.y += 4; + } + + } + +})(); diff --git a/Tests/stage/hue rotate filter.js b/Tests/stage/hue rotate filter.js new file mode 100644 index 00000000..e1684de0 --- /dev/null +++ b/Tests/stage/hue rotate filter.js @@ -0,0 +1,28 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + function init() { + game.load.image('backdrop', 'assets/pics/large-color-wheel.png'); + game.load.image('coke', 'assets/sprites/cokecan.png'); + game.load.image('mushroom', 'assets/sprites/mushroom2.png'); + game.load.start(); + } + var hue = 0; + function create() { + game.world.setSize(800, 800); + game.add.sprite(0, 0, 'backdrop'); + game.add.sprite(30, 20, 'coke'); + game.add.sprite(600, 20, 'mushroom'); + } + function update() { + // The value is given in degrees, so between 0 and 360, hence the wrapValue call below. + hue = game.math.wrapValue(hue, 1, 360); + // Apply a hue rotation to the stage + game.stage.css3.hueRotate = hue; + if(game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + game.camera.y -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + game.camera.y += 4; + } + } +})(); diff --git a/Tests/stage/hue rotate filter.ts b/Tests/stage/hue rotate filter.ts new file mode 100644 index 00000000..362c11b2 --- /dev/null +++ b/Tests/stage/hue rotate filter.ts @@ -0,0 +1,47 @@ +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + + function init() { + + game.load.image('backdrop', 'assets/pics/large-color-wheel.png'); + game.load.image('coke', 'assets/sprites/cokecan.png'); + game.load.image('mushroom', 'assets/sprites/mushroom2.png'); + game.load.start(); + + } + + var hue: number = 0; + + function create() { + + game.world.setSize(800, 800); + + game.add.sprite(0, 0, 'backdrop'); + game.add.sprite(30, 20, 'coke'); + game.add.sprite(600, 20, 'mushroom'); + + } + + function update() { + + // The value is given in degrees, so between 0 and 360, hence the wrapValue call below. + hue = game.math.wrapValue(hue, 1, 360); + + // Apply a hue rotation to the stage + game.stage.css3.hueRotate = hue; + + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) + { + game.camera.y -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) + { + game.camera.y += 4; + } + + } + +})(); diff --git a/Tests/stage/sepia filter.js b/Tests/stage/sepia filter.js new file mode 100644 index 00000000..6302640f --- /dev/null +++ b/Tests/stage/sepia filter.js @@ -0,0 +1,26 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + function init() { + game.load.image('backdrop', 'assets/pics/remember-me.jpg'); + game.load.start(); + } + function create() { + game.world.setSize(1920, 1200); + game.add.sprite(0, 0, 'backdrop'); + // Apply a 100% sepia filter to the entire game (this value can be tweened, modified in-game, etc) + game.stage.css3.sepia = 100; + } + function update() { + if(game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + game.camera.x -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + game.camera.x += 4; + } + if(game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + game.camera.y -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + game.camera.y += 4; + } + } +})(); diff --git a/Tests/stage/sepia filter.ts b/Tests/stage/sepia filter.ts new file mode 100644 index 00000000..e6fb78a8 --- /dev/null +++ b/Tests/stage/sepia filter.ts @@ -0,0 +1,47 @@ +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + + function init() { + + game.load.image('backdrop', 'assets/pics/remember-me.jpg'); + game.load.start(); + + } + + function create() { + + game.world.setSize(1920, 1200); + + game.add.sprite(0, 0, 'backdrop'); + + // Apply a 100% sepia filter to the entire game (this value can be tweened, modified in-game, etc) + game.stage.css3.sepia = 100; + + } + + function update() { + + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) + { + game.camera.x -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) + { + game.camera.x += 4; + } + + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) + { + game.camera.y -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) + { + game.camera.y += 4; + } + + } + +})(); diff --git a/Tests/textures/filter test.js b/Tests/textures/filter test.js new file mode 100644 index 00000000..74f81eb4 --- /dev/null +++ b/Tests/textures/filter test.js @@ -0,0 +1,39 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + function init() { + game.load.image('backdrop', 'assets/pics/large-color-wheel.png'); + game.load.image('coke', 'assets/sprites/cokecan.png'); + game.load.image('mushroom', 'assets/sprites/mushroom2.png'); + game.load.start(); + } + var hue = 0; + var texture; + function create() { + game.world.setSize(800, 800); + texture = game.add.dynamicTexture(800, 600); + var backdrop = game.add.sprite(0, 0, 'backdrop'); + var cokecan = game.add.sprite(30, 20, 'coke'); + var mushroom = game.add.sprite(600, 20, 'mushroom'); + texture.assignCanvasToGameObjects([ + backdrop, + cokecan, + mushroom + ]); + texture.css3.grayscale = 100; + } + function update() { + // The value is given in degrees, so between 0 and 360, hence the wrapValue call below. + hue = game.math.wrapValue(hue, 1, 360); + // Apply a hue rotation to the stage + //game.stage.css3.hueRotate = hue; + if(game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + game.camera.y -= 4; + } else if(game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + game.camera.y += 4; + } + } + function render() { + texture.render(); + } +})(); diff --git a/Tests/textures/filter test.ts b/Tests/textures/filter test.ts new file mode 100644 index 00000000..ab1dcdee --- /dev/null +++ b/Tests/textures/filter test.ts @@ -0,0 +1,61 @@ +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + function init() { + + game.load.image('backdrop', 'assets/pics/large-color-wheel.png'); + game.load.image('coke', 'assets/sprites/cokecan.png'); + game.load.image('mushroom', 'assets/sprites/mushroom2.png'); + game.load.start(); + + } + + var hue: number = 0; + var texture: Phaser.DynamicTexture; + + function create() { + + game.world.setSize(800, 800); + + texture = game.add.dynamicTexture(800, 600); + + var backdrop = game.add.sprite(0, 0, 'backdrop'); + var cokecan = game.add.sprite(30, 20, 'coke'); + var mushroom = game.add.sprite(600, 20, 'mushroom'); + + texture.assignCanvasToGameObjects([backdrop, cokecan, mushroom]); + + // Rats, filters don't get applied when the canvas is drawn to another canvas. Oh well :) + texture.css3.grayscale = 100; + + } + + function update() { + + // The value is given in degrees, so between 0 and 360, hence the wrapValue call below. + hue = game.math.wrapValue(hue, 1, 360); + + // Apply a hue rotation to the stage + //game.stage.css3.hueRotate = hue; + + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) + { + game.camera.y -= 4; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) + { + game.camera.y += 4; + } + + } + + function render() { + + texture.render(); + + } + +})(); diff --git a/build/phaser.d.ts b/build/phaser.d.ts index 50fea951..33f5318a 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -1,4 +1,4 @@ -/** +/** * Phaser - Point * * The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis. @@ -1325,6 +1325,11 @@ module Phaser { private _dw; private _dh; /** + * Controls the CSS3 Filters applied to the textures canvas object. + * @type {Phaser.Components.CSS3Filters} + */ + public css3: Components.CSS3Filters; + /** * Bound of this texture with width and height info. * @type {Rectangle} */ @@ -4365,6 +4370,43 @@ module Phaser { } } /** +* Phaser - Net +* +* +*/ +module Phaser { + class Net { + /** + * Net constructor + */ + constructor(game: Game); + /** + * Local reference to the current Phaser.Game. + */ + public game: Game; + /** + * Compares the given domain name against the hostname of the browser containing the game. + * If the domain name is found it returns true. + * You can specify a part of a domain, for example 'google' would match 'google.com', 'google.co.uk', etc. + * Do not include 'http://' at the start. + */ + public checkDomainName(domain: string): bool; + /** + * Updates a value on the Query String and returns it in full. + * If the value doesn't already exist it is set. + * If the value exists it is replaced with the new value given. If you don't provide a new value it is removed from the query string. + * Optionally you can redirect to the new url, or just return it as a string. + */ + public updateQueryString(key: string, value: string, redirect?: bool, url?: string): string; + /** + * Returns the Query String as an object. + * If you specify a parameter it will return just the value of that parameter, should it exist. + */ + public getQueryString(parameter?: string): {}; + private decodeURI(value); + } +} +/** * Phaser - Cache * * A game only has one instance of a Cache and it is used to store all externally loaded assets such @@ -7063,7 +7105,6 @@ module Phaser { /** * Phaser - SoundManager * -* This is an embroyonic web audio sound management class. There is a lot of work still to do here. */ module Phaser { class SoundManager { @@ -7141,6 +7182,92 @@ module Phaser { var VERSION: string; } /** +* Phaser - Components - CSS3Filters +* +* Allows for easy addition and modification of CSS3 Filters on DOM objects (typically the Game.Stage.canvas). +*/ +module Phaser.Components { + class CSS3Filters { + /** + * Creates a new CSS3 Filter component + * @param parent The DOM object to apply the filters to. + */ + constructor(parent); + /** + * Reference to the parent DOM object (stage.canvas for example) + */ + public parent; + private _blur; + private _grayscale; + private _sepia; + private _brightness; + private _contrast; + private _hueRotate; + private _invert; + private _opacity; + private _saturate; + private setFilter(local, prefix, value, unit); + /** + * Applies a Gaussian blur to the DOM element. The value of ‘radius’ defines the value of the standard deviation to the Gaussian function, + * or how many pixels on the screen blend into each other, so a larger value will create more blur. + * If no parameter is provided, then a value 0 is used. The parameter is specified as a CSS length, but does not accept percentage values. + */ + public blur : number; + /** + * Converts the input image to grayscale. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely grayscale. A value of 0% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public grayscale : number; + /** + * Converts the input image to sepia. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely sepia. A value of 0 leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public sepia : number; + /** + * Applies a linear multiplier to input image, making it appear more or less bright. + * A value of 0% will create an image that is completely black. A value of 100% leaves the input unchanged. + * Other values are linear multipliers on the effect. Values of an amount over 100% are allowed, providing brighter results. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public brightness : number; + /** + * Adjusts the contrast of the input. A value of 0% will create an image that is completely black. + * A value of 100% leaves the input unchanged. Values of amount over 100% are allowed, providing results with less contrast. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public contrast : number; + /** + * Applies a hue rotation on the input image. The value of ‘angle’ defines the number of degrees around the color circle + * the input samples will be adjusted. A value of 0deg leaves the input unchanged. If the ‘angle’ parameter is missing, + * a value of 0deg is used. Maximum value is 360deg. + */ + public hueRotate : number; + /** + * Inverts the samples in the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely inverted. A value of 0% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public invert : number; + /** + * Applies transparency to the samples in the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 0% is completely transparent. A value of 100% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. This is equivalent to multiplying the input image samples by amount. + * If the ‘amount’ parameter is missing, a value of 100% is used. + * This function is similar to the more established opacity property; the difference is that with filters, some browsers provide hardware acceleration for better performance. + */ + public opacity : number; + /** + * Saturates the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 0% is completely un-saturated. A value of 100% leaves the input unchanged. + * Other values are linear multipliers on the effect. Values of amount over 100% are allowed, providing super-saturated results. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + public saturate : number; + } +} +/** * Phaser - StageScaleMode * * This class controls the scaling of your game. On mobile devices it will also remove the URL bar and allow @@ -7246,6 +7373,11 @@ module Phaser { */ public aspectRatio: number; /** + * The maximum number of times it will try to resize the canvas to fill the browser (default is 10) + * @type {number} + */ + public maxIterations: number; + /** * The scale factor of the scaled game width * @type {Vec2} */ @@ -7502,6 +7634,11 @@ module Phaser { */ public orientationScreen; /** + * Controls the CSS3 Filters applied to the Stages canvas object. + * @type {Phaser.Components.CSS3Filters} + */ + public css3: Components.CSS3Filters; + /** * Bound of this stage. * @type {Rectangle} */ @@ -9823,6 +9960,11 @@ module Phaser { */ public motion: Motion; /** + * Reference to the network class. + * @type {Net} + */ + public net: Net; + /** * Reference to the sound manager. * @type {SoundManager} */ diff --git a/build/phaser.js b/build/phaser.js index 163996cf..ff65ffdd 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -1,4 +1,4 @@ -/// +/// /** * Phaser - Point * @@ -2004,6 +2004,7 @@ var Phaser; this.canvas.width = width; this.canvas.height = height; this.context = this.canvas.getContext('2d'); + this.css3 = new Phaser.Components.CSS3Filters(this.canvas); this.bounds = new Phaser.Rectangle(0, 0, width, height); } DynamicTexture.prototype.getPixel = /** @@ -3607,6 +3608,7 @@ var Phaser; */ function (pointer) { if(this.enabled == false || this._parent.visible == false) { + this._pointerOutHandler(pointer); return false; } if(this.draggable && this._draggedPointerID == pointer.id) { @@ -9461,6 +9463,97 @@ var Phaser; })(Phaser || (Phaser = {})); /// /** +* Phaser - Net +* +* +*/ +var Phaser; +(function (Phaser) { + var Net = (function () { + /** + * Net constructor + */ + function Net(game) { + this.game = game; + } + Net.prototype.checkDomainName = /** + * Compares the given domain name against the hostname of the browser containing the game. + * If the domain name is found it returns true. + * You can specify a part of a domain, for example 'google' would match 'google.com', 'google.co.uk', etc. + * Do not include 'http://' at the start. + */ + function (domain) { + return window.location.hostname.indexOf(domain) !== -1; + }; + Net.prototype.updateQueryString = /** + * Updates a value on the Query String and returns it in full. + * If the value doesn't already exist it is set. + * If the value exists it is replaced with the new value given. If you don't provide a new value it is removed from the query string. + * Optionally you can redirect to the new url, or just return it as a string. + */ + function (key, value, redirect, url) { + if (typeof redirect === "undefined") { redirect = false; } + if (typeof url === "undefined") { url = ''; } + if(url == '') { + url = window.location.href; + } + var output = ''; + var re = new RegExp("([?|&])" + key + "=.*?(&|#|$)(.*)", "gi"); + if(re.test(url)) { + if(typeof value !== 'undefined' && value !== null) { + output = url.replace(re, '$1' + key + "=" + value + '$2$3'); + } else { + output = url.replace(re, '$1$3').replace(/(&|\?)$/, ''); + } + } else { + if(typeof value !== 'undefined' && value !== null) { + var separator = url.indexOf('?') !== -1 ? '&' : '?'; + var hash = url.split('#'); + url = hash[0] + separator + key + '=' + value; + if(hash[1]) { + url += '#' + hash[1]; + } + output = url; + } else { + output = url; + } + } + if(redirect) { + window.location.href = output; + } else { + return output; + } + }; + Net.prototype.getQueryString = /** + * Returns the Query String as an object. + * If you specify a parameter it will return just the value of that parameter, should it exist. + */ + function (parameter) { + if (typeof parameter === "undefined") { parameter = ''; } + var output = { + }; + var keyValues = location.search.substring(1).split('&'); + for(var i in keyValues) { + var key = keyValues[i].split('='); + if(key.length > 1) { + if(parameter && parameter == this.decodeURI(key[0])) { + return this.decodeURI(key[1]); + } else { + output[this.decodeURI(key[0])] = this.decodeURI(key[1]); + } + } + } + return output; + }; + Net.prototype.decodeURI = function (value) { + return decodeURIComponent(value.replace(/\+/g, " ")); + }; + return Net; + })(); + Phaser.Net = Net; +})(Phaser || (Phaser = {})); +/// +/** * Phaser - Cache * * A game only has one instance of a Cache and it is used to store all externally loaded assets such @@ -14349,7 +14442,7 @@ var Phaser; } } else { //console.log('Sound play Audio'); - if(this.game.cache.getSound(this.key).locked) { + 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; @@ -14362,7 +14455,11 @@ var Phaser; //console.log('playing', this._sound); this._sound.currentTime = this.position; this._sound.muted = this._muted; - this._sound.volume = this._volume; + 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; @@ -14503,7 +14600,6 @@ var Phaser; /** * Phaser - SoundManager * -* This is an embroyonic web audio sound management class. There is a lot of work still to do here. */ var Phaser; (function (Phaser) { @@ -14612,6 +14708,7 @@ var Phaser; return this._muted; }, set: function (value) { + console.log('SoundManager mute', value); if(value) { if(this._muted) { return; @@ -14623,7 +14720,7 @@ var Phaser; } // Loop through sounds for(var i = 0; i < this._sounds.length; i++) { - if(this._sounds[i]) { + if(this._sounds[i].usingAudioTag) { this._sounds[i].mute = true; } } @@ -14637,7 +14734,7 @@ var Phaser; } // Loop through sounds for(var i = 0; i < this._sounds.length; i++) { - if(this._sounds[i]) { + if(this._sounds[i].usingAudioTag) { this._sounds[i].mute = false; } } @@ -14761,6 +14858,192 @@ var Phaser; (function (Phaser) { Phaser.VERSION = 'Phaser version 1.0.0'; })(Phaser || (Phaser = {})); +var Phaser; +(function (Phaser) { + /// + /** + * Phaser - Components - CSS3Filters + * + * Allows for easy addition and modification of CSS3 Filters on DOM objects (typically the Game.Stage.canvas). + */ + (function (Components) { + var CSS3Filters = (function () { + /** + * Creates a new CSS3 Filter component + * @param parent The DOM object to apply the filters to. + */ + function CSS3Filters(parent) { + this._blur = 0; + this._grayscale = 0; + this._sepia = 0; + this._brightness = 0; + this._contrast = 0; + this._hueRotate = 0; + this._invert = 0; + this._opacity = 0; + this._saturate = 0; + this.parent = parent; + } + CSS3Filters.prototype.setFilter = function (local, prefix, value, unit) { + this[local] = value; + if(this.parent) { + this.parent.style['-webkit-filter'] = prefix + '(' + value + unit + ')'; + } + }; + Object.defineProperty(CSS3Filters.prototype, "blur", { + get: function () { + return this._blur; + }, + set: /** + * Applies a Gaussian blur to the DOM element. The value of ‘radius’ defines the value of the standard deviation to the Gaussian function, + * or how many pixels on the screen blend into each other, so a larger value will create more blur. + * If no parameter is provided, then a value 0 is used. The parameter is specified as a CSS length, but does not accept percentage values. + */ + function (radius) { + if (typeof radius === "undefined") { radius = 0; } + this.setFilter('_blur', 'blur', radius, 'px'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "grayscale", { + get: function () { + return this._grayscale; + }, + set: /** + * Converts the input image to grayscale. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely grayscale. A value of 0% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (amount) { + if (typeof amount === "undefined") { amount = 100; } + this.setFilter('_grayscale', 'grayscale', amount, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "sepia", { + get: function () { + return this._sepia; + }, + set: /** + * Converts the input image to sepia. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely sepia. A value of 0 leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (amount) { + if (typeof amount === "undefined") { amount = 100; } + this.setFilter('_sepia', 'sepia', amount, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "brightness", { + get: function () { + return this._brightness; + }, + set: /** + * Applies a linear multiplier to input image, making it appear more or less bright. + * A value of 0% will create an image that is completely black. A value of 100% leaves the input unchanged. + * Other values are linear multipliers on the effect. Values of an amount over 100% are allowed, providing brighter results. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (amount) { + if (typeof amount === "undefined") { amount = 100; } + this.setFilter('_brightness', 'brightness', amount, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "contrast", { + get: function () { + return this._contrast; + }, + set: /** + * Adjusts the contrast of the input. A value of 0% will create an image that is completely black. + * A value of 100% leaves the input unchanged. Values of amount over 100% are allowed, providing results with less contrast. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (amount) { + if (typeof amount === "undefined") { amount = 100; } + this.setFilter('_contrast', 'contrast', amount, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "hueRotate", { + get: function () { + return this._hueRotate; + }, + set: /** + * Applies a hue rotation on the input image. The value of ‘angle’ defines the number of degrees around the color circle + * the input samples will be adjusted. A value of 0deg leaves the input unchanged. If the ‘angle’ parameter is missing, + * a value of 0deg is used. Maximum value is 360deg. + */ + function (angle) { + if (typeof angle === "undefined") { angle = 0; } + this.setFilter('_hueRotate', 'hue-rotate', angle, 'deg'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "invert", { + get: function () { + return this._invert; + }, + set: /** + * Inverts the samples in the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 100% is completely inverted. A value of 0% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (value) { + if (typeof value === "undefined") { value = 100; } + this.setFilter('_invert', 'invert', value, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "opacity", { + get: function () { + return this._opacity; + }, + set: /** + * Applies transparency to the samples in the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 0% is completely transparent. A value of 100% leaves the input unchanged. + * Values between 0% and 100% are linear multipliers on the effect. This is equivalent to multiplying the input image samples by amount. + * If the ‘amount’ parameter is missing, a value of 100% is used. + * This function is similar to the more established opacity property; the difference is that with filters, some browsers provide hardware acceleration for better performance. + */ + function (value) { + if (typeof value === "undefined") { value = 100; } + this.setFilter('_opacity', 'opacity', value, '%'); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CSS3Filters.prototype, "saturate", { + get: function () { + return this._saturate; + }, + set: /** + * Saturates the input image. The value of ‘amount’ defines the proportion of the conversion. + * A value of 0% is completely un-saturated. A value of 100% leaves the input unchanged. + * Other values are linear multipliers on the effect. Values of amount over 100% are allowed, providing super-saturated results. + * If the ‘amount’ parameter is missing, a value of 100% is used. + */ + function (value) { + if (typeof value === "undefined") { value = 100; } + this.setFilter('_saturate', 'saturate', value, '%'); + }, + enumerable: true, + configurable: true + }); + return CSS3Filters; + })(); + Components.CSS3Filters = CSS3Filters; + })(Phaser.Components || (Phaser.Components = {})); + var Components = Phaser.Components; +})(Phaser || (Phaser = {})); /// /** * Phaser - StageScaleMode @@ -14843,6 +15126,11 @@ var Phaser; * @type {number} */ this.height = 0; + /** + * The maximum number of times it will try to resize the canvas to fill the browser (default is 10) + * @type {number} + */ + this.maxIterations = 10; this._game = game; this.enterLandscape = new Phaser.Signal(); this.enterPortrait = new Phaser.Signal(); @@ -14994,8 +15282,8 @@ var Phaser; window.scrollTo(0, 0); } } - if(this._check == null) { - this._iterations = 10; + if(this._check == null && this.maxIterations > 0) { + this._iterations = this.maxIterations; this._check = window.setInterval(function () { return _this.setScreenSize(); }, 10); @@ -15348,6 +15636,7 @@ var Phaser; })(Phaser || (Phaser = {})); /// /// +/// /// /// /// @@ -15413,6 +15702,7 @@ var Phaser; event.preventDefault(); }; this.context = this.canvas.getContext('2d'); + this.css3 = new Phaser.Components.CSS3Filters(this.canvas); this.scaleMode = Phaser.StageScaleMode.NO_SCALE; this.scale = new Phaser.StageScaleMode(this._game, width, height); this.getOffset(this.canvas); @@ -15453,8 +15743,13 @@ var Phaser; function () { this.scale.update(); if(this.clear) { - // implement dirty rect? could take up more cpu time than it saves. needs benching. - this.context.clearRect(0, 0, this.width, this.height); + // A 'fix' for the horrendous Android stock browser bug: https://code.google.com/p/android/issues/detail?id=39247 + if(this._game.device.android && this._game.device.chrome == false) { + this.context.fillStyle = 'rgb(0,0,0)'; + this.context.fillRect(0, 0, this.width, this.height); + } else { + this.context.clearRect(0, 0, this.width, this.height); + } } if(this._game.paused && this.scale.incorrectOrientation) { this.orientationScreen.update(); @@ -19618,6 +19913,7 @@ var Phaser; /// /// /// +/// /// /// /// @@ -19790,6 +20086,7 @@ var Phaser; }, 13); } else { this.device = new Phaser.Device(); + this.net = new Phaser.Net(this); this.motion = new Phaser.Motion(this); this.math = new Phaser.GameMath(this); this.stage = new Phaser.Stage(this, parent, width, height);