diff --git a/Phaser/Game.ts b/Phaser/Game.ts index 44d44fdb..5c4f79a4 100644 --- a/Phaser/Game.ts +++ b/Phaser/Game.ts @@ -398,7 +398,7 @@ module Phaser { return this.world.createEmitter(x, y, size); } - public createScrollZone(key:string, x: number, y: number, width: number, height: number): ScrollZone { + public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone { return this.world.createScrollZone(key, x, y, width, height); } diff --git a/Phaser/Phaser.csproj b/Phaser/Phaser.csproj index db8bad1e..d45371f8 100644 --- a/Phaser/Phaser.csproj +++ b/Phaser/Phaser.csproj @@ -86,6 +86,10 @@ Particle.ts + + + ScrollRegion.ts + ScrollZone.ts diff --git a/Phaser/State.ts b/Phaser/State.ts index 408ed298..df5cb6da 100644 --- a/Phaser/State.ts +++ b/Phaser/State.ts @@ -82,7 +82,7 @@ module Phaser { return this.game.world.createEmitter(x, y, size); } - public createScrollZone(key:string, x: number, y: number, width: number, height: number): ScrollZone { + public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone { return this.game.world.createScrollZone(key, x, y, width, height); } diff --git a/Phaser/World.ts b/Phaser/World.ts index dbe234ae..51af8e17 100644 --- a/Phaser/World.ts +++ b/Phaser/World.ts @@ -108,11 +108,6 @@ module Phaser { // Cameras - public addExistingCamera(cam: Camera): Camera { - //return this._cameras.addCamera(x, y, width, height); - return cam; - } - public createCamera(x: number, y: number, width: number, height: number): Camera { return this._cameras.addCamera(x, y, width, height); } @@ -127,11 +122,6 @@ module Phaser { // Game Objects - // Drop this? - public addExistingSprite(sprite: Sprite): Sprite { - return this.group.add(sprite); - } - public createSprite(x: number, y: number, key?: string = ''): Sprite { return this.group.add(new Sprite(this._game, x, y, key)); } @@ -148,7 +138,7 @@ module Phaser { return this.group.add(new Group(this._game, MaxSize)); } - public createScrollZone(key: string, x: number, y: number, width: number, height: number): ScrollZone { + public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone { return this.group.add(new ScrollZone(this._game, key, x, y, width, height)); } diff --git a/Phaser/gameobjects/ScrollRegion.ts b/Phaser/gameobjects/ScrollRegion.ts new file mode 100644 index 00000000..97ff5404 --- /dev/null +++ b/Phaser/gameobjects/ScrollRegion.ts @@ -0,0 +1,146 @@ +/// +/// + +/** +* Phaser - ScrollRegion +* +* Creates a scrolling region within a ScrollZone. +* It is scrolled via the scrollSpeed.x/y properties. +*/ + +module Phaser { + + export class ScrollRegion{ + + constructor(x: number, y: number, width: number, height: number, speedX:number, speedY:number) { + + // Our seamless scrolling quads + this._A = new Quad(0, 0, width, height); + this._B = new Quad(); + this._C = new Quad(); + this._D = new Quad(); + + this._scroll = new MicroPoint(); + this._offset = new MicroPoint(x, y); + + this.scrollSpeed = new MicroPoint(speedX, speedY); + this.bounds = new Quad(0, 0, width, height); + + } + + private _A: Quad; + private _B: Quad; + private _C: Quad; + private _D: Quad; + + private _scroll: MicroPoint; + private _offset: MicroPoint; + + private _anchorWidth: number = 0; + private _anchorHeight: number = 0; + private _inverseWidth: number = 0; + private _inverseHeight: number = 0; + + public bounds: Quad; + public visible: bool = true; + public scrollSpeed: MicroPoint; + + public update(delta: number) { + + this._scroll.x = Math.round(this._scroll.x + (this.scrollSpeed.x)); + this._scroll.y = Math.round(this._scroll.y + (this.scrollSpeed.y)); + + if (this._scroll.x > this._offset.x + this.bounds.width) + { + this._scroll.x = this._offset.x; + } + + if (this._scroll.x < this._offset.x) + { + this._scroll.x = this._offset.x + this.bounds.width; + } + + if (this._scroll.y > this._offset.y + this.bounds.height) + { + this._scroll.y = this._offset.y; + } + + if (this._scroll.y < this._offset.y) + { + this._scroll.y = this._offset.y + this.bounds.height; + } + + // Anchor Dimensions + this._anchorWidth = this.bounds.width - this._scroll.x; + this._anchorHeight = this.bounds.height - this._scroll.y; + + if (this._anchorWidth > this.bounds.width) + { + this._anchorWidth = this.bounds.width; + } + + if (this._anchorHeight > this.bounds.height) + { + this._anchorHeight = this.bounds.height; + } + + this._inverseWidth = this.bounds.width - this._anchorWidth; + this._inverseHeight = this.bounds.height - this._anchorHeight; + + // Quad A + this._A.setTo(this._scroll.x, this._scroll.y, this._anchorWidth, this._anchorHeight); + + // Quad B + this._B.y = this._scroll.y; + this._B.width = this._inverseWidth; + this._B.height = this._anchorHeight; + + // Quad C + this._C.x = this._scroll.x; + this._C.width = this._anchorWidth; + this._C.height = this._inverseHeight; + + // Quad D + this._D.width = this._inverseWidth; + this._D.height = this._inverseHeight; + + } + + public render(context:CanvasRenderingContext2D, texture, dx: number, dy: number, dw: number, dh: number) { + + if (this.visible == false) + { + return; + } + + this.crop(context, texture, this._A.x, this._A.y, this._A.width, this._A.height, dx, dy, dw, dh, 0, 0); + this.crop(context, texture, this._B.x, this._B.y, this._B.width, this._B.height, dx, dy, dw, dh, this._A.width, 0); + this.crop(context, texture, this._C.x, this._C.y, this._C.width, this._C.height, dx, dy, dw, dh, 0, this._A.height); + this.crop(context, texture, this._D.x, this._D.y, this._D.width, this._D.height, dx, dy, dw, dh, this._C.width, this._A.height); + + } + + private crop(context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY) { + + offsetX += destX; + offsetY += destY; + + if (srcW > (destX + destW) - offsetX) + { + srcW = (destX + destW) - offsetX; + } + + if (srcH > (destY + destH) - offsetY) + { + srcH = (destY + destH) - offsetY; + } + + if (srcW > 0 && srcH > 0) + { + context.drawImage(texture, srcX, srcY, srcW, srcH, offsetX, offsetY, srcW, srcH); + } + } + + } + +} diff --git a/Phaser/gameobjects/ScrollZone.ts b/Phaser/gameobjects/ScrollZone.ts index 44c91d06..7d4094ed 100644 --- a/Phaser/gameobjects/ScrollZone.ts +++ b/Phaser/gameobjects/ScrollZone.ts @@ -1,12 +1,13 @@ /// /// +/// /** * Phaser - ScrollZone * * Creates a scrolling region of the given width and height from an image in the cache. -* The ScrollZone can be positioned anywhere in-world like a normal game object. -* The image within it is scrolled via the scrollSpeed.x/y properties. +* The ScrollZone can be positioned anywhere in-world like a normal game object, re-act to physics, collision, etc. +* The image within it is scrolled via ScrollRegions and their scrollSpeed.x/y properties. * If you create a scroll zone larger than the given source image it will create a DynamicTexture and fill it with a pattern of the source image. */ @@ -14,37 +15,36 @@ module Phaser { export class ScrollZone extends GameObject { - /** - * - */ - constructor(game: Game, key:string, x: number, y: number, width: number, height: number) { + constructor(game: Game, key:string, x: number = 0, y: number = 0, width?: number = 0, height?: number = 0) { super(game, x, y, width, height); - // Our seamless scrolling quads - this._A = new Quad(0, 0, width, height); - this._B = new Quad(); - this._C = new Quad(); - this._D = new Quad(); - - this._scroll = new MicroPoint(); - - this.offset = new MicroPoint(); - this.scrollSpeed = new MicroPoint(); + this.regions = []; if (this._game.cache.getImage(key)) { this._texture = this._game.cache.getImage(key); - this.bounds.width = width; - this.bounds.height = height; - this._sourceWidth = this._texture.width; - this._sourceHeight = this._texture.height; + this.width = this._texture.width; + this.height = this._texture.height; + + if (width > this._texture.width || height > this._texture.height) + { + // Create our repeating texture (as the source image wasn't large enough for the requested size) + this.createRepeatingTexture(width, height); + this.width = width; + this.height = height; + } + + // Create a default ScrollRegion at the requested size + this.addRegion(0, 0, this.width, this.height); + + // If the zone is smaller than the image itself then shrink the bounds + if ((width < this._texture.width || height < this._texture.height) && width !== 0 && height !== 0) + { + this.width = width; + this.height = height; + } - // If the Scrolling Zone is BIGGER than the texture then we need to create a repeating pattern DynamicTexture - if (this._texture.width < width || this._texture.height < height) - { - this.createRepeatingTexture(); - } } } @@ -52,88 +52,41 @@ module Phaser { private _texture; private _dynamicTexture: DynamicTexture = null; - private _A: Quad; - private _B: Quad; - private _C: Quad; - private _D: Quad; - - private _scroll: MicroPoint; - private _sourceWidth: number; - private _sourceHeight: number; - // local rendering related temp vars to help avoid gc spikes private _dx: number = 0; private _dy: number = 0; private _dw: number = 0; private _dh: number = 0; - private _anchorWidth: number = 0; - private _anchorHeight: number = 0; - private _inverseWidth: number = 0; - private _inverseHeight: number = 0; - - public scrollSpeed: MicroPoint; - public offset: MicroPoint; + public currentRegion: ScrollRegion; + public regions: ScrollRegion[]; public flipped: bool = false; + public addRegion(x: number, y: number, width: number, height: number, speedX?:number = 0, speedY?:number = 0):ScrollRegion { + + this.currentRegion = new ScrollRegion(x, y, width, height, speedX, speedY); + + this.regions.push(this.currentRegion); + + return this.currentRegion; + + } + + public setSpeed(x: number, y: number) { + + if (this.currentRegion) + { + this.currentRegion.scrollSpeed.setTo(x, y); + } + + } + public update() { - this._scroll.x = Math.round(this._scroll.x + this.scrollSpeed.x); - this._scroll.y = Math.round(this._scroll.y + this.scrollSpeed.y); - - if (this._scroll.x > this._sourceWidth) - { - this._scroll.x = 0; - } - - if (this._scroll.x < 0) - { - this._scroll.x = this._sourceWidth; - } - - if (this._scroll.y > this._sourceHeight) - { - this._scroll.y = 0; - } - - if (this._scroll.y < 0) - { - this._scroll.y = this._sourceHeight; - } - - // Anchor Dimensions - this._anchorWidth = this._sourceWidth - this._scroll.x; - this._anchorHeight = this._sourceHeight - this._scroll.y; - - if (this._anchorWidth > this.width) - { - this._anchorWidth = this.width; - } - - if (this._anchorHeight > this.height) - { - this._anchorHeight = this.height; - } - - this._inverseWidth = this.width - this._anchorWidth; - this._inverseHeight = this.height - this._anchorHeight; - - // Quad A - this._A.setTo(this._scroll.x, this._scroll.y, this._anchorWidth, this._anchorHeight); - - // Quad B - this._B.y = this._scroll.y; - this._B.width = this._inverseWidth; - this._B.height = this._anchorHeight; - - // Quad C - this._C.x = this._scroll.x; - this._C.width = this._anchorWidth; - this._C.height = this._inverseHeight; - - // Quad D - this._D.width = this._inverseWidth; - this._D.height = this._inverseHeight; + for (var i = 0; i < this.regions.length; i++) + { + this.regions[i].update(this._game.time.delta); + } } @@ -204,50 +157,19 @@ module Phaser { this._dx = Math.round(this._dx); this._dy = Math.round(this._dy); + this._dw = Math.round(this._dw); + this._dh = Math.round(this._dh); - if (this._dynamicTexture) + for (var i = 0; i < this.regions.length; i++) { - if (this._A.width !== 0 && this._A.height !== 0) - { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._A.x, this._A.y, this._A.width, this._A.height, this._dx, this._dy, this._A.width, this._A.height); - } - - if (this._B.width !== 0 && this._B.height !== 0) - { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._B.x, this._B.y, this._B.width, this._B.height, this._dx + this._A.width, this._dy, this._B.width, this._B.height); - } - - if (this._C.width !== 0 && this._C.height !== 0) - { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._C.x, this._C.y, this._C.width, this._C.height, this._dx, this._dy + this._A.height, this._C.width, this._C.height); - } - - if (this._D.width !== 0 && this._D.height !== 0) - { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._D.x, this._D.y, this._D.width, this._D.height, this._dx + this._C.width, this._dy + this._A.height, this._D.width, this._D.height); - } - } - else - { - if (this._A.width !== 0 && this._A.height !== 0) - { - this._game.stage.context.drawImage(this._texture, this._A.x, this._A.y, this._A.width, this._A.height, this._dx, this._dy, this._A.width, this._A.height); - } - - if (this._B.width !== 0 && this._B.height !== 0) - { - this._game.stage.context.drawImage(this._texture, this._B.x, this._B.y, this._B.width, this._B.height, this._dx + this._A.width, this._dy, this._B.width, this._B.height); - } - - if (this._C.width !== 0 && this._C.height !== 0) - { - this._game.stage.context.drawImage(this._texture, this._C.x, this._C.y, this._C.width, this._C.height, this._dx, this._dy + this._A.height, this._C.width, this._C.height); - } - - if (this._D.width !== 0 && this._D.height !== 0) - { - this._game.stage.context.drawImage(this._texture, this._D.x, this._D.y, this._D.width, this._D.height, this._dx + this._C.width, this._dy + this._A.height, this._D.width, this._D.height); - } + if (this._dynamicTexture) + { + this.regions[i].render(this._game.stage.context, this._dynamicTexture.canvas, this._dx, this._dy, this._dw, this._dh); + } + else + { + this.regions[i].render(this._game.stage.context, this._texture, this._dx, this._dy, this._dw, this._dh); + } } if (globalAlpha > -1) @@ -259,11 +181,11 @@ module Phaser { } - private createRepeatingTexture() { + private createRepeatingTexture(regionWidth: number, regionHeight: number) { // Work out how many we'll need of the source image to make it tile properly - var tileWidth = Math.ceil(this.width / this._sourceWidth) * this._sourceWidth; - var tileHeight = Math.ceil(this.height / this._sourceHeight) * this._sourceHeight; + var tileWidth = Math.ceil(this._texture.width / regionWidth) * regionWidth; + var tileHeight = Math.ceil(this._texture.height / regionHeight) * regionHeight; this._dynamicTexture = new DynamicTexture(this._game, tileWidth, tileHeight); @@ -271,9 +193,6 @@ module Phaser { this._dynamicTexture.context.fillStyle = this._dynamicTexture.context.createPattern(this._texture, "repeat"); this._dynamicTexture.context.fill(); - this._sourceWidth = tileWidth; - this._sourceHeight = tileHeight; - } } diff --git a/Phaser/geom/Quad.ts b/Phaser/geom/Quad.ts index d156c941..45e889a1 100644 --- a/Phaser/geom/Quad.ts +++ b/Phaser/geom/Quad.ts @@ -52,6 +52,35 @@ module Phaser { } + public get left(): number { + return this.x; + } + + public get right(): number { + return this.x + this.width; + } + + public get top(): number { + return this.y; + } + + public get bottom(): number { + return this.y + this.height; + } + + /** + * Determines whether the object specified intersects (overlaps) with this Quad object. + * This method checks the x, y, width, and height properties of the specified Quad object to see if it intersects with this Quad object. + * @method intersects + * @param {Quad} q The Quad to compare against to see if it intersects with this Quad. + * @param {Number} t A tolerance value to allow for an intersection test with padding, default to 0 + * @return {Boolean} A value of true if the specified object intersects with this Quad; otherwise false. + **/ + public intersects(q: Quad, t?: number = 0): bool { + + return !(q.left > this.right + t || q.right < this.left - t || q.top > this.bottom + t || q.bottom < this.top - t); + + } } diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index ca56161d..f1fd2fdb 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -110,6 +110,10 @@ parallax.ts + + + scroll window.ts + simple scrollzone.ts diff --git a/Tests/phaser.js b/Tests/phaser.js index 8f70d6d9..150af5fe 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -8522,12 +8522,8 @@ var Phaser; enumerable: true, configurable: true }); - World.prototype.addExistingCamera = // Cameras - function (cam) { - //return this._cameras.addCamera(x, y, width, height); - return cam; - }; - World.prototype.createCamera = function (x, y, width, height) { + World.prototype.createCamera = // Cameras + function (x, y, width, height) { return this._cameras.addCamera(x, y, width, height); }; World.prototype.removeCamera = function (id) { @@ -8536,12 +8532,8 @@ var Phaser; World.prototype.getAllCameras = function () { return this._cameras.getAll(); }; - World.prototype.addExistingSprite = // Game Objects - // Drop this? - function (sprite) { - return this.group.add(sprite); - }; - World.prototype.createSprite = function (x, y, key) { + World.prototype.createSprite = // Game Objects + function (x, y, key) { if (typeof key === "undefined") { key = ''; } return this.group.add(new Phaser.Sprite(this._game, x, y, key)); }; @@ -8556,6 +8548,10 @@ var Phaser; return this.group.add(new Phaser.Group(this._game, MaxSize)); }; World.prototype.createScrollZone = function (key, x, y, width, height) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof width === "undefined") { width = 0; } + if (typeof height === "undefined") { height = 0; } return this.group.add(new Phaser.ScrollZone(this._game, key, x, y, width, height)); }; World.prototype.createTilemap = function (key, mapData, format, resizeWorld, tileWidth, tileHeight) { @@ -11477,6 +11473,10 @@ var Phaser; return this.world.createEmitter(x, y, size); }; Game.prototype.createScrollZone = function (key, x, y, width, height) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof width === "undefined") { width = 0; } + if (typeof height === "undefined") { height = 0; } return this.world.createScrollZone(key, x, y, width, height); }; Game.prototype.createTilemap = function (key, mapData, format, resizeWorld, tileWidth, tileHeight) { @@ -11541,6 +11541,46 @@ var Phaser; this.height = height; return this; }; + Object.defineProperty(Quad.prototype, "left", { + get: function () { + return this.x; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Quad.prototype, "right", { + get: function () { + return this.x + this.width; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Quad.prototype, "top", { + get: function () { + return this.y; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Quad.prototype, "bottom", { + get: function () { + return this.y + this.height; + }, + enumerable: true, + configurable: true + }); + Quad.prototype.intersects = /** + * Determines whether the object specified intersects (overlaps) with this Quad object. + * This method checks the x, y, width, and height properties of the specified Quad object to see if it intersects with this Quad object. + * @method intersects + * @param {Quad} q The Quad to compare against to see if it intersects with this Quad. + * @param {Number} t A tolerance value to allow for an intersection test with padding, default to 0 + * @return {Boolean} A value of true if the specified object intersects with this Quad; otherwise false. + **/ + function (q, t) { + if (typeof t === "undefined") { t = 0; } + return !(q.left > this.right + t || q.right < this.left - t || q.top > this.bottom + t || q.bottom < this.top - t); + }; return Quad; })(); Phaser.Quad = Quad; @@ -11548,79 +11588,56 @@ var Phaser; /// /// /** -* Phaser - ScrollZone +* Phaser - ScrollRegion * -* Creates a scrolling region of the given width and height from an image in the cache. -* The ScrollZone can be positioned anywhere in-world like a normal game object. -* The image within it is scrolled via the scrollSpeed.x/y properties. -* If you create a scroll zone larger than the given source image it will create a DynamicTexture and fill it with a pattern of the source image. +* Creates a scrolling region within a ScrollZone. +* It is scrolled via the scrollSpeed.x/y properties. */ var Phaser; (function (Phaser) { - var ScrollZone = (function (_super) { - __extends(ScrollZone, _super); - /** - * - */ - function ScrollZone(game, key, x, y, width, height) { - _super.call(this, game, x, y, width, height); - this._dynamicTexture = null; - // local rendering related temp vars to help avoid gc spikes - this._dx = 0; - this._dy = 0; - this._dw = 0; - this._dh = 0; + var ScrollRegion = (function () { + function ScrollRegion(x, y, width, height, speedX, speedY) { this._anchorWidth = 0; this._anchorHeight = 0; this._inverseWidth = 0; this._inverseHeight = 0; - this.flipped = false; + this.visible = true; // Our seamless scrolling quads this._A = new Phaser.Quad(0, 0, width, height); this._B = new Phaser.Quad(); this._C = new Phaser.Quad(); this._D = new Phaser.Quad(); this._scroll = new Phaser.MicroPoint(); - this.offset = new Phaser.MicroPoint(); - this.scrollSpeed = new Phaser.MicroPoint(); - if(this._game.cache.getImage(key)) { - this._texture = this._game.cache.getImage(key); - this.bounds.width = width; - this.bounds.height = height; - this._sourceWidth = this._texture.width; - this._sourceHeight = this._texture.height; - // If the Scrolling Zone is BIGGER than the texture we need to create a repeating pattern DynamicTexture - if(this._texture.width < width || this._texture.height < height) { - this.createRepeatingTexture(); - } - } + this._offset = new Phaser.MicroPoint(x, y); + this.scrollSpeed = new Phaser.MicroPoint(speedX, speedY); + this.bounds = new Phaser.Quad(0, 0, width, height); } - ScrollZone.prototype.update = function () { - this._scroll.x = Math.round(this._scroll.x + this.scrollSpeed.x); - this._scroll.y = Math.round(this._scroll.y + this.scrollSpeed.y); - if(this._scroll.x > this._sourceWidth) { - this._scroll.x = 0; + ScrollRegion.prototype.update = function (delta) { + this._scroll.x = Math.round(this._scroll.x + (this.scrollSpeed.x)); + this._scroll.y = Math.round(this._scroll.y + (this.scrollSpeed.y)); + if(this._scroll.x > this._offset.x + this.bounds.width) { + this._scroll.x = this._offset.x; } - if(this._scroll.x < 0) { - this._scroll.x = this._sourceWidth; + if(this._scroll.x < this._offset.x) { + this._scroll.x = this._offset.x + this.bounds.width; } - if(this._scroll.y > this._sourceHeight) { - this._scroll.y = 0; + if(this._scroll.y > this._offset.y + this.bounds.height) { + this._scroll.y = this._offset.y; } - if(this._scroll.y < 0) { - this._scroll.y = this._sourceHeight; + if(this._scroll.y < this._offset.y) { + this._scroll.y = this._offset.y + this.bounds.height; } // Anchor Dimensions - this._anchorWidth = this._sourceWidth - this._scroll.x; - this._anchorHeight = this._sourceHeight - this._scroll.y; - if(this._anchorWidth > this.width) { - this._anchorWidth = this.width; + this._anchorWidth = this.bounds.width - this._scroll.x; + this._anchorHeight = this.bounds.height - this._scroll.y; + if(this._anchorWidth > this.bounds.width) { + this._anchorWidth = this.bounds.width; } - if(this._anchorHeight > this.height) { - this._anchorHeight = this.height; + if(this._anchorHeight > this.bounds.height) { + this._anchorHeight = this.bounds.height; } - this._inverseWidth = this.width - this._anchorWidth; - this._inverseHeight = this.height - this._anchorHeight; + this._inverseWidth = this.bounds.width - this._anchorWidth; + this._inverseHeight = this.bounds.height - this._anchorHeight; // Quad A this._A.setTo(this._scroll.x, this._scroll.y, this._anchorWidth, this._anchorHeight); // Quad B @@ -11635,6 +11652,97 @@ var Phaser; this._D.width = this._inverseWidth; this._D.height = this._inverseHeight; }; + ScrollRegion.prototype.render = function (context, texture, dx, dy, dw, dh) { + if(this.visible == false) { + return; + } + this.crop(context, texture, this._A.x, this._A.y, this._A.width, this._A.height, dx, dy, dw, dh, 0, 0); + this.crop(context, texture, this._B.x, this._B.y, this._B.width, this._B.height, dx, dy, dw, dh, this._A.width, 0); + this.crop(context, texture, this._C.x, this._C.y, this._C.width, this._C.height, dx, dy, dw, dh, 0, this._A.height); + this.crop(context, texture, this._D.x, this._D.y, this._D.width, this._D.height, dx, dy, dw, dh, this._C.width, this._A.height); + }; + ScrollRegion.prototype.crop = function (context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY) { + offsetX += destX; + offsetY += destY; + if(srcW > (destX + destW) - offsetX) { + srcW = (destX + destW) - offsetX; + } + if(srcH > (destY + destH) - offsetY) { + srcH = (destY + destH) - offsetY; + } + if(srcW > 0 && srcH > 0) { + context.drawImage(texture, srcX, srcY, srcW, srcH, offsetX, offsetY, srcW, srcH); + } + }; + return ScrollRegion; + })(); + Phaser.ScrollRegion = ScrollRegion; +})(Phaser || (Phaser = {})); +/// +/// +/// +/** +* Phaser - ScrollZone +* +* Creates a scrolling region of the given width and height from an image in the cache. +* The ScrollZone can be positioned anywhere in-world like a normal game object, re-act to physics, collision, etc. +* The image within it is scrolled via ScrollRegions and their scrollSpeed.x/y properties. +* If you create a scroll zone larger than the given source image it will create a DynamicTexture and fill it with a pattern of the source image. +*/ +var Phaser; +(function (Phaser) { + var ScrollZone = (function (_super) { + __extends(ScrollZone, _super); + function ScrollZone(game, key, x, y, width, height) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof width === "undefined") { width = 0; } + if (typeof height === "undefined") { height = 0; } + _super.call(this, game, x, y, width, height); + this._dynamicTexture = null; + // local rendering related temp vars to help avoid gc spikes + this._dx = 0; + this._dy = 0; + this._dw = 0; + this._dh = 0; + this.flipped = false; + this.regions = []; + if(this._game.cache.getImage(key)) { + this._texture = this._game.cache.getImage(key); + this.width = this._texture.width; + this.height = this._texture.height; + if(width > this._texture.width || height > this._texture.height) { + // Create our repeating texture (as the source image wasn't large enough for the requested size) + this.createRepeatingTexture(width, height); + this.width = width; + this.height = height; + } + // Create a default ScrollRegion at the requested size + this.addRegion(0, 0, this.width, this.height); + // If the zone is smaller than the image itself then shrink the bounds + if((width < this._texture.width || height < this._texture.height) && width !== 0 && height !== 0) { + this.width = width; + this.height = height; + } + } + } + ScrollZone.prototype.addRegion = function (x, y, width, height, speedX, speedY) { + if (typeof speedX === "undefined") { speedX = 0; } + if (typeof speedY === "undefined") { speedY = 0; } + this.currentRegion = new Phaser.ScrollRegion(x, y, width, height, speedX, speedY); + this.regions.push(this.currentRegion); + return this.currentRegion; + }; + ScrollZone.prototype.setSpeed = function (x, y) { + if(this.currentRegion) { + this.currentRegion.scrollSpeed.setTo(x, y); + } + }; + ScrollZone.prototype.update = function () { + for(var i = 0; i < this.regions.length; i++) { + this.regions[i].update(this._game.time.delta); + } + }; ScrollZone.prototype.inCamera = function (camera) { if(this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) { this._dx = this.bounds.x - (camera.x * this.scrollFactor.x); @@ -11656,8 +11764,8 @@ var Phaser; var globalAlpha = this._game.stage.context.globalAlpha; this._game.stage.context.globalAlpha = this.alpha; } - this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x) + this.offset.x; - this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y) + this.offset.y; + this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x); + this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y); this._dw = this.bounds.width * this.scale.x; this._dh = this.bounds.height * this.scale.y; // Apply camera difference @@ -11680,31 +11788,13 @@ var Phaser; } this._dx = Math.round(this._dx); this._dy = Math.round(this._dy); - if(this._dynamicTexture) { - if(this._A.width !== 0 && this._A.height !== 0) { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._A.x, this._A.y, this._A.width, this._A.height, this._dx, this._dy, this._A.width, this._A.height); - } - if(this._B.width !== 0 && this._B.height !== 0) { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._B.x, this._B.y, this._B.width, this._B.height, this._dx + this._A.width, this._dy, this._B.width, this._B.height); - } - if(this._C.width !== 0 && this._C.height !== 0) { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._C.x, this._C.y, this._C.width, this._C.height, this._dx, this._dy + this._A.height, this._C.width, this._C.height); - } - if(this._D.width !== 0 && this._D.height !== 0) { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._D.x, this._D.y, this._D.width, this._D.height, this._dx + this._C.width, this._dy + this._A.height, this._D.width, this._D.height); - } - } else { - if(this._A.width !== 0 && this._A.height !== 0) { - this._game.stage.context.drawImage(this._texture, this._A.x, this._A.y, this._A.width, this._A.height, this._dx, this._dy, this._A.width, this._A.height); - } - if(this._B.width !== 0 && this._B.height !== 0) { - this._game.stage.context.drawImage(this._texture, this._B.x, this._B.y, this._B.width, this._B.height, this._dx + this._A.width, this._dy, this._B.width, this._B.height); - } - if(this._C.width !== 0 && this._C.height !== 0) { - this._game.stage.context.drawImage(this._texture, this._C.x, this._C.y, this._C.width, this._C.height, this._dx, this._dy + this._A.height, this._C.width, this._C.height); - } - if(this._D.width !== 0 && this._D.height !== 0) { - this._game.stage.context.drawImage(this._texture, this._D.x, this._D.y, this._D.width, this._D.height, this._dx + this._C.width, this._dy + this._A.height, this._D.width, this._D.height); + this._dw = Math.round(this._dw); + this._dh = Math.round(this._dh); + for(var i = 0; i < this.regions.length; i++) { + if(this._dynamicTexture) { + this.regions[i].render(this._game.stage.context, this._dynamicTexture.canvas, this._dx, this._dy, this._dw, this._dh); + } else { + this.regions[i].render(this._game.stage.context, this._texture, this._dx, this._dy, this._dw, this._dh); } } if(globalAlpha > -1) { @@ -11712,16 +11802,14 @@ var Phaser; } return true; }; - ScrollZone.prototype.createRepeatingTexture = function () { + ScrollZone.prototype.createRepeatingTexture = function (regionWidth, regionHeight) { // Work out how many we'll need of the source image to make it tile properly - var tileWidth = Math.ceil(this.width / this._sourceWidth) * this._sourceWidth; - var tileHeight = Math.ceil(this.height / this._sourceHeight) * this._sourceHeight; + var tileWidth = Math.ceil(this._texture.width / regionWidth) * regionWidth; + var tileHeight = Math.ceil(this._texture.height / regionHeight) * regionHeight; this._dynamicTexture = new Phaser.DynamicTexture(this._game, tileWidth, tileHeight); this._dynamicTexture.context.rect(0, 0, tileWidth, tileHeight); this._dynamicTexture.context.fillStyle = this._dynamicTexture.context.createPattern(this._texture, "repeat"); this._dynamicTexture.context.fill(); - this._sourceWidth = tileWidth; - this._sourceHeight = tileHeight; }; return ScrollZone; })(Phaser.GameObject); @@ -11834,6 +11922,10 @@ var Phaser; return this.game.world.createEmitter(x, y, size); }; State.prototype.createScrollZone = function (key, x, y, width, height) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof width === "undefined") { width = 0; } + if (typeof height === "undefined") { height = 0; } return this.game.world.createScrollZone(key, x, y, width, height); }; State.prototype.createTilemap = function (key, mapData, format, resizeWorld, tileWidth, tileHeight) { diff --git a/Tests/scrollzones/ballscroller.js b/Tests/scrollzones/ballscroller.js index 815fe3cc..ed51e4ed 100644 --- a/Tests/scrollzones/ballscroller.js +++ b/Tests/scrollzones/ballscroller.js @@ -8,15 +8,18 @@ } var scroller; function create() { - // This creates a ScrollZone the size of the game window - // However the source image (balls.png) is only 102x17 so it will automatically create a fill pattern - scroller = myGame.createScrollZone('balls', 0, 0, 800, 600); + // The source image (balls.png) is only 102x17 in size, but we want it to create a scroll the size of the whole game window. + // We can take advantage of the way a ScrollZone can create a seamless pattern for us automatically. + // If you create a ScrollRegion larger than the source texture, it'll create a DynamicTexture and perform a pattern fill on it and use that + // for rendering. + // We've rounded the height up to 612 because in order to have a seamless pattern it needs to be a multiple of 17 (the height of the source image) + scroller = myGame.createScrollZone('balls', 0, 0, 800, 612); // Some sin/cos data for the movement myGame.math.sinCosGenerator(256, 4, 4, 2); } function update() { // Cycle through the wave data and apply it to the scroll speed (causes the circular wave motion) - scroller.scrollSpeed.x = myGame.math.shiftSinTable(); - scroller.scrollSpeed.y = myGame.math.shiftCosTable(); + scroller.currentRegion.scrollSpeed.x = myGame.math.shiftSinTable(); + scroller.currentRegion.scrollSpeed.y = myGame.math.shiftCosTable(); } })(); diff --git a/Tests/scrollzones/ballscroller.ts b/Tests/scrollzones/ballscroller.ts index db3bcd57..73808cb7 100644 --- a/Tests/scrollzones/ballscroller.ts +++ b/Tests/scrollzones/ballscroller.ts @@ -17,9 +17,13 @@ function create() { - // This creates a ScrollZone the size of the game window - // However the source image (balls.png) is only 102x17 so it will automatically create a fill pattern - scroller = myGame.createScrollZone('balls', 0, 0, 800, 600); + // The source image (balls.png) is only 102x17 in size, but we want it to create a scroll the size of the whole game window. + // We can take advantage of the way a ScrollZone can create a seamless pattern for us automatically. + // If you create a ScrollRegion larger than the source texture, it'll create a DynamicTexture and perform a pattern fill on it and use that + // for rendering. + + // We've rounded the height up to 612 because in order to have a seamless pattern it needs to be a multiple of 17 (the height of the source image) + scroller = myGame.createScrollZone('balls', 0, 0, 800, 612); // Some sin/cos data for the movement myGame.math.sinCosGenerator(256, 4, 4, 2); @@ -29,8 +33,8 @@ function update() { // Cycle through the wave data and apply it to the scroll speed (causes the circular wave motion) - scroller.scrollSpeed.x = myGame.math.shiftSinTable(); - scroller.scrollSpeed.y = myGame.math.shiftCosTable(); + scroller.currentRegion.scrollSpeed.x = myGame.math.shiftSinTable(); + scroller.currentRegion.scrollSpeed.y = myGame.math.shiftCosTable(); } diff --git a/Tests/scrollzones/parallax.js b/Tests/scrollzones/parallax.js index 5d9f075f..07862c27 100644 --- a/Tests/scrollzones/parallax.js +++ b/Tests/scrollzones/parallax.js @@ -8,14 +8,13 @@ } function create() { // In this example we're creating a whole bunch of ScrollZones working on the same image + var zone = myGame.createScrollZone('starray'); var y = 10; var speed = 6; speed -= 0.3; // The image consists of 10px high scrolling layers, this creates them quickly (top = fastest, getting slower as we move down) for(var z = 0; z < 31; z++) { - var zone = myGame.createScrollZone('starray', 0, y, 640, 10); - zone.scrollSpeed.setTo(speed, 0); - zone.offset.y = y; + zone.addRegion(0, y, 640, 10, speed); if(z <= 14) { speed -= 0.3; } else { diff --git a/Tests/scrollzones/parallax.ts b/Tests/scrollzones/parallax.ts index 34493c4d..2b3760f6 100644 --- a/Tests/scrollzones/parallax.ts +++ b/Tests/scrollzones/parallax.ts @@ -16,6 +16,7 @@ function create() { // In this example we're creating a whole bunch of ScrollZones working on the same image + var zone: Phaser.ScrollZone = myGame.createScrollZone('starray'); var y:number = 10; var speed:number = 6; @@ -25,9 +26,7 @@ // The image consists of 10px high scrolling layers, this creates them quickly (top = fastest, getting slower as we move down) for (var z:number = 0; z < 31; z++) { - var zone:Phaser.ScrollZone = myGame.createScrollZone('starray', 0, y, 640, 10); - zone.scrollSpeed.setTo(speed, 0); - zone.offset.y = y; + zone.addRegion(0, y, 640, 10, speed); if (z <= 14) { diff --git a/Tests/scrollzones/scroll window.js b/Tests/scrollzones/scroll window.js new file mode 100644 index 00000000..d39d799a --- /dev/null +++ b/Tests/scrollzones/scroll window.js @@ -0,0 +1,18 @@ +/// +/// +(function () { + var myGame = new Phaser.Game(this, 'game', 800, 600, init, create); + function init() { + myGame.loader.addImageFile('dragonsun', 'assets/pics/cougar_dragonsun.png'); + myGame.loader.addImageFile('overlay', 'assets/pics/scrollframe.png'); + myGame.loader.load(); + } + var scroller; + function create() { + // This creates our ScrollZone. It is positioned at x32 y32 (world coodinates) + // and is a size of 352x240 (which matches the window in our overlay image) + scroller = myGame.createScrollZone('dragonsun', 32, 32, 352, 240); + scroller.setSpeed(2, 2); + myGame.createSprite(0, 0, 'overlay'); + } +})(); diff --git a/Tests/scrollzones/scroll window.ts b/Tests/scrollzones/scroll window.ts new file mode 100644 index 00000000..c87a4718 --- /dev/null +++ b/Tests/scrollzones/scroll window.ts @@ -0,0 +1,31 @@ +/// +/// + +(function () { + + var myGame = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + + myGame.loader.addImageFile('dragonsun', 'assets/pics/cougar_dragonsun.png'); + myGame.loader.addImageFile('overlay', 'assets/pics/scrollframe.png'); + + myGame.loader.load(); + + } + + var scroller: Phaser.ScrollZone; + + function create() { + + // This creates our ScrollZone. It is positioned at x32 y32 (world coodinates) + // and is a size of 352x240 (which matches the window in our overlay image) + scroller = myGame.createScrollZone('dragonsun', 32, 32, 352, 240); + + scroller.setSpeed(2, 2); + + myGame.createSprite(0, 0, 'overlay'); + + } + +})(); diff --git a/Tests/scrollzones/simple scrollzone.js b/Tests/scrollzones/simple scrollzone.js index 8a4ac447..25530df9 100644 --- a/Tests/scrollzones/simple scrollzone.js +++ b/Tests/scrollzones/simple scrollzone.js @@ -3,18 +3,14 @@ (function () { var myGame = new Phaser.Game(this, 'game', 800, 600, init, create); function init() { - myGame.loader.addImageFile('dragonsun', 'assets/pics/cougar_dragonsun.png'); - myGame.loader.addImageFile('overlay', 'assets/pics/scrollframe.png'); + myGame.loader.addImageFile('crystal', 'assets/pics/jim_sachs_time_crystal.png'); myGame.loader.load(); } - var scroller; function create() { - // This creates our ScrollZone. It is positioned at x32 y32 (world coodinates) - // and is a size of 352x240 (which matches the window in our overlay image) - scroller = myGame.createScrollZone('dragonsun', 32, 32, 352, 240); - // The speed of the scroll movement - scroller.scrollSpeed.x = 4; - scroller.scrollSpeed.y = 2; - myGame.createSprite(0, 0, 'overlay'); + // This creates our ScrollZone. It is positioned at x0 y0 (world coodinates) by default and uses + // the 'crystal' image from the cache. + // The default is for the scroll zone to create 1 new scrolling region the size of the whole image you gave it. + // For this example we'll keep that, but look at the other tests to see reasons why you may not want to. + myGame.createScrollZone('crystal').setSpeed(4, 2); } })(); diff --git a/Tests/scrollzones/simple scrollzone.ts b/Tests/scrollzones/simple scrollzone.ts index a56853c0..9d6ebea8 100644 --- a/Tests/scrollzones/simple scrollzone.ts +++ b/Tests/scrollzones/simple scrollzone.ts @@ -7,26 +7,21 @@ function init() { - myGame.loader.addImageFile('dragonsun', 'assets/pics/cougar_dragonsun.png'); - myGame.loader.addImageFile('overlay', 'assets/pics/scrollframe.png'); + myGame.loader.addImageFile('crystal', 'assets/pics/jim_sachs_time_crystal.png'); myGame.loader.load(); } - var scroller: Phaser.ScrollZone; - function create() { - // This creates our ScrollZone. It is positioned at x32 y32 (world coodinates) - // and is a size of 352x240 (which matches the window in our overlay image) - scroller = myGame.createScrollZone('dragonsun', 32, 32, 352, 240); + // This creates our ScrollZone. It is positioned at x0 y0 (world coodinates) by default and uses + // the 'crystal' image from the cache. - // The speed of the scroll movement - scroller.scrollSpeed.x = 4; - scroller.scrollSpeed.y = 2; + // The default is for the scroll zone to create 1 new scrolling region the size of the whole image you gave it. + // For this example we'll keep that, but look at the other tests to see reasons why you may not want to. - myGame.createSprite(0, 0, 'overlay'); + myGame.createScrollZone('crystal').setSpeed(4, 2); } diff --git a/Tests/scrollzones/texture repeat.js b/Tests/scrollzones/texture repeat.js index 24093834..dbd9a790 100644 --- a/Tests/scrollzones/texture repeat.js +++ b/Tests/scrollzones/texture repeat.js @@ -3,19 +3,19 @@ (function () { var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update); function init() { - myGame.loader.addImageFile('balls', 'assets/misc/starfield.jpg'); + myGame.loader.addImageFile('starfield', 'assets/misc/starfield.jpg'); myGame.loader.load(); } var scroller; var ship; function create() { - // This creates a ScrollZone the size of the game window - // The texture will repeat automatically - scroller = myGame.createScrollZone('balls', 0, 0, 800, 600); + // 512 x 512 + scroller = myGame.createScrollZone('starfield', 0, 0, 1024, 512); + // Some sin/cos data for the movement + myGame.math.sinCosGenerator(256, 4, 4, 2); } function update() { - // Cycle through the wave data and apply it to the scroll speed (causes the circular wave motion) - scroller.scrollSpeed.x = myGame.math.shiftSinTable(); - scroller.scrollSpeed.y = myGame.math.shiftCosTable(); + scroller.currentRegion.scrollSpeed.x = myGame.math.shiftSinTable(); + scroller.currentRegion.scrollSpeed.y = myGame.math.shiftCosTable(); } })(); diff --git a/Tests/scrollzones/texture repeat.ts b/Tests/scrollzones/texture repeat.ts index 431c10d1..94572196 100644 --- a/Tests/scrollzones/texture repeat.ts +++ b/Tests/scrollzones/texture repeat.ts @@ -7,7 +7,7 @@ function init() { - myGame.loader.addImageFile('balls', 'assets/misc/starfield.jpg'); + myGame.loader.addImageFile('starfield', 'assets/misc/starfield.jpg'); myGame.loader.load(); @@ -18,18 +18,18 @@ function create() { - // This creates a ScrollZone the size of the game window - // The texture will repeat automatically - scroller = myGame.createScrollZone('balls', 0, 0, 800, 600); + // 512 x 512 + scroller = myGame.createScrollZone('starfield', 0, 0, 1024, 512); + // Some sin/cos data for the movement + myGame.math.sinCosGenerator(256, 4, 4, 2); } function update() { - // Cycle through the wave data and apply it to the scroll speed (causes the circular wave motion) - scroller.scrollSpeed.x = myGame.math.shiftSinTable(); - scroller.scrollSpeed.y = myGame.math.shiftCosTable(); + scroller.currentRegion.scrollSpeed.x = myGame.math.shiftSinTable(); + scroller.currentRegion.scrollSpeed.y = myGame.math.shiftCosTable(); } diff --git a/Tests/sprites/mark of the bunny.js b/Tests/sprites/mark of the bunny.js index bfdd68a0..452419f0 100644 --- a/Tests/sprites/mark of the bunny.js +++ b/Tests/sprites/mark of the bunny.js @@ -27,7 +27,6 @@ var tempSprite = myGame.createSprite(myGame.stage.randomX, 0, 'bunny'); tempSprite.velocity.x = -200 + (Math.random() * 400); tempSprite.velocity.y = 100 + Math.random() * 200; - myGame.world.addExistingSprite(tempSprite); } } function update() { diff --git a/Tests/sprites/mark of the bunny.ts b/Tests/sprites/mark of the bunny.ts index 718c2450..3baa9ae3 100644 --- a/Tests/sprites/mark of the bunny.ts +++ b/Tests/sprites/mark of the bunny.ts @@ -42,8 +42,6 @@ var tempSprite = myGame.createSprite(myGame.stage.randomX, 0, 'bunny'); tempSprite.velocity.x = -200 + (Math.random() * 400); tempSprite.velocity.y = 100 + Math.random() * 200; - - myGame.world.addExistingSprite(tempSprite); } } diff --git a/build/phaser.js b/build/phaser.js index 8f70d6d9..150af5fe 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -8522,12 +8522,8 @@ var Phaser; enumerable: true, configurable: true }); - World.prototype.addExistingCamera = // Cameras - function (cam) { - //return this._cameras.addCamera(x, y, width, height); - return cam; - }; - World.prototype.createCamera = function (x, y, width, height) { + World.prototype.createCamera = // Cameras + function (x, y, width, height) { return this._cameras.addCamera(x, y, width, height); }; World.prototype.removeCamera = function (id) { @@ -8536,12 +8532,8 @@ var Phaser; World.prototype.getAllCameras = function () { return this._cameras.getAll(); }; - World.prototype.addExistingSprite = // Game Objects - // Drop this? - function (sprite) { - return this.group.add(sprite); - }; - World.prototype.createSprite = function (x, y, key) { + World.prototype.createSprite = // Game Objects + function (x, y, key) { if (typeof key === "undefined") { key = ''; } return this.group.add(new Phaser.Sprite(this._game, x, y, key)); }; @@ -8556,6 +8548,10 @@ var Phaser; return this.group.add(new Phaser.Group(this._game, MaxSize)); }; World.prototype.createScrollZone = function (key, x, y, width, height) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof width === "undefined") { width = 0; } + if (typeof height === "undefined") { height = 0; } return this.group.add(new Phaser.ScrollZone(this._game, key, x, y, width, height)); }; World.prototype.createTilemap = function (key, mapData, format, resizeWorld, tileWidth, tileHeight) { @@ -11477,6 +11473,10 @@ var Phaser; return this.world.createEmitter(x, y, size); }; Game.prototype.createScrollZone = function (key, x, y, width, height) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof width === "undefined") { width = 0; } + if (typeof height === "undefined") { height = 0; } return this.world.createScrollZone(key, x, y, width, height); }; Game.prototype.createTilemap = function (key, mapData, format, resizeWorld, tileWidth, tileHeight) { @@ -11541,6 +11541,46 @@ var Phaser; this.height = height; return this; }; + Object.defineProperty(Quad.prototype, "left", { + get: function () { + return this.x; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Quad.prototype, "right", { + get: function () { + return this.x + this.width; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Quad.prototype, "top", { + get: function () { + return this.y; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Quad.prototype, "bottom", { + get: function () { + return this.y + this.height; + }, + enumerable: true, + configurable: true + }); + Quad.prototype.intersects = /** + * Determines whether the object specified intersects (overlaps) with this Quad object. + * This method checks the x, y, width, and height properties of the specified Quad object to see if it intersects with this Quad object. + * @method intersects + * @param {Quad} q The Quad to compare against to see if it intersects with this Quad. + * @param {Number} t A tolerance value to allow for an intersection test with padding, default to 0 + * @return {Boolean} A value of true if the specified object intersects with this Quad; otherwise false. + **/ + function (q, t) { + if (typeof t === "undefined") { t = 0; } + return !(q.left > this.right + t || q.right < this.left - t || q.top > this.bottom + t || q.bottom < this.top - t); + }; return Quad; })(); Phaser.Quad = Quad; @@ -11548,79 +11588,56 @@ var Phaser; /// /// /** -* Phaser - ScrollZone +* Phaser - ScrollRegion * -* Creates a scrolling region of the given width and height from an image in the cache. -* The ScrollZone can be positioned anywhere in-world like a normal game object. -* The image within it is scrolled via the scrollSpeed.x/y properties. -* If you create a scroll zone larger than the given source image it will create a DynamicTexture and fill it with a pattern of the source image. +* Creates a scrolling region within a ScrollZone. +* It is scrolled via the scrollSpeed.x/y properties. */ var Phaser; (function (Phaser) { - var ScrollZone = (function (_super) { - __extends(ScrollZone, _super); - /** - * - */ - function ScrollZone(game, key, x, y, width, height) { - _super.call(this, game, x, y, width, height); - this._dynamicTexture = null; - // local rendering related temp vars to help avoid gc spikes - this._dx = 0; - this._dy = 0; - this._dw = 0; - this._dh = 0; + var ScrollRegion = (function () { + function ScrollRegion(x, y, width, height, speedX, speedY) { this._anchorWidth = 0; this._anchorHeight = 0; this._inverseWidth = 0; this._inverseHeight = 0; - this.flipped = false; + this.visible = true; // Our seamless scrolling quads this._A = new Phaser.Quad(0, 0, width, height); this._B = new Phaser.Quad(); this._C = new Phaser.Quad(); this._D = new Phaser.Quad(); this._scroll = new Phaser.MicroPoint(); - this.offset = new Phaser.MicroPoint(); - this.scrollSpeed = new Phaser.MicroPoint(); - if(this._game.cache.getImage(key)) { - this._texture = this._game.cache.getImage(key); - this.bounds.width = width; - this.bounds.height = height; - this._sourceWidth = this._texture.width; - this._sourceHeight = this._texture.height; - // If the Scrolling Zone is BIGGER than the texture we need to create a repeating pattern DynamicTexture - if(this._texture.width < width || this._texture.height < height) { - this.createRepeatingTexture(); - } - } + this._offset = new Phaser.MicroPoint(x, y); + this.scrollSpeed = new Phaser.MicroPoint(speedX, speedY); + this.bounds = new Phaser.Quad(0, 0, width, height); } - ScrollZone.prototype.update = function () { - this._scroll.x = Math.round(this._scroll.x + this.scrollSpeed.x); - this._scroll.y = Math.round(this._scroll.y + this.scrollSpeed.y); - if(this._scroll.x > this._sourceWidth) { - this._scroll.x = 0; + ScrollRegion.prototype.update = function (delta) { + this._scroll.x = Math.round(this._scroll.x + (this.scrollSpeed.x)); + this._scroll.y = Math.round(this._scroll.y + (this.scrollSpeed.y)); + if(this._scroll.x > this._offset.x + this.bounds.width) { + this._scroll.x = this._offset.x; } - if(this._scroll.x < 0) { - this._scroll.x = this._sourceWidth; + if(this._scroll.x < this._offset.x) { + this._scroll.x = this._offset.x + this.bounds.width; } - if(this._scroll.y > this._sourceHeight) { - this._scroll.y = 0; + if(this._scroll.y > this._offset.y + this.bounds.height) { + this._scroll.y = this._offset.y; } - if(this._scroll.y < 0) { - this._scroll.y = this._sourceHeight; + if(this._scroll.y < this._offset.y) { + this._scroll.y = this._offset.y + this.bounds.height; } // Anchor Dimensions - this._anchorWidth = this._sourceWidth - this._scroll.x; - this._anchorHeight = this._sourceHeight - this._scroll.y; - if(this._anchorWidth > this.width) { - this._anchorWidth = this.width; + this._anchorWidth = this.bounds.width - this._scroll.x; + this._anchorHeight = this.bounds.height - this._scroll.y; + if(this._anchorWidth > this.bounds.width) { + this._anchorWidth = this.bounds.width; } - if(this._anchorHeight > this.height) { - this._anchorHeight = this.height; + if(this._anchorHeight > this.bounds.height) { + this._anchorHeight = this.bounds.height; } - this._inverseWidth = this.width - this._anchorWidth; - this._inverseHeight = this.height - this._anchorHeight; + this._inverseWidth = this.bounds.width - this._anchorWidth; + this._inverseHeight = this.bounds.height - this._anchorHeight; // Quad A this._A.setTo(this._scroll.x, this._scroll.y, this._anchorWidth, this._anchorHeight); // Quad B @@ -11635,6 +11652,97 @@ var Phaser; this._D.width = this._inverseWidth; this._D.height = this._inverseHeight; }; + ScrollRegion.prototype.render = function (context, texture, dx, dy, dw, dh) { + if(this.visible == false) { + return; + } + this.crop(context, texture, this._A.x, this._A.y, this._A.width, this._A.height, dx, dy, dw, dh, 0, 0); + this.crop(context, texture, this._B.x, this._B.y, this._B.width, this._B.height, dx, dy, dw, dh, this._A.width, 0); + this.crop(context, texture, this._C.x, this._C.y, this._C.width, this._C.height, dx, dy, dw, dh, 0, this._A.height); + this.crop(context, texture, this._D.x, this._D.y, this._D.width, this._D.height, dx, dy, dw, dh, this._C.width, this._A.height); + }; + ScrollRegion.prototype.crop = function (context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY) { + offsetX += destX; + offsetY += destY; + if(srcW > (destX + destW) - offsetX) { + srcW = (destX + destW) - offsetX; + } + if(srcH > (destY + destH) - offsetY) { + srcH = (destY + destH) - offsetY; + } + if(srcW > 0 && srcH > 0) { + context.drawImage(texture, srcX, srcY, srcW, srcH, offsetX, offsetY, srcW, srcH); + } + }; + return ScrollRegion; + })(); + Phaser.ScrollRegion = ScrollRegion; +})(Phaser || (Phaser = {})); +/// +/// +/// +/** +* Phaser - ScrollZone +* +* Creates a scrolling region of the given width and height from an image in the cache. +* The ScrollZone can be positioned anywhere in-world like a normal game object, re-act to physics, collision, etc. +* The image within it is scrolled via ScrollRegions and their scrollSpeed.x/y properties. +* If you create a scroll zone larger than the given source image it will create a DynamicTexture and fill it with a pattern of the source image. +*/ +var Phaser; +(function (Phaser) { + var ScrollZone = (function (_super) { + __extends(ScrollZone, _super); + function ScrollZone(game, key, x, y, width, height) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof width === "undefined") { width = 0; } + if (typeof height === "undefined") { height = 0; } + _super.call(this, game, x, y, width, height); + this._dynamicTexture = null; + // local rendering related temp vars to help avoid gc spikes + this._dx = 0; + this._dy = 0; + this._dw = 0; + this._dh = 0; + this.flipped = false; + this.regions = []; + if(this._game.cache.getImage(key)) { + this._texture = this._game.cache.getImage(key); + this.width = this._texture.width; + this.height = this._texture.height; + if(width > this._texture.width || height > this._texture.height) { + // Create our repeating texture (as the source image wasn't large enough for the requested size) + this.createRepeatingTexture(width, height); + this.width = width; + this.height = height; + } + // Create a default ScrollRegion at the requested size + this.addRegion(0, 0, this.width, this.height); + // If the zone is smaller than the image itself then shrink the bounds + if((width < this._texture.width || height < this._texture.height) && width !== 0 && height !== 0) { + this.width = width; + this.height = height; + } + } + } + ScrollZone.prototype.addRegion = function (x, y, width, height, speedX, speedY) { + if (typeof speedX === "undefined") { speedX = 0; } + if (typeof speedY === "undefined") { speedY = 0; } + this.currentRegion = new Phaser.ScrollRegion(x, y, width, height, speedX, speedY); + this.regions.push(this.currentRegion); + return this.currentRegion; + }; + ScrollZone.prototype.setSpeed = function (x, y) { + if(this.currentRegion) { + this.currentRegion.scrollSpeed.setTo(x, y); + } + }; + ScrollZone.prototype.update = function () { + for(var i = 0; i < this.regions.length; i++) { + this.regions[i].update(this._game.time.delta); + } + }; ScrollZone.prototype.inCamera = function (camera) { if(this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) { this._dx = this.bounds.x - (camera.x * this.scrollFactor.x); @@ -11656,8 +11764,8 @@ var Phaser; var globalAlpha = this._game.stage.context.globalAlpha; this._game.stage.context.globalAlpha = this.alpha; } - this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x) + this.offset.x; - this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y) + this.offset.y; + this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x); + this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y); this._dw = this.bounds.width * this.scale.x; this._dh = this.bounds.height * this.scale.y; // Apply camera difference @@ -11680,31 +11788,13 @@ var Phaser; } this._dx = Math.round(this._dx); this._dy = Math.round(this._dy); - if(this._dynamicTexture) { - if(this._A.width !== 0 && this._A.height !== 0) { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._A.x, this._A.y, this._A.width, this._A.height, this._dx, this._dy, this._A.width, this._A.height); - } - if(this._B.width !== 0 && this._B.height !== 0) { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._B.x, this._B.y, this._B.width, this._B.height, this._dx + this._A.width, this._dy, this._B.width, this._B.height); - } - if(this._C.width !== 0 && this._C.height !== 0) { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._C.x, this._C.y, this._C.width, this._C.height, this._dx, this._dy + this._A.height, this._C.width, this._C.height); - } - if(this._D.width !== 0 && this._D.height !== 0) { - this._game.stage.context.drawImage(this._dynamicTexture.canvas, this._D.x, this._D.y, this._D.width, this._D.height, this._dx + this._C.width, this._dy + this._A.height, this._D.width, this._D.height); - } - } else { - if(this._A.width !== 0 && this._A.height !== 0) { - this._game.stage.context.drawImage(this._texture, this._A.x, this._A.y, this._A.width, this._A.height, this._dx, this._dy, this._A.width, this._A.height); - } - if(this._B.width !== 0 && this._B.height !== 0) { - this._game.stage.context.drawImage(this._texture, this._B.x, this._B.y, this._B.width, this._B.height, this._dx + this._A.width, this._dy, this._B.width, this._B.height); - } - if(this._C.width !== 0 && this._C.height !== 0) { - this._game.stage.context.drawImage(this._texture, this._C.x, this._C.y, this._C.width, this._C.height, this._dx, this._dy + this._A.height, this._C.width, this._C.height); - } - if(this._D.width !== 0 && this._D.height !== 0) { - this._game.stage.context.drawImage(this._texture, this._D.x, this._D.y, this._D.width, this._D.height, this._dx + this._C.width, this._dy + this._A.height, this._D.width, this._D.height); + this._dw = Math.round(this._dw); + this._dh = Math.round(this._dh); + for(var i = 0; i < this.regions.length; i++) { + if(this._dynamicTexture) { + this.regions[i].render(this._game.stage.context, this._dynamicTexture.canvas, this._dx, this._dy, this._dw, this._dh); + } else { + this.regions[i].render(this._game.stage.context, this._texture, this._dx, this._dy, this._dw, this._dh); } } if(globalAlpha > -1) { @@ -11712,16 +11802,14 @@ var Phaser; } return true; }; - ScrollZone.prototype.createRepeatingTexture = function () { + ScrollZone.prototype.createRepeatingTexture = function (regionWidth, regionHeight) { // Work out how many we'll need of the source image to make it tile properly - var tileWidth = Math.ceil(this.width / this._sourceWidth) * this._sourceWidth; - var tileHeight = Math.ceil(this.height / this._sourceHeight) * this._sourceHeight; + var tileWidth = Math.ceil(this._texture.width / regionWidth) * regionWidth; + var tileHeight = Math.ceil(this._texture.height / regionHeight) * regionHeight; this._dynamicTexture = new Phaser.DynamicTexture(this._game, tileWidth, tileHeight); this._dynamicTexture.context.rect(0, 0, tileWidth, tileHeight); this._dynamicTexture.context.fillStyle = this._dynamicTexture.context.createPattern(this._texture, "repeat"); this._dynamicTexture.context.fill(); - this._sourceWidth = tileWidth; - this._sourceHeight = tileHeight; }; return ScrollZone; })(Phaser.GameObject); @@ -11834,6 +11922,10 @@ var Phaser; return this.game.world.createEmitter(x, y, size); }; State.prototype.createScrollZone = function (key, x, y, width, height) { + if (typeof x === "undefined") { x = 0; } + if (typeof y === "undefined") { y = 0; } + if (typeof width === "undefined") { width = 0; } + if (typeof height === "undefined") { height = 0; } return this.game.world.createScrollZone(key, x, y, width, height); }; State.prototype.createTilemap = function (key, mapData, format, resizeWorld, tileWidth, tileHeight) {