From ce1523585f238c9c0ceba26badedfdbfed13f397 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Thu, 30 May 2013 05:34:35 +0100 Subject: [PATCH] ScrollZone back in under the new renderer with new demos --- Phaser/Phaser.csproj | 2 + Phaser/components/sprite/Physics.ts | 31 +- Phaser/components/sprite/Texture.ts | 32 +- Phaser/gameobjects/GameObjectFactory.ts | 12 +- Phaser/gameobjects/ScrollZone.ts | 176 +-------- Phaser/gameobjects/Sprite.ts | 23 +- Phaser/physics/AABB.ts | 10 +- Phaser/renderers/CanvasRenderer.ts | 116 ++++++ Phaser/renderers/HeadlessRenderer.ts | 12 +- Phaser/renderers/IRenderer.ts | 1 + Tests/Tests.csproj | 24 ++ Tests/phaser.js | 473 +++++++++++++++++++++--- Tests/physics/aabb 1.js | 4 +- Tests/physics/aabb 1.ts | 2 +- Tests/scrollzones/ballscroller.js | 25 ++ Tests/scrollzones/ballscroller.ts | 41 ++ Tests/scrollzones/parallax.js | 31 ++ Tests/scrollzones/parallax.ts | 53 +++ Tests/scrollzones/region demo.js | 22 ++ Tests/scrollzones/region demo.ts | 37 ++ Tests/scrollzones/scroll window.js | 18 + Tests/scrollzones/scroll window.ts | 31 ++ Tests/scrollzones/simple scrollzone.js | 16 + Tests/scrollzones/simple scrollzone.ts | 27 ++ Tests/scrollzones/skewed scroller.js | 27 ++ Tests/scrollzones/skewed scroller.ts | 34 ++ build/phaser.d.ts | 178 ++++++++- build/phaser.js | 473 +++++++++++++++++++++--- 28 files changed, 1582 insertions(+), 349 deletions(-) create mode 100644 Tests/scrollzones/ballscroller.js create mode 100644 Tests/scrollzones/ballscroller.ts create mode 100644 Tests/scrollzones/parallax.js create mode 100644 Tests/scrollzones/parallax.ts create mode 100644 Tests/scrollzones/region demo.js create mode 100644 Tests/scrollzones/region demo.ts create mode 100644 Tests/scrollzones/scroll window.js create mode 100644 Tests/scrollzones/scroll window.ts create mode 100644 Tests/scrollzones/simple scrollzone.js create mode 100644 Tests/scrollzones/simple scrollzone.ts create mode 100644 Tests/scrollzones/skewed scroller.js create mode 100644 Tests/scrollzones/skewed scroller.ts diff --git a/Phaser/Phaser.csproj b/Phaser/Phaser.csproj index 7faf41d8..60c9de63 100644 --- a/Phaser/Phaser.csproj +++ b/Phaser/Phaser.csproj @@ -69,6 +69,7 @@ CameraFX.ts + Texture.ts @@ -93,6 +94,7 @@ IGameObject.ts + GameMath.ts diff --git a/Phaser/components/sprite/Physics.ts b/Phaser/components/sprite/Physics.ts index 9767d463..7379d0ff 100644 --- a/Phaser/components/sprite/Physics.ts +++ b/Phaser/components/sprite/Physics.ts @@ -1,11 +1,10 @@ /// /// +/// /// /** * Phaser - Components - Physics -* -* */ module Phaser.Components { @@ -14,32 +13,24 @@ module Phaser.Components { constructor(parent: Sprite) { - this._game = parent.game; + this.game = parent.game; this._sprite = parent; - // Copy from PhysicsManager? - this.gravity = new Vec2; - this.drag = new Vec2; - this.bounce = new Vec2; - this.friction = new Vec2; + this.gravity = Vec2Utils.clone(this.game.world.physics.gravity); + this.drag = Vec2Utils.clone(this.game.world.physics.drag); + this.bounce = Vec2Utils.clone(this.game.world.physics.bounce); + this.friction = Vec2Utils.clone(this.game.world.physics.friction); + this.velocity = new Vec2; this.acceleration = new Vec2; - //this.AABB = new Phaser.Physics.AABB(this._game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height); - this.shape = this._game.world.physics.add(new Phaser.Physics.AABB(this._game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height)); + this.shape = this.game.world.physics.add(new Phaser.Physics.AABB(this.game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height)); } - /** - * - */ - private _game: Game; - - /** - * - */ private _sprite: Sprite; + public game: Game; public shape: Phaser.Physics.IPhysicsShape; /** @@ -70,10 +61,6 @@ module Phaser.Components { { this._sprite.x = (this.shape.position.x - this.shape.bounds.halfWidth) - this.shape.offset.x; this._sprite.y = (this.shape.position.y - this.shape.bounds.halfHeight) - this.shape.offset.y; - //this._sprite.x = (this.shape.position.x - this.shape.bounds.halfWidth); - //this._sprite.y = (this.shape.position.y - this.shape.bounds.halfHeight); - //this._sprite.x = (this.shape.position.x); - //this._sprite.y = (this.shape.position.y); } } diff --git a/Phaser/components/sprite/Texture.ts b/Phaser/components/sprite/Texture.ts index ff78d5f9..551839b6 100644 --- a/Phaser/components/sprite/Texture.ts +++ b/Phaser/components/sprite/Texture.ts @@ -44,13 +44,13 @@ module Phaser.Components { /** * Reference to the Image stored in the Game.Cache that is used as the texture for the Sprite. */ - private _imageTexture = null; + public imageTexture = null; /** * Reference to the DynamicTexture that is used as the texture for the Sprite. * @type {DynamicTexture} */ - private _dynamicTexture: DynamicTexture = null; + public dynamicTexture: DynamicTexture = null; /** * The status of the texture image. @@ -105,6 +105,12 @@ module Phaser.Components { */ public flippedY: bool = false; + /** + * Is the texture a DynamicTexture? + * @type {boolean} + */ + public isDynamic: bool = false; + /** * Updates the texture being used to render the Sprite. * Called automatically by SpriteUtils.loadTexture and SpriteUtils.loadDynamicTexture. @@ -113,13 +119,15 @@ module Phaser.Components { if (dynamic) { - this._dynamicTexture = dynamic; - this.texture = this._dynamicTexture.canvas; + this.isDynamic = true; + this.dynamicTexture = dynamic; + this.texture = this.dynamicTexture.canvas; } else { - this._imageTexture = image; - this.texture = this._imageTexture; + this.isDynamic = false; + this.imageTexture = image; + this.texture = this.imageTexture; } this.loaded = true; @@ -183,13 +191,13 @@ module Phaser.Components { */ public get width(): number { - if (this._dynamicTexture) + if (this.isDynamic) { - return this._dynamicTexture.width; + return this.dynamicTexture.width; } else { - return this._imageTexture.width; + return this.imageTexture.width; } } @@ -199,13 +207,13 @@ module Phaser.Components { */ public get height(): number { - if (this._dynamicTexture) + if (this.isDynamic) { - return this._dynamicTexture.height; + return this.dynamicTexture.height; } else { - return this._imageTexture.height; + return this.imageTexture.height; } } diff --git a/Phaser/gameobjects/GameObjectFactory.ts b/Phaser/gameobjects/GameObjectFactory.ts index 75024640..a20ca2c4 100644 --- a/Phaser/gameobjects/GameObjectFactory.ts +++ b/Phaser/gameobjects/GameObjectFactory.ts @@ -134,9 +134,9 @@ module Phaser { * @param height {number} Height of this object. * @returns {ScrollZone} The newly created scroll zone object. */ - //public scrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone { - // return this._world.group.add(new ScrollZone(this._game, key, x, y, width, height)); - //} + public scrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone { + return this._world.group.add(new ScrollZone(this._game, key, x, y, width, height)); + } /** * Create a new Tilemap. @@ -203,9 +203,9 @@ module Phaser { * @param scrollZone The ScrollZone to add to the Game World * @return {Phaser.ScrollZone} The ScrollZone object */ - //public existingScrollZone(scrollZone: ScrollZone): ScrollZone { - // return this._world.group.add(scrollZone); - //} + public existingScrollZone(scrollZone: ScrollZone): ScrollZone { + return this._world.group.add(scrollZone); + } /** * Add an existing Tilemap to the current world. diff --git a/Phaser/gameobjects/ScrollZone.ts b/Phaser/gameobjects/ScrollZone.ts index 8252e871..4c84e350 100644 --- a/Phaser/gameobjects/ScrollZone.ts +++ b/Phaser/gameobjects/ScrollZone.ts @@ -28,17 +28,17 @@ module Phaser { */ constructor(game: Game, key:string, x: number = 0, y: number = 0, width?: number = 0, height?: number = 0) { - super(game, x, y, width, height); + super(game, x, y, key, width, height); + + this.type = Phaser.Types.SCROLLZONE; + this.render = game.renderer.renderScrollZone; + this.physics.moves = false; this.regions = []; - if (this._game.cache.getImage(key)) + if (this.texture.loaded) { - 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) + if (width > this.width || height > this.height) { // Create our repeating texture (as the source image wasn't large enough for the requested size) this.createRepeatingTexture(width, height); @@ -50,7 +50,7 @@ module Phaser { 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) + if ((width < this.width || height < this.height) && width !== 0 && height !== 0) { this.width = width; this.height = height; @@ -60,41 +60,6 @@ module Phaser { } - /** - * Texture of this object. - */ - private _texture; - - /** - * If this zone is larger than texture image, this will be filled with a pattern of texture. - * @type {DynamicTexture} - */ - private _dynamicTexture: DynamicTexture = null; - - /** - * Local rendering related temp vars to help avoid gc spikes. - * @type {number} - */ - private _dx: number = 0; - - /** - * Local rendering related temp vars to help avoid gc spikes. - * @type {number} - */ - private _dy: number = 0; - - /** - * Local rendering related temp vars to help avoid gc spikes. - * @type {number} - */ - private _dw: number = 0; - - /** - * Local rendering related temp vars to help avoid gc spikes. - * @type {number} - */ - private _dh: number = 0; - /** * Current region this zone is scrolling. * @type {ScrollRegion} @@ -107,12 +72,6 @@ module Phaser { */ public regions: ScrollRegion[]; - /** - * Flip this zone vertically? (default to false) - * @type {boolean} - */ - public flipped: bool = false; - /** * Add a new region to this zone. * @param x {number} X position of the new region. @@ -162,114 +121,11 @@ module Phaser { for (var i = 0; i < this.regions.length; i++) { - this.regions[i].update(this._game.time.delta); + this.regions[i].update(this.game.time.delta); } } - /** - * Check whether this zone is visible in a specific camera rectangle. - * @param camera {Rectangle} The rectangle you want to check. - * @return {boolean} Return true if bound of this zone intersects the given rectangle, otherwise return false. - */ - public inCamera(camera: Rectangle): bool { - - if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) - { - this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x); - this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x); - this._dw = this.frameBounds.width * this.scale.x; - this._dh = this.frameBounds.height * this.scale.y; - - return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh); - } - else - { - return camera.intersects(this.frameBounds, this.frameBounds.length); - } - - } - - /** - * Render this zone object to a specific camera. - * @param camera {Camera} The camera this object will be render to. - * @param cameraOffsetX {number} X offset of camera. - * @param cameraOffsetY {number} Y offset of camera. - * @return Return false if not rendered, otherwise return true. - */ - public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) { - - // Render checks - if (this.visible == false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1 || this.cameraBlacklist.indexOf(camera.ID) !== -1 || this.inCamera(camera.worldView) == false) - { - return false; - } - - // Alpha - if (this.alpha !== 1) - { - var globalAlpha = this.context.globalAlpha; - this.context.globalAlpha = this.alpha; - } - - this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x); - this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y); - this._dw = this.frameBounds.width * this.scale.x; - this._dh = this.frameBounds.height * this.scale.y; - - // Apply camera difference - if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) - { - this._dx -= (camera.worldView.x * this.scrollFactor.x); - this._dy -= (camera.worldView.y * this.scrollFactor.y); - } - - // Rotation - needs to work from origin point really, but for now from center - if (this.angle !== 0 || this.flipped == true) - { - this.context.save(); - this.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2)); - - if (this.angle !== 0) - { - this.context.rotate(this.angle * (Math.PI / 180)); - } - - this._dx = -(this._dw / 2); - this._dy = -(this._dh / 2); - - if (this.flipped == true) - { - this.context.scale(-1, 1); - } - } - - this._dx = Math.round(this._dx); - this._dy = Math.round(this._dy); - 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.context, this._dynamicTexture.canvas, this._dx, this._dy, this._dw, this._dh); - } - else - { - this.regions[i].render(this.context, this._texture, this._dx, this._dy, this._dw, this._dh); - } - } - - if (globalAlpha > -1) - { - this.context.globalAlpha = globalAlpha; - } - - return true; - - } - /** * Create repeating texture with _texture, and store it into the _dynamicTexture. * Used to create texture when texture image is small than size of the zone. @@ -277,14 +133,16 @@ module Phaser { 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._texture.width / regionWidth) * regionWidth; - var tileHeight = Math.ceil(this._texture.height / regionHeight) * regionHeight; + var tileWidth = Math.ceil(this.width / regionWidth) * regionWidth; + var tileHeight = Math.ceil(this.height / regionHeight) * regionHeight; - this._dynamicTexture = new DynamicTexture(this._game, tileWidth, tileHeight); + var dt: DynamicTexture = new 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(); + dt.context.rect(0, 0, tileWidth, tileHeight); + dt.context.fillStyle = dt.context.createPattern(this.texture.imageTexture, "repeat"); + dt.context.fill(); + + this.texture.loadDynamicTexture(dt); } diff --git a/Phaser/gameobjects/Sprite.ts b/Phaser/gameobjects/Sprite.ts index dcaf4754..9e5aca88 100644 --- a/Phaser/gameobjects/Sprite.ts +++ b/Phaser/gameobjects/Sprite.ts @@ -45,9 +45,6 @@ module Phaser { this.animations = new Phaser.Components.AnimationManager(this); this.texture = new Phaser.Components.Texture(this, key); - this.width = this.frameBounds.width; - this.height = this.frameBounds.height; - // Transform related (if we add any more then move to a component) this.origin = new Phaser.Vec2(0, 0); this.scale = new Phaser.Vec2(1, 1); @@ -99,10 +96,6 @@ module Phaser { */ public alive: bool; - // Getters only, don't over-write these values - public width: number; - public height: number; - /** * Sprite physics. */ @@ -217,6 +210,22 @@ module Phaser { return this.animations.frameName; } + public set width(value: number) { + this.frameBounds.width = value; + } + + public get width(): number { + return this.frameBounds.width; + } + + public set height(value: number) { + this.frameBounds.height = value; + } + + public get height(): number { + return this.frameBounds.height; + } + /** * Pre-update is called right before update() on each object in the game loop. */ diff --git a/Phaser/physics/AABB.ts b/Phaser/physics/AABB.ts index a49ce5f9..ad5ec9ce 100644 --- a/Phaser/physics/AABB.ts +++ b/Phaser/physics/AABB.ts @@ -29,7 +29,6 @@ module Phaser.Physics { this.scale = new Vec2(1, 1); } - //this.bounds = new Rectangle(x + Math.round(width / 2), y + Math.round(height / 2), width, height); this.bounds = new Rectangle(x + Math.round(width / 2), y + Math.round(height / 2), width, height); this.position = new Vec2(x + this.bounds.halfWidth, y + this.bounds.halfHeight); this.oldPosition = new Vec2(x + this.bounds.halfWidth, y + this.bounds.halfHeight); @@ -57,16 +56,11 @@ module Phaser.Physics { if (this.sprite) { - // Update position to sprite value - //console.log('a', this.position.x, this.position.y); this.position.setTo((this.sprite.x + this.bounds.halfWidth) + this.offset.x, (this.sprite.y + this.bounds.halfHeight) + this.offset.y); - //console.log('b', this.position.x, this.position.y); - //this.position.setTo(this.sprite.x, this.sprite.y); // Update scale / dimensions if (Vec2Utils.equals(this.scale, this.sprite.scale) == false) { - console.log('scaled'); this.scale.copyFrom(this.sprite.scale); this.bounds.width = this.sprite.width; this.bounds.height = this.sprite.height; @@ -76,6 +70,10 @@ module Phaser.Physics { } public update() { + + this.bounds.x = this.position.x; + this.bounds.y = this.position.y; + } public setSize(width: number, height: number) { diff --git a/Phaser/renderers/CanvasRenderer.ts b/Phaser/renderers/CanvasRenderer.ts index 4bcc10cd..ee3b824c 100644 --- a/Phaser/renderers/CanvasRenderer.ts +++ b/Phaser/renderers/CanvasRenderer.ts @@ -1,5 +1,6 @@ /// /// +/// /// /// @@ -199,6 +200,121 @@ module Phaser { } + public renderScrollZone(camera: Camera, scrollZone: ScrollZone): bool { + + // Render checks (needs inCamera check added) + if (scrollZone.scale.x == 0 || scrollZone.scale.y == 0 || scrollZone.texture.alpha < 0.1) + { + return false; + } + + // Reset our temp vars + this._ga = -1; + this._sx = 0; + this._sy = 0; + this._sw = scrollZone.frameBounds.width; + this._sh = scrollZone.frameBounds.height; + this._fx = scrollZone.scale.x; + this._fy = scrollZone.scale.y; + this._sin = 0; + this._cos = 1; + this._dx = (camera.scaledX * scrollZone.scrollFactor.x) + scrollZone.frameBounds.x - (camera.worldView.x * scrollZone.scrollFactor.x); + this._dy = (camera.scaledY * scrollZone.scrollFactor.y) + scrollZone.frameBounds.y - (camera.worldView.y * scrollZone.scrollFactor.y); + this._dw = scrollZone.frameBounds.width; + this._dh = scrollZone.frameBounds.height; + + // Alpha + if (scrollZone.texture.alpha !== 1) + { + this._ga = scrollZone.texture.context.globalAlpha; + scrollZone.texture.context.globalAlpha = scrollZone.texture.alpha; + } + + // Sprite Flip X + if (scrollZone.texture.flippedX) + { + this._fx = -scrollZone.scale.x; + } + + // Sprite Flip Y + if (scrollZone.texture.flippedY) + { + this._fy = -scrollZone.scale.y; + } + + // Rotation and Flipped + if (scrollZone.modified) + { + if (scrollZone.texture.renderRotation == true && (scrollZone.rotation !== 0 || scrollZone.rotationOffset !== 0)) + { + this._sin = Math.sin(scrollZone.game.math.degreesToRadians(scrollZone.rotationOffset + scrollZone.rotation)); + this._cos = Math.cos(scrollZone.game.math.degreesToRadians(scrollZone.rotationOffset + scrollZone.rotation)); + } + + // setTransform(a, b, c, d, e, f); + // a = scale x + // b = skew x + // c = skew y + // d = scale y + // e = translate x + // f = translate y + + scrollZone.texture.context.save(); + scrollZone.texture.context.setTransform(this._cos * this._fx, (this._sin * this._fx) + scrollZone.skew.x, -(this._sin * this._fy) + scrollZone.skew.y, this._cos * this._fy, this._dx, this._dy); + + this._dx = -scrollZone.origin.x; + this._dy = -scrollZone.origin.y; + } + else + { + if (!scrollZone.origin.equals(0)) + { + this._dx -= scrollZone.origin.x; + this._dy -= scrollZone.origin.y; + } + } + + this._sx = Math.round(this._sx); + this._sy = Math.round(this._sy); + this._sw = Math.round(this._sw); + this._sh = Math.round(this._sh); + this._dx = Math.round(this._dx); + this._dy = Math.round(this._dy); + this._dw = Math.round(this._dw); + this._dh = Math.round(this._dh); + + for (var i = 0; i < scrollZone.regions.length; i++) + { + if (scrollZone.texture.isDynamic) + { + scrollZone.regions[i].render(scrollZone.texture.context, scrollZone.texture.texture, this._dx, this._dy, this._dw, this._dh); + } + else + { + scrollZone.regions[i].render(scrollZone.texture.context, scrollZone.texture.texture, this._dx, this._dy, this._dw, this._dh); + } + } + + if (scrollZone.modified) + { + scrollZone.texture.context.restore(); + } + + //if (this.renderDebug) + //{ + // this.renderBounds(camera, cameraOffsetX, cameraOffsetY); + //this.collisionMask.render(camera, cameraOffsetX, cameraOffsetY); + //} + + if (this._ga > -1) + { + scrollZone.texture.context.globalAlpha = this._ga; + } + + return true; + + } + } } \ No newline at end of file diff --git a/Phaser/renderers/HeadlessRenderer.ts b/Phaser/renderers/HeadlessRenderer.ts index 94025908..d6c7ef9d 100644 --- a/Phaser/renderers/HeadlessRenderer.ts +++ b/Phaser/renderers/HeadlessRenderer.ts @@ -18,18 +18,12 @@ module Phaser { public render() {} public renderSprite(camera: Camera, sprite: Sprite): bool { - - // Render checks (needs inCamera check added) - if (sprite.scale.x == 0 || sprite.scale.y == 0 || sprite.texture.alpha < 0.1) - { - return false; - } - return true; - } - // Add Tilemap, ScrollZone, etc? + public renderScrollZone(camera: Camera, scrollZone: ScrollZone): bool { + return true; + } } diff --git a/Phaser/renderers/IRenderer.ts b/Phaser/renderers/IRenderer.ts index af1190cc..b6e60eb6 100644 --- a/Phaser/renderers/IRenderer.ts +++ b/Phaser/renderers/IRenderer.ts @@ -6,6 +6,7 @@ module Phaser { render(); renderSprite(camera: Camera, sprite: Sprite): bool; + renderScrollZone(camera: Camera, sprite: ScrollZone): bool; } diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 01604c17..24d352bf 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -69,6 +69,30 @@ aabb 1.ts + + + + + + + ballscroller.ts + + + parallax.ts + + + region demo.ts + + + scroll window.ts + + + simple scrollzone.ts + + + + skewed scroller.ts + tween loop 1.ts diff --git a/Tests/phaser.js b/Tests/phaser.js index 02f303a2..a8a836c1 100644 --- a/Tests/phaser.js +++ b/Tests/phaser.js @@ -3849,12 +3849,12 @@ var Phaser; /** * Reference to the Image stored in the Game.Cache that is used as the texture for the Sprite. */ - this._imageTexture = null; + this.imageTexture = null; /** * Reference to the DynamicTexture that is used as the texture for the Sprite. * @type {DynamicTexture} */ - this._dynamicTexture = null; + this.dynamicTexture = null; /** * The status of the texture image. * @type {boolean} @@ -3876,6 +3876,11 @@ var Phaser; * @type {boolean} */ this.flippedY = false; + /** + * Is the texture a DynamicTexture? + * @type {boolean} + */ + this.isDynamic = false; this._game = parent.game; this._sprite = parent; this.canvas = parent.game.stage.canvas; @@ -3896,11 +3901,13 @@ var Phaser; if (typeof image === "undefined") { image = null; } if (typeof dynamic === "undefined") { dynamic = null; } if(dynamic) { - this._dynamicTexture = dynamic; - this.texture = this._dynamicTexture.canvas; + this.isDynamic = true; + this.dynamicTexture = dynamic; + this.texture = this.dynamicTexture.canvas; } else { - this._imageTexture = image; - this.texture = this._imageTexture; + this.isDynamic = false; + this.imageTexture = image; + this.texture = this.imageTexture; } this.loaded = true; return this._sprite; @@ -3946,10 +3953,10 @@ var Phaser; * @type {number} */ function () { - if(this._dynamicTexture) { - return this._dynamicTexture.width; + if(this.isDynamic) { + return this.dynamicTexture.width; } else { - return this._imageTexture.width; + return this.imageTexture.width; } }, enumerable: true, @@ -3961,10 +3968,10 @@ var Phaser; * @type {number} */ function () { - if(this._dynamicTexture) { - return this._dynamicTexture.height; + if(this.isDynamic) { + return this.dynamicTexture.height; } else { - return this._imageTexture.height; + return this.imageTexture.height; } }, enumerable: true, @@ -4048,8 +4055,6 @@ var Phaser; ; this.animations = new Phaser.Components.AnimationManager(this); this.texture = new Phaser.Components.Texture(this, key); - this.width = this.frameBounds.width; - this.height = this.frameBounds.height; // Transform related (if we add any more then move to a component) this.origin = new Phaser.Vec2(0, 0); this.scale = new Phaser.Vec2(1, 1); @@ -4106,6 +4111,26 @@ var Phaser; enumerable: true, configurable: true }); + Object.defineProperty(Sprite.prototype, "width", { + get: function () { + return this.frameBounds.width; + }, + set: function (value) { + this.frameBounds.width = value; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Sprite.prototype, "height", { + get: function () { + return this.frameBounds.height; + }, + set: function (value) { + this.frameBounds.height = value; + }, + enumerable: true, + configurable: true + }); Sprite.prototype.preUpdate = /** * Pre-update is called right before update() on each object in the game loop. */ @@ -6045,7 +6070,6 @@ var Phaser; this.physics = null; this.scale = new Phaser.Vec2(1, 1); } - //this.bounds = new Rectangle(x + Math.round(width / 2), y + Math.round(height / 2), width, height); this.bounds = new Phaser.Rectangle(x + Math.round(width / 2), y + Math.round(height / 2), width, height); this.position = new Phaser.Vec2(x + this.bounds.halfWidth, y + this.bounds.halfHeight); this.oldPosition = new Phaser.Vec2(x + this.bounds.halfWidth, y + this.bounds.halfHeight); @@ -6054,14 +6078,9 @@ var Phaser; AABB.prototype.preUpdate = function () { this.oldPosition.copyFrom(this.position); if(this.sprite) { - // Update position to sprite value - //console.log('a', this.position.x, this.position.y); this.position.setTo((this.sprite.x + this.bounds.halfWidth) + this.offset.x, (this.sprite.y + this.bounds.halfHeight) + this.offset.y); - //console.log('b', this.position.x, this.position.y); - //this.position.setTo(this.sprite.x, this.sprite.y); // Update scale / dimensions if(Phaser.Vec2Utils.equals(this.scale, this.sprite.scale) == false) { - console.log('scaled'); this.scale.copyFrom(this.sprite.scale); this.bounds.width = this.sprite.width; this.bounds.height = this.sprite.height; @@ -6069,6 +6088,8 @@ var Phaser; } }; AABB.prototype.update = function () { + this.bounds.x = this.position.x; + this.bounds.y = this.position.y; }; AABB.prototype.setSize = function (width, height) { this.bounds.width = width; @@ -6205,7 +6226,7 @@ var Phaser; function (x, y, width, height) { return this._world.physics.add(new Phaser.Physics.AABB(this._game, null, x, y, width, height)); }; - GameObjectFactory.prototype.tween = /** + GameObjectFactory.prototype.scrollZone = /** * Create a new Particle. * * @return {Particle} The newly created particle object. @@ -6234,10 +6255,14 @@ var Phaser; * @param height {number} Height of this object. * @returns {ScrollZone} The newly created scroll zone object. */ - //public scrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone { - // return this._world.group.add(new ScrollZone(this._game, key, x, y, width, height)); - //} - /** + 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.group.add(new Phaser.ScrollZone(this._game, key, x, y, width, height)); + }; + GameObjectFactory.prototype.tween = /** * Create a new Tilemap. * * @param key {string} Key for tileset image. @@ -6270,7 +6295,7 @@ var Phaser; function (sprite) { return this._world.group.add(sprite); }; - GameObjectFactory.prototype.existingTween = /** + GameObjectFactory.prototype.existingScrollZone = /** * Add an existing GeomSprite to the current world. * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break. * @@ -6297,10 +6322,10 @@ var Phaser; * @param scrollZone The ScrollZone to add to the Game World * @return {Phaser.ScrollZone} The ScrollZone object */ - //public existingScrollZone(scrollZone: ScrollZone): ScrollZone { - // return this._world.group.add(scrollZone); - //} - /** + function (scrollZone) { + return this._world.group.add(scrollZone); + }; + GameObjectFactory.prototype.existingTween = /** * Add an existing Tilemap to the current world. * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break. * @@ -10881,19 +10906,284 @@ var Phaser; HeadlessRenderer.prototype.render = function () { }; HeadlessRenderer.prototype.renderSprite = function (camera, sprite) { - // Render checks (needs inCamera check added) - if(sprite.scale.x == 0 || sprite.scale.y == 0 || sprite.texture.alpha < 0.1) { - return false; - } + return true; + }; + HeadlessRenderer.prototype.renderScrollZone = function (camera, scrollZone) { return true; }; return HeadlessRenderer; })(); Phaser.HeadlessRenderer = HeadlessRenderer; - // Add Tilemap, ScrollZone, etc? - })(Phaser || (Phaser = {})); +})(Phaser || (Phaser = {})); +/// +/// +/// +/** +* Phaser - ScrollRegion +* +* Creates a scrolling region within a ScrollZone. +* It is scrolled via the scrollSpeed.x/y properties. +*/ +var Phaser; +(function (Phaser) { + var ScrollRegion = (function () { + /** + * ScrollRegion constructor + * Create a new ScrollRegion. + * + * @param x {number} X position in world coordinate. + * @param y {number} Y position in world coordinate. + * @param width {number} Width of this object. + * @param height {number} Height of this object. + * @param speedX {number} X-axis scrolling speed. + * @param speedY {number} Y-axis scrolling speed. + */ + function ScrollRegion(x, y, width, height, speedX, speedY) { + this._anchorWidth = 0; + this._anchorHeight = 0; + this._inverseWidth = 0; + this._inverseHeight = 0; + /** + * Will this region be rendered? (default to true) + * @type {boolean} + */ + this.visible = true; + // Our seamless scrolling quads + this._A = new Phaser.Rectangle(x, y, width, height); + this._B = new Phaser.Rectangle(x, y, width, height); + this._C = new Phaser.Rectangle(x, y, width, height); + this._D = new Phaser.Rectangle(x, y, width, height); + this._scroll = new Phaser.Vec2(); + this._bounds = new Phaser.Rectangle(x, y, width, height); + this.scrollSpeed = new Phaser.Vec2(speedX, speedY); + } + ScrollRegion.prototype.update = /** + * Update region scrolling with tick time. + * @param delta {number} Elapsed time since last update. + */ + function (delta) { + this._scroll.x += this.scrollSpeed.x; + this._scroll.y += this.scrollSpeed.y; + if(this._scroll.x > this._bounds.right) { + this._scroll.x = this._bounds.x; + } + if(this._scroll.x < this._bounds.x) { + this._scroll.x = this._bounds.right; + } + if(this._scroll.y > this._bounds.bottom) { + this._scroll.y = this._bounds.y; + } + if(this._scroll.y < this._bounds.y) { + this._scroll.y = this._bounds.bottom; + } + // Anchor Dimensions + this._anchorWidth = (this._bounds.width - this._scroll.x) + this._bounds.x; + this._anchorHeight = (this._bounds.height - this._scroll.y) + this._bounds.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; + // Rectangle A + this._A.setTo(this._scroll.x, this._scroll.y, this._anchorWidth, this._anchorHeight); + // Rectangle B + this._B.y = this._scroll.y; + this._B.width = this._inverseWidth; + this._B.height = this._anchorHeight; + // Rectangle C + this._C.x = this._scroll.x; + this._C.width = this._anchorWidth; + this._C.height = this._inverseHeight; + // Rectangle D + this._D.width = this._inverseWidth; + this._D.height = this._inverseHeight; + }; + ScrollRegion.prototype.render = /** + * Render this region to specific context. + * @param context {CanvasRenderingContext2D} Canvas context this region will be rendered to. + * @param texture {object} The texture to be rendered. + * @param dx {number} X position in world coordinate. + * @param dy {number} Y position in world coordinate. + * @param width {number} Width of this region to be rendered. + * @param height {number} Height of this region to be rendered. + */ + function (context, texture, dx, dy, dw, dh) { + if(this.visible == false) { + return; + } + // dx/dy are the world coordinates to render the FULL ScrollZone into. + // This ScrollRegion may be smaller than that and offset from the dx/dy coordinates. + 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); + //context.fillStyle = 'rgb(255,255,255)'; + //context.font = '18px Arial'; + //context.fillText('RectangleA: ' + this._A.toString(), 32, 450); + //context.fillText('RectangleB: ' + this._B.toString(), 32, 480); + //context.fillText('RectangleC: ' + this._C.toString(), 32, 510); + //context.fillText('RectangleD: ' + this._D.toString(), 32, 540); + }; + ScrollRegion.prototype.crop = /** + * Crop part of the texture and render it to the given context. + * @param context {CanvasRenderingContext2D} Canvas context the texture will be rendered to. + * @param texture {object} Texture to be rendered. + * @param srcX {number} Target region top-left x coordinate in the texture. + * @param srcX {number} Target region top-left y coordinate in the texture. + * @param srcW {number} Target region width in the texture. + * @param srcH {number} Target region height in the texture. + * @param destX {number} Render region top-left x coordinate in the context. + * @param destX {number} Render region top-left y coordinate in the context. + * @param destW {number} Target region width in the context. + * @param destH {number} Target region height in the context. + * @param offsetX {number} X offset to the context. + * @param offsetY {number} Y offset to the context. + */ + 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; + } + srcX = Math.floor(srcX); + srcY = Math.floor(srcY); + srcW = Math.floor(srcW); + srcH = Math.floor(srcH); + offsetX = Math.floor(offsetX + this._bounds.x); + offsetY = Math.floor(offsetY + this._bounds.y); + if(srcW > 0 && srcH > 0) { + context.drawImage(texture, srcX, srcY, srcW, srcH, offsetX, offsetY, srcW, srcH); + } + }; + return ScrollRegion; + })(); + Phaser.ScrollRegion = ScrollRegion; +})(Phaser || (Phaser = {})); +var __extends = this.__extends || function (d, b) { + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +/// +/// +/// +/** +* 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); + /** + * ScrollZone constructor + * Create a new ScrollZone. + * + * @param game {Phaser.Game} Current game instance. + * @param key {string} Asset key for image texture of this object. + * @param x {number} X position in world coordinate. + * @param y {number} Y position in world coordinate. + * @param [width] {number} width of this object. + * @param [height] {number} height of this object. + */ + 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, key, width, height); + this.type = Phaser.Types.SCROLLZONE; + this.render = game.renderer.renderScrollZone; + this.physics.moves = false; + this.regions = []; + if(this.texture.loaded) { + if(width > this.width || height > this.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.width || height < this.height) && width !== 0 && height !== 0) { + this.width = width; + this.height = height; + } + } + } + ScrollZone.prototype.addRegion = /** + * Add a new region to this zone. + * @param x {number} X position of the new region. + * @param y {number} Y position of the new region. + * @param width {number} Width of the new region. + * @param height {number} Height of the new region. + * @param [speedX] {number} x-axis scrolling speed. + * @param [speedY] {number} y-axis scrolling speed. + * @return {ScrollRegion} The newly added region. + */ + function (x, y, width, height, speedX, speedY) { + if (typeof speedX === "undefined") { speedX = 0; } + if (typeof speedY === "undefined") { speedY = 0; } + if(x > this.width || y > this.height || x < 0 || y < 0 || (x + width) > this.width || (y + height) > this.height) { + throw Error('Invalid ScrollRegion defined. Cannot be larger than parent ScrollZone'); + return; + } + this.currentRegion = new Phaser.ScrollRegion(x, y, width, height, speedX, speedY); + this.regions.push(this.currentRegion); + return this.currentRegion; + }; + ScrollZone.prototype.setSpeed = /** + * Set scrolling speed of current region. + * @param x {number} X speed of current region. + * @param y {number} Y speed of current region. + */ + function (x, y) { + if(this.currentRegion) { + this.currentRegion.scrollSpeed.setTo(x, y); + } + return this; + }; + ScrollZone.prototype.update = /** + * Update regions. + */ + function () { + for(var i = 0; i < this.regions.length; i++) { + this.regions[i].update(this.game.time.delta); + } + }; + ScrollZone.prototype.createRepeatingTexture = /** + * Create repeating texture with _texture, and store it into the _dynamicTexture. + * Used to create texture when texture image is small than size of the zone. + */ + function (regionWidth, regionHeight) { + console.log('create repeat'); + // Work out how many we'll need of the source image to make it tile properly + var tileWidth = Math.ceil(this.width / regionWidth) * regionWidth; + var tileHeight = Math.ceil(this.height / regionHeight) * regionHeight; + var dt = new Phaser.DynamicTexture(this.game, tileWidth, tileHeight); + dt.context.rect(0, 0, tileWidth, tileHeight); + dt.context.fillStyle = dt.context.createPattern(this.texture.imageTexture, "repeat"); + dt.context.fill(); + this.texture.loadDynamicTexture(dt); + }; + return ScrollZone; + })(Phaser.Sprite); + Phaser.ScrollZone = ScrollZone; +})(Phaser || (Phaser = {})); /// /// +/// /// /// var Phaser; @@ -11034,6 +11324,89 @@ var Phaser; } return true; }; + CanvasRenderer.prototype.renderScrollZone = function (camera, scrollZone) { + // Render checks (needs inCamera check added) + if(scrollZone.scale.x == 0 || scrollZone.scale.y == 0 || scrollZone.texture.alpha < 0.1) { + return false; + } + // Reset our temp vars + this._ga = -1; + this._sx = 0; + this._sy = 0; + this._sw = scrollZone.frameBounds.width; + this._sh = scrollZone.frameBounds.height; + this._fx = scrollZone.scale.x; + this._fy = scrollZone.scale.y; + this._sin = 0; + this._cos = 1; + this._dx = (camera.scaledX * scrollZone.scrollFactor.x) + scrollZone.frameBounds.x - (camera.worldView.x * scrollZone.scrollFactor.x); + this._dy = (camera.scaledY * scrollZone.scrollFactor.y) + scrollZone.frameBounds.y - (camera.worldView.y * scrollZone.scrollFactor.y); + this._dw = scrollZone.frameBounds.width; + this._dh = scrollZone.frameBounds.height; + // Alpha + if(scrollZone.texture.alpha !== 1) { + this._ga = scrollZone.texture.context.globalAlpha; + scrollZone.texture.context.globalAlpha = scrollZone.texture.alpha; + } + // Sprite Flip X + if(scrollZone.texture.flippedX) { + this._fx = -scrollZone.scale.x; + } + // Sprite Flip Y + if(scrollZone.texture.flippedY) { + this._fy = -scrollZone.scale.y; + } + // Rotation and Flipped + if(scrollZone.modified) { + if(scrollZone.texture.renderRotation == true && (scrollZone.rotation !== 0 || scrollZone.rotationOffset !== 0)) { + this._sin = Math.sin(scrollZone.game.math.degreesToRadians(scrollZone.rotationOffset + scrollZone.rotation)); + this._cos = Math.cos(scrollZone.game.math.degreesToRadians(scrollZone.rotationOffset + scrollZone.rotation)); + } + // setTransform(a, b, c, d, e, f); + // a = scale x + // b = skew x + // c = skew y + // d = scale y + // e = translate x + // f = translate y + scrollZone.texture.context.save(); + scrollZone.texture.context.setTransform(this._cos * this._fx, (this._sin * this._fx) + scrollZone.skew.x, -(this._sin * this._fy) + scrollZone.skew.y, this._cos * this._fy, this._dx, this._dy); + this._dx = -scrollZone.origin.x; + this._dy = -scrollZone.origin.y; + } else { + if(!scrollZone.origin.equals(0)) { + this._dx -= scrollZone.origin.x; + this._dy -= scrollZone.origin.y; + } + } + this._sx = Math.round(this._sx); + this._sy = Math.round(this._sy); + this._sw = Math.round(this._sw); + this._sh = Math.round(this._sh); + this._dx = Math.round(this._dx); + this._dy = Math.round(this._dy); + this._dw = Math.round(this._dw); + this._dh = Math.round(this._dh); + for(var i = 0; i < scrollZone.regions.length; i++) { + if(scrollZone.texture.isDynamic) { + scrollZone.regions[i].render(scrollZone.texture.context, scrollZone.texture.texture, this._dx, this._dy, this._dw, this._dh); + } else { + scrollZone.regions[i].render(scrollZone.texture.context, scrollZone.texture.texture, this._dx, this._dy, this._dw, this._dh); + } + } + if(scrollZone.modified) { + scrollZone.texture.context.restore(); + } + //if (this.renderDebug) + //{ + // this.renderBounds(camera, cameraOffsetX, cameraOffsetY); + //this.collisionMask.render(camera, cameraOffsetX, cameraOffsetY); + //} + if(this._ga > -1) { + scrollZone.texture.context.globalAlpha = this._ga; + } + return true; + }; return CanvasRenderer; })(); Phaser.CanvasRenderer = CanvasRenderer; @@ -11685,11 +12058,10 @@ var Phaser; (function (Phaser) { /// /// + /// /// /** * Phaser - Components - Physics - * - * */ (function (Components) { var Physics = (function () { @@ -11699,17 +12071,15 @@ var Phaser; * @type {boolean} */ this.moves = true; - this._game = parent.game; + this.game = parent.game; this._sprite = parent; - // Copy from PhysicsManager? - this.gravity = new Phaser.Vec2(); - this.drag = new Phaser.Vec2(); - this.bounce = new Phaser.Vec2(); - this.friction = new Phaser.Vec2(); + this.gravity = Phaser.Vec2Utils.clone(this.game.world.physics.gravity); + this.drag = Phaser.Vec2Utils.clone(this.game.world.physics.drag); + this.bounce = Phaser.Vec2Utils.clone(this.game.world.physics.bounce); + this.friction = Phaser.Vec2Utils.clone(this.game.world.physics.friction); this.velocity = new Phaser.Vec2(); this.acceleration = new Phaser.Vec2(); - //this.AABB = new Phaser.Physics.AABB(this._game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height); - this.shape = this._game.world.physics.add(new Phaser.Physics.AABB(this._game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height)); + this.shape = this.game.world.physics.add(new Phaser.Physics.AABB(this.game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height)); } Physics.prototype.update = /** * Internal function for updating the position and speed of this object. @@ -11718,11 +12088,7 @@ var Phaser; if(this.moves) { this._sprite.x = (this.shape.position.x - this.shape.bounds.halfWidth) - this.shape.offset.x; this._sprite.y = (this.shape.position.y - this.shape.bounds.halfHeight) - this.shape.offset.y; - //this._sprite.x = (this.shape.position.x - this.shape.bounds.halfWidth); - //this._sprite.y = (this.shape.position.y - this.shape.bounds.halfHeight); - //this._sprite.x = (this.shape.position.x); - //this._sprite.y = (this.shape.position.y); - } + } }; Physics.prototype.renderDebugInfo = /** * Render debug infos. (including name, bounds info, position and some other properties) @@ -11896,11 +12262,6 @@ var Phaser; })(); Phaser.LinkedList = LinkedList; })(Phaser || (Phaser = {})); -var __extends = this.__extends || function (d, b) { - function __() { this.constructor = d; } - __.prototype = b.prototype; - d.prototype = new __(); -}; /// /// /// diff --git a/Tests/physics/aabb 1.js b/Tests/physics/aabb 1.js index 41b4b4be..bd9375c5 100644 --- a/Tests/physics/aabb 1.js +++ b/Tests/physics/aabb 1.js @@ -10,9 +10,9 @@ function create() { atari = game.add.sprite(200, 300, 'atari'); atari.texture.alpha = 0.5; - //atari.scale.setTo(2, 2); + //atari.scale.setTo(1.5, 1.5); atari.physics.shape.setSize(150, 50); - atari.physics.shape.offset.setTo(250, 25); + atari.physics.shape.offset.setTo(50, 25); //atari.physics.gravity.setTo(0, 2); atari.physics.bounce.setTo(0.7, 0.7); atari.physics.drag.setTo(10, 10); diff --git a/Tests/physics/aabb 1.ts b/Tests/physics/aabb 1.ts index 280b5452..ac8392cd 100644 --- a/Tests/physics/aabb 1.ts +++ b/Tests/physics/aabb 1.ts @@ -18,7 +18,7 @@ atari = game.add.sprite(200, 300, 'atari'); atari.texture.alpha = 0.5; - //atari.scale.setTo(2, 2); + //atari.scale.setTo(1.5, 1.5); atari.physics.shape.setSize(150, 50); atari.physics.shape.offset.setTo(50, 25); diff --git a/Tests/scrollzones/ballscroller.js b/Tests/scrollzones/ballscroller.js new file mode 100644 index 00000000..aa38432f --- /dev/null +++ b/Tests/scrollzones/ballscroller.js @@ -0,0 +1,25 @@ +/// +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + function init() { + game.loader.addImageFile('balls', 'assets/sprites/balls.png'); + game.loader.load(); + } + var scroller; + function create() { + // 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 = game.add.scrollZone('balls', 0, 0, 800, 612); + // Some sin/cos data for the movement + game.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.currentRegion.scrollSpeed.x = game.math.shiftSinTable(); + scroller.currentRegion.scrollSpeed.y = game.math.shiftCosTable(); + } +})(); diff --git a/Tests/scrollzones/ballscroller.ts b/Tests/scrollzones/ballscroller.ts new file mode 100644 index 00000000..705fcfd5 --- /dev/null +++ b/Tests/scrollzones/ballscroller.ts @@ -0,0 +1,41 @@ +/// +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + + function init() { + + game.loader.addImageFile('balls', 'assets/sprites/balls.png'); + + game.loader.load(); + + } + + var scroller: Phaser.ScrollZone; + + function create() { + + // 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 = game.add.scrollZone('balls', 0, 0, 800, 612); + + // Some sin/cos data for the movement + game.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.currentRegion.scrollSpeed.x = game.math.shiftSinTable(); + scroller.currentRegion.scrollSpeed.y = game.math.shiftCosTable(); + + } + +})(); diff --git a/Tests/scrollzones/parallax.js b/Tests/scrollzones/parallax.js new file mode 100644 index 00000000..35287e5a --- /dev/null +++ b/Tests/scrollzones/parallax.js @@ -0,0 +1,31 @@ +/// +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + function init() { + game.loader.addImageFile('starray', 'assets/pics/auto_scroll_landscape.png'); + game.loader.load(); + } + function create() { + var zone = game.add.scrollZone('starray'); + // Hide the default region (the full image) + zone.currentRegion.visible = false; + var y = 0; + var speed = 16; + // 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 < 32; z++) { + zone.addRegion(0, y, 640, 10, speed); + if(z <= 15) { + speed -= 1; + } else { + speed += 1; + } + if(z == 15) { + y = 240; + speed += 1; + } else { + y += 10; + } + } + } +})(); diff --git a/Tests/scrollzones/parallax.ts b/Tests/scrollzones/parallax.ts new file mode 100644 index 00000000..c91b15d8 --- /dev/null +++ b/Tests/scrollzones/parallax.ts @@ -0,0 +1,53 @@ +/// +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + + game.loader.addImageFile('starray', 'assets/pics/auto_scroll_landscape.png'); + + game.loader.load(); + + } + + function create() { + + var zone: Phaser.ScrollZone = game.add.scrollZone('starray'); + + // Hide the default region (the full image) + zone.currentRegion.visible = false; + + var y:number = 0; + var speed:number = 16; + + // 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 < 32; z++) + { + zone.addRegion(0, y, 640, 10, speed); + + if (z <= 15) + { + speed -= 1; + } + else + { + speed += 1; + } + + if (z == 15) + { + y = 240; + speed += 1; + } + else + { + y += 10; + } + } + + } + +})(); diff --git a/Tests/scrollzones/region demo.js b/Tests/scrollzones/region demo.js new file mode 100644 index 00000000..86f86e7f --- /dev/null +++ b/Tests/scrollzones/region demo.js @@ -0,0 +1,22 @@ +/// +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + function init() { + game.loader.addImageFile('angelDawn', 'assets/pics/game14_angel_dawn.png'); + game.loader.load(); + } + var scroller; + function create() { + // This creates our ScrollZone centered in the middle of the stage. + scroller = game.add.scrollZone('angelDawn', game.stage.centerX - 320, 100); + // By default we won't scroll the full image, but we will create 3 ScrollRegions within it: + // This creates a ScrollRegion which can be thought of as a rectangle within the ScrollZone that can be scrolled + // independantly - this one scrolls the image of the spacemans head + scroller.addRegion(32, 32, 352, 240, 0, 2); + // The head in the top right + scroller.addRegion(480, 30, 96, 96, 4, 0); + // The small piece of text + scroller.addRegion(466, 160, 122, 14, 0, -0.5); + } +})(); diff --git a/Tests/scrollzones/region demo.ts b/Tests/scrollzones/region demo.ts new file mode 100644 index 00000000..21fac8e3 --- /dev/null +++ b/Tests/scrollzones/region demo.ts @@ -0,0 +1,37 @@ +/// +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + + game.loader.addImageFile('angelDawn', 'assets/pics/game14_angel_dawn.png'); + + game.loader.load(); + + } + + var scroller: Phaser.ScrollZone; + + function create() { + + // This creates our ScrollZone centered in the middle of the stage. + scroller = game.add.scrollZone('angelDawn', game.stage.centerX - 320, 100); + + // By default we won't scroll the full image, but we will create 3 ScrollRegions within it: + + // This creates a ScrollRegion which can be thought of as a rectangle within the ScrollZone that can be scrolled + // independantly - this one scrolls the image of the spacemans head + scroller.addRegion(32, 32, 352, 240, 0, 2); + + // The head in the top right + scroller.addRegion(480, 30, 96, 96, 4, 0); + + // The small piece of text + scroller.addRegion(466, 160, 122, 14, 0, -0.5); + + } + +})(); diff --git a/Tests/scrollzones/scroll window.js b/Tests/scrollzones/scroll window.js new file mode 100644 index 00000000..c106b8c6 --- /dev/null +++ b/Tests/scrollzones/scroll window.js @@ -0,0 +1,18 @@ +/// +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + function init() { + game.loader.addImageFile('dragonsun', 'assets/pics/cougar_dragonsun.png'); + game.loader.addImageFile('overlay', 'assets/pics/scrollframe.png'); + game.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 = game.add.scrollZone('dragonsun', 32, 32, 352, 240); + scroller.setSpeed(2, 2); + game.add.sprite(0, 0, 'overlay'); + } +})(); diff --git a/Tests/scrollzones/scroll window.ts b/Tests/scrollzones/scroll window.ts new file mode 100644 index 00000000..dcf8b968 --- /dev/null +++ b/Tests/scrollzones/scroll window.ts @@ -0,0 +1,31 @@ +/// +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + + game.loader.addImageFile('dragonsun', 'assets/pics/cougar_dragonsun.png'); + game.loader.addImageFile('overlay', 'assets/pics/scrollframe.png'); + + game.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 = game.add.scrollZone('dragonsun', 32, 32, 352, 240); + + scroller.setSpeed(2, 2); + + game.add.sprite(0, 0, 'overlay'); + + } + +})(); diff --git a/Tests/scrollzones/simple scrollzone.js b/Tests/scrollzones/simple scrollzone.js new file mode 100644 index 00000000..9f23bd2c --- /dev/null +++ b/Tests/scrollzones/simple scrollzone.js @@ -0,0 +1,16 @@ +/// +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + function init() { + game.loader.addImageFile('crystal', 'assets/pics/jim_sachs_time_crystal.png'); + game.loader.load(); + } + function create() { + // 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. + game.add.scrollZone('crystal').setSpeed(4, 2); + } +})(); diff --git a/Tests/scrollzones/simple scrollzone.ts b/Tests/scrollzones/simple scrollzone.ts new file mode 100644 index 00000000..16d445d5 --- /dev/null +++ b/Tests/scrollzones/simple scrollzone.ts @@ -0,0 +1,27 @@ +/// +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + + game.loader.addImageFile('crystal', 'assets/pics/jim_sachs_time_crystal.png'); + game.loader.load(); + + } + + function create() { + + // 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. + + game.add.scrollZone('crystal').setSpeed(4, 2); + + } + +})(); diff --git a/Tests/scrollzones/skewed scroller.js b/Tests/scrollzones/skewed scroller.js new file mode 100644 index 00000000..87d12c89 --- /dev/null +++ b/Tests/scrollzones/skewed scroller.js @@ -0,0 +1,27 @@ +/// +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + function init() { + game.loader.addImageFile('balls', 'assets/sprites/balls.png'); + game.loader.load(); + } + var leftFace; + var rightFace; + var topFace; + function create() { + topFace = game.add.scrollZone('balls', 200, 0, 204, 204).setSpeed(0, 2.2); + topFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(-30)))// 0,-30 + scale(1,1.16) + ; + topFace.scale.setTo(1, 1.3); + leftFace = game.add.scrollZone('balls', 110, 264, 204, 204).setSpeed(0, 2.1); + leftFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(30)))// 0,30deg + ; + rightFace = game.add.scrollZone('balls', 200, 466, 204, 204).setSpeed(0, 2); + rightFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(-30)))// 0,-30 + scale(1,1.16) + ; + rightFace.scale.setTo(1, 0.8); + //var a = Math.tan(game.math.radiansToDegrees(-180)) + //game.add.tween(rightFace.skew).to({ x: 2, y: 4 }, 4000, Phaser.Easing.Linear.None, true, 0, true); + } +})(); diff --git a/Tests/scrollzones/skewed scroller.ts b/Tests/scrollzones/skewed scroller.ts new file mode 100644 index 00000000..66d37734 --- /dev/null +++ b/Tests/scrollzones/skewed scroller.ts @@ -0,0 +1,34 @@ +/// +/// + +(function () { + + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + + game.loader.addImageFile('balls', 'assets/sprites/balls.png'); + game.loader.load(); + + } + + var leftFace: Phaser.ScrollZone; + var rightFace: Phaser.ScrollZone; + var topFace: Phaser.ScrollZone; + + function create() { + + topFace = game.add.scrollZone('balls', 200, 0, 204, 204).setSpeed(0, 2.2); + topFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(-30))); + topFace.scale.setTo(1, 1.3); + + leftFace = game.add.scrollZone('balls', 110, 264, 204, 204).setSpeed(0, 2.1); + leftFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(30))); + + rightFace = game.add.scrollZone('balls', 200, 466, 204, 204).setSpeed(0, 2); + rightFace.skew.setTo(0, Math.tan(game.math.radiansToDegrees(-30))); + rightFace.scale.setTo(1, 0.8); + + } + +})(); diff --git a/build/phaser.d.ts b/build/phaser.d.ts index 1b74028d..6efbe513 100644 --- a/build/phaser.d.ts +++ b/build/phaser.d.ts @@ -2169,12 +2169,12 @@ module Phaser.Components { /** * Reference to the Image stored in the Game.Cache that is used as the texture for the Sprite. */ - private _imageTexture; + public imageTexture; /** * Reference to the DynamicTexture that is used as the texture for the Sprite. * @type {DynamicTexture} */ - private _dynamicTexture; + public dynamicTexture: DynamicTexture; /** * The status of the texture image. * @type {boolean} @@ -2220,6 +2220,11 @@ module Phaser.Components { */ public flippedY: bool; /** + * Is the texture a DynamicTexture? + * @type {boolean} + */ + public isDynamic: bool; + /** * Updates the texture being used to render the Sprite. * Called automatically by SpriteUtils.loadTexture and SpriteUtils.loadDynamicTexture. */ @@ -2300,8 +2305,6 @@ module Phaser { * */ public alive: bool; - public width: number; - public height: number; /** * Sprite physics. */ @@ -2382,6 +2385,8 @@ module Phaser { * Set the animation frame by frame name. */ public frameName : string; + public width : number; + public height : number; /** * Pre-update is called right before update() on each object in the game loop. */ @@ -3348,6 +3353,17 @@ module Phaser { */ public physicsAABB(x: number, y: number, width: number, height: number): Physics.AABB; /** + * Create a new ScrollZone object with image key, position and size. + * + * @param key {string} Key to a image you wish this object to use. + * @param x {number} X position of this object. + * @param y {number} Y position of this object. + * @param width number} Width of this object. + * @param height {number} Height of this object. + * @returns {ScrollZone} The newly created scroll zone object. + */ + public scrollZone(key: string, x?: number, y?: number, width?: number, height?: number): ScrollZone; + /** * Create a tween object for a specific object. * * @param obj Object you wish the tween will affect. @@ -3363,6 +3379,14 @@ module Phaser { */ public existingSprite(sprite: Sprite): Sprite; /** + * Add an existing ScrollZone to the current world. + * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break. + * + * @param scrollZone The ScrollZone to add to the Game World + * @return {Phaser.ScrollZone} The ScrollZone object + */ + public existingScrollZone(scrollZone: ScrollZone): ScrollZone; + /** * Add an existing Tween to the current world. * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break. * @@ -6014,6 +6038,7 @@ module Phaser { interface IRenderer { render(); renderSprite(camera: Camera, sprite: Sprite): bool; + renderScrollZone(camera: Camera, sprite: ScrollZone): bool; } } module Phaser { @@ -6025,6 +6050,140 @@ module Phaser { private _game; public render(): void; public renderSprite(camera: Camera, sprite: Sprite): bool; + public renderScrollZone(camera: Camera, scrollZone: ScrollZone): bool; + } +} +/** +* Phaser - ScrollRegion +* +* Creates a scrolling region within a ScrollZone. +* It is scrolled via the scrollSpeed.x/y properties. +*/ +module Phaser { + class ScrollRegion { + /** + * ScrollRegion constructor + * Create a new ScrollRegion. + * + * @param x {number} X position in world coordinate. + * @param y {number} Y position in world coordinate. + * @param width {number} Width of this object. + * @param height {number} Height of this object. + * @param speedX {number} X-axis scrolling speed. + * @param speedY {number} Y-axis scrolling speed. + */ + constructor(x: number, y: number, width: number, height: number, speedX: number, speedY: number); + private _A; + private _B; + private _C; + private _D; + private _bounds; + private _scroll; + private _anchorWidth; + private _anchorHeight; + private _inverseWidth; + private _inverseHeight; + /** + * Will this region be rendered? (default to true) + * @type {boolean} + */ + public visible: bool; + /** + * Region scrolling speed. + * @type {Vec2} + */ + public scrollSpeed: Vec2; + /** + * Update region scrolling with tick time. + * @param delta {number} Elapsed time since last update. + */ + public update(delta: number): void; + /** + * Render this region to specific context. + * @param context {CanvasRenderingContext2D} Canvas context this region will be rendered to. + * @param texture {object} The texture to be rendered. + * @param dx {number} X position in world coordinate. + * @param dy {number} Y position in world coordinate. + * @param width {number} Width of this region to be rendered. + * @param height {number} Height of this region to be rendered. + */ + public render(context: CanvasRenderingContext2D, texture, dx: number, dy: number, dw: number, dh: number): void; + /** + * Crop part of the texture and render it to the given context. + * @param context {CanvasRenderingContext2D} Canvas context the texture will be rendered to. + * @param texture {object} Texture to be rendered. + * @param srcX {number} Target region top-left x coordinate in the texture. + * @param srcX {number} Target region top-left y coordinate in the texture. + * @param srcW {number} Target region width in the texture. + * @param srcH {number} Target region height in the texture. + * @param destX {number} Render region top-left x coordinate in the context. + * @param destX {number} Render region top-left y coordinate in the context. + * @param destW {number} Target region width in the context. + * @param destH {number} Target region height in the context. + * @param offsetX {number} X offset to the context. + * @param offsetY {number} Y offset to the context. + */ + private crop(context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY); + } +} +/** +* 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. +*/ +module Phaser { + class ScrollZone extends Sprite { + /** + * ScrollZone constructor + * Create a new ScrollZone. + * + * @param game {Phaser.Game} Current game instance. + * @param key {string} Asset key for image texture of this object. + * @param x {number} X position in world coordinate. + * @param y {number} Y position in world coordinate. + * @param [width] {number} width of this object. + * @param [height] {number} height of this object. + */ + constructor(game: Game, key: string, x?: number, y?: number, width?: number, height?: number); + /** + * Current region this zone is scrolling. + * @type {ScrollRegion} + */ + public currentRegion: ScrollRegion; + /** + * Array contains all added regions. + * @type {ScrollRegion[]} + */ + public regions: ScrollRegion[]; + /** + * Add a new region to this zone. + * @param x {number} X position of the new region. + * @param y {number} Y position of the new region. + * @param width {number} Width of the new region. + * @param height {number} Height of the new region. + * @param [speedX] {number} x-axis scrolling speed. + * @param [speedY] {number} y-axis scrolling speed. + * @return {ScrollRegion} The newly added region. + */ + public addRegion(x: number, y: number, width: number, height: number, speedX?: number, speedY?: number): ScrollRegion; + /** + * Set scrolling speed of current region. + * @param x {number} X speed of current region. + * @param y {number} Y speed of current region. + */ + public setSpeed(x: number, y: number): ScrollZone; + /** + * Update regions. + */ + public update(): void; + /** + * Create repeating texture with _texture, and store it into the _dynamicTexture. + * Used to create texture when texture image is small than size of the zone. + */ + private createRepeatingTexture(regionWidth, regionHeight); } } module Phaser { @@ -6057,6 +6216,7 @@ module Phaser { * @return {boolean} Return false if not rendered, otherwise return true. */ public renderSprite(camera: Camera, sprite: Sprite): bool; + public renderScrollZone(camera: Camera, scrollZone: ScrollZone): bool; } } /** @@ -6434,20 +6594,12 @@ module Phaser { } /** * Phaser - Components - Physics -* -* */ module Phaser.Components { class Physics { constructor(parent: Sprite); - /** - * - */ - private _game; - /** - * - */ private _sprite; + public game: Game; public shape: Physics.IPhysicsShape; /** * Whether this object will be moved by impacts with other objects or not. diff --git a/build/phaser.js b/build/phaser.js index 02f303a2..a8a836c1 100644 --- a/build/phaser.js +++ b/build/phaser.js @@ -3849,12 +3849,12 @@ var Phaser; /** * Reference to the Image stored in the Game.Cache that is used as the texture for the Sprite. */ - this._imageTexture = null; + this.imageTexture = null; /** * Reference to the DynamicTexture that is used as the texture for the Sprite. * @type {DynamicTexture} */ - this._dynamicTexture = null; + this.dynamicTexture = null; /** * The status of the texture image. * @type {boolean} @@ -3876,6 +3876,11 @@ var Phaser; * @type {boolean} */ this.flippedY = false; + /** + * Is the texture a DynamicTexture? + * @type {boolean} + */ + this.isDynamic = false; this._game = parent.game; this._sprite = parent; this.canvas = parent.game.stage.canvas; @@ -3896,11 +3901,13 @@ var Phaser; if (typeof image === "undefined") { image = null; } if (typeof dynamic === "undefined") { dynamic = null; } if(dynamic) { - this._dynamicTexture = dynamic; - this.texture = this._dynamicTexture.canvas; + this.isDynamic = true; + this.dynamicTexture = dynamic; + this.texture = this.dynamicTexture.canvas; } else { - this._imageTexture = image; - this.texture = this._imageTexture; + this.isDynamic = false; + this.imageTexture = image; + this.texture = this.imageTexture; } this.loaded = true; return this._sprite; @@ -3946,10 +3953,10 @@ var Phaser; * @type {number} */ function () { - if(this._dynamicTexture) { - return this._dynamicTexture.width; + if(this.isDynamic) { + return this.dynamicTexture.width; } else { - return this._imageTexture.width; + return this.imageTexture.width; } }, enumerable: true, @@ -3961,10 +3968,10 @@ var Phaser; * @type {number} */ function () { - if(this._dynamicTexture) { - return this._dynamicTexture.height; + if(this.isDynamic) { + return this.dynamicTexture.height; } else { - return this._imageTexture.height; + return this.imageTexture.height; } }, enumerable: true, @@ -4048,8 +4055,6 @@ var Phaser; ; this.animations = new Phaser.Components.AnimationManager(this); this.texture = new Phaser.Components.Texture(this, key); - this.width = this.frameBounds.width; - this.height = this.frameBounds.height; // Transform related (if we add any more then move to a component) this.origin = new Phaser.Vec2(0, 0); this.scale = new Phaser.Vec2(1, 1); @@ -4106,6 +4111,26 @@ var Phaser; enumerable: true, configurable: true }); + Object.defineProperty(Sprite.prototype, "width", { + get: function () { + return this.frameBounds.width; + }, + set: function (value) { + this.frameBounds.width = value; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Sprite.prototype, "height", { + get: function () { + return this.frameBounds.height; + }, + set: function (value) { + this.frameBounds.height = value; + }, + enumerable: true, + configurable: true + }); Sprite.prototype.preUpdate = /** * Pre-update is called right before update() on each object in the game loop. */ @@ -6045,7 +6070,6 @@ var Phaser; this.physics = null; this.scale = new Phaser.Vec2(1, 1); } - //this.bounds = new Rectangle(x + Math.round(width / 2), y + Math.round(height / 2), width, height); this.bounds = new Phaser.Rectangle(x + Math.round(width / 2), y + Math.round(height / 2), width, height); this.position = new Phaser.Vec2(x + this.bounds.halfWidth, y + this.bounds.halfHeight); this.oldPosition = new Phaser.Vec2(x + this.bounds.halfWidth, y + this.bounds.halfHeight); @@ -6054,14 +6078,9 @@ var Phaser; AABB.prototype.preUpdate = function () { this.oldPosition.copyFrom(this.position); if(this.sprite) { - // Update position to sprite value - //console.log('a', this.position.x, this.position.y); this.position.setTo((this.sprite.x + this.bounds.halfWidth) + this.offset.x, (this.sprite.y + this.bounds.halfHeight) + this.offset.y); - //console.log('b', this.position.x, this.position.y); - //this.position.setTo(this.sprite.x, this.sprite.y); // Update scale / dimensions if(Phaser.Vec2Utils.equals(this.scale, this.sprite.scale) == false) { - console.log('scaled'); this.scale.copyFrom(this.sprite.scale); this.bounds.width = this.sprite.width; this.bounds.height = this.sprite.height; @@ -6069,6 +6088,8 @@ var Phaser; } }; AABB.prototype.update = function () { + this.bounds.x = this.position.x; + this.bounds.y = this.position.y; }; AABB.prototype.setSize = function (width, height) { this.bounds.width = width; @@ -6205,7 +6226,7 @@ var Phaser; function (x, y, width, height) { return this._world.physics.add(new Phaser.Physics.AABB(this._game, null, x, y, width, height)); }; - GameObjectFactory.prototype.tween = /** + GameObjectFactory.prototype.scrollZone = /** * Create a new Particle. * * @return {Particle} The newly created particle object. @@ -6234,10 +6255,14 @@ var Phaser; * @param height {number} Height of this object. * @returns {ScrollZone} The newly created scroll zone object. */ - //public scrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone { - // return this._world.group.add(new ScrollZone(this._game, key, x, y, width, height)); - //} - /** + 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.group.add(new Phaser.ScrollZone(this._game, key, x, y, width, height)); + }; + GameObjectFactory.prototype.tween = /** * Create a new Tilemap. * * @param key {string} Key for tileset image. @@ -6270,7 +6295,7 @@ var Phaser; function (sprite) { return this._world.group.add(sprite); }; - GameObjectFactory.prototype.existingTween = /** + GameObjectFactory.prototype.existingScrollZone = /** * Add an existing GeomSprite to the current world. * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break. * @@ -6297,10 +6322,10 @@ var Phaser; * @param scrollZone The ScrollZone to add to the Game World * @return {Phaser.ScrollZone} The ScrollZone object */ - //public existingScrollZone(scrollZone: ScrollZone): ScrollZone { - // return this._world.group.add(scrollZone); - //} - /** + function (scrollZone) { + return this._world.group.add(scrollZone); + }; + GameObjectFactory.prototype.existingTween = /** * Add an existing Tilemap to the current world. * Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break. * @@ -10881,19 +10906,284 @@ var Phaser; HeadlessRenderer.prototype.render = function () { }; HeadlessRenderer.prototype.renderSprite = function (camera, sprite) { - // Render checks (needs inCamera check added) - if(sprite.scale.x == 0 || sprite.scale.y == 0 || sprite.texture.alpha < 0.1) { - return false; - } + return true; + }; + HeadlessRenderer.prototype.renderScrollZone = function (camera, scrollZone) { return true; }; return HeadlessRenderer; })(); Phaser.HeadlessRenderer = HeadlessRenderer; - // Add Tilemap, ScrollZone, etc? - })(Phaser || (Phaser = {})); +})(Phaser || (Phaser = {})); +/// +/// +/// +/** +* Phaser - ScrollRegion +* +* Creates a scrolling region within a ScrollZone. +* It is scrolled via the scrollSpeed.x/y properties. +*/ +var Phaser; +(function (Phaser) { + var ScrollRegion = (function () { + /** + * ScrollRegion constructor + * Create a new ScrollRegion. + * + * @param x {number} X position in world coordinate. + * @param y {number} Y position in world coordinate. + * @param width {number} Width of this object. + * @param height {number} Height of this object. + * @param speedX {number} X-axis scrolling speed. + * @param speedY {number} Y-axis scrolling speed. + */ + function ScrollRegion(x, y, width, height, speedX, speedY) { + this._anchorWidth = 0; + this._anchorHeight = 0; + this._inverseWidth = 0; + this._inverseHeight = 0; + /** + * Will this region be rendered? (default to true) + * @type {boolean} + */ + this.visible = true; + // Our seamless scrolling quads + this._A = new Phaser.Rectangle(x, y, width, height); + this._B = new Phaser.Rectangle(x, y, width, height); + this._C = new Phaser.Rectangle(x, y, width, height); + this._D = new Phaser.Rectangle(x, y, width, height); + this._scroll = new Phaser.Vec2(); + this._bounds = new Phaser.Rectangle(x, y, width, height); + this.scrollSpeed = new Phaser.Vec2(speedX, speedY); + } + ScrollRegion.prototype.update = /** + * Update region scrolling with tick time. + * @param delta {number} Elapsed time since last update. + */ + function (delta) { + this._scroll.x += this.scrollSpeed.x; + this._scroll.y += this.scrollSpeed.y; + if(this._scroll.x > this._bounds.right) { + this._scroll.x = this._bounds.x; + } + if(this._scroll.x < this._bounds.x) { + this._scroll.x = this._bounds.right; + } + if(this._scroll.y > this._bounds.bottom) { + this._scroll.y = this._bounds.y; + } + if(this._scroll.y < this._bounds.y) { + this._scroll.y = this._bounds.bottom; + } + // Anchor Dimensions + this._anchorWidth = (this._bounds.width - this._scroll.x) + this._bounds.x; + this._anchorHeight = (this._bounds.height - this._scroll.y) + this._bounds.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; + // Rectangle A + this._A.setTo(this._scroll.x, this._scroll.y, this._anchorWidth, this._anchorHeight); + // Rectangle B + this._B.y = this._scroll.y; + this._B.width = this._inverseWidth; + this._B.height = this._anchorHeight; + // Rectangle C + this._C.x = this._scroll.x; + this._C.width = this._anchorWidth; + this._C.height = this._inverseHeight; + // Rectangle D + this._D.width = this._inverseWidth; + this._D.height = this._inverseHeight; + }; + ScrollRegion.prototype.render = /** + * Render this region to specific context. + * @param context {CanvasRenderingContext2D} Canvas context this region will be rendered to. + * @param texture {object} The texture to be rendered. + * @param dx {number} X position in world coordinate. + * @param dy {number} Y position in world coordinate. + * @param width {number} Width of this region to be rendered. + * @param height {number} Height of this region to be rendered. + */ + function (context, texture, dx, dy, dw, dh) { + if(this.visible == false) { + return; + } + // dx/dy are the world coordinates to render the FULL ScrollZone into. + // This ScrollRegion may be smaller than that and offset from the dx/dy coordinates. + 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); + //context.fillStyle = 'rgb(255,255,255)'; + //context.font = '18px Arial'; + //context.fillText('RectangleA: ' + this._A.toString(), 32, 450); + //context.fillText('RectangleB: ' + this._B.toString(), 32, 480); + //context.fillText('RectangleC: ' + this._C.toString(), 32, 510); + //context.fillText('RectangleD: ' + this._D.toString(), 32, 540); + }; + ScrollRegion.prototype.crop = /** + * Crop part of the texture and render it to the given context. + * @param context {CanvasRenderingContext2D} Canvas context the texture will be rendered to. + * @param texture {object} Texture to be rendered. + * @param srcX {number} Target region top-left x coordinate in the texture. + * @param srcX {number} Target region top-left y coordinate in the texture. + * @param srcW {number} Target region width in the texture. + * @param srcH {number} Target region height in the texture. + * @param destX {number} Render region top-left x coordinate in the context. + * @param destX {number} Render region top-left y coordinate in the context. + * @param destW {number} Target region width in the context. + * @param destH {number} Target region height in the context. + * @param offsetX {number} X offset to the context. + * @param offsetY {number} Y offset to the context. + */ + 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; + } + srcX = Math.floor(srcX); + srcY = Math.floor(srcY); + srcW = Math.floor(srcW); + srcH = Math.floor(srcH); + offsetX = Math.floor(offsetX + this._bounds.x); + offsetY = Math.floor(offsetY + this._bounds.y); + if(srcW > 0 && srcH > 0) { + context.drawImage(texture, srcX, srcY, srcW, srcH, offsetX, offsetY, srcW, srcH); + } + }; + return ScrollRegion; + })(); + Phaser.ScrollRegion = ScrollRegion; +})(Phaser || (Phaser = {})); +var __extends = this.__extends || function (d, b) { + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +/// +/// +/// +/** +* 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); + /** + * ScrollZone constructor + * Create a new ScrollZone. + * + * @param game {Phaser.Game} Current game instance. + * @param key {string} Asset key for image texture of this object. + * @param x {number} X position in world coordinate. + * @param y {number} Y position in world coordinate. + * @param [width] {number} width of this object. + * @param [height] {number} height of this object. + */ + 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, key, width, height); + this.type = Phaser.Types.SCROLLZONE; + this.render = game.renderer.renderScrollZone; + this.physics.moves = false; + this.regions = []; + if(this.texture.loaded) { + if(width > this.width || height > this.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.width || height < this.height) && width !== 0 && height !== 0) { + this.width = width; + this.height = height; + } + } + } + ScrollZone.prototype.addRegion = /** + * Add a new region to this zone. + * @param x {number} X position of the new region. + * @param y {number} Y position of the new region. + * @param width {number} Width of the new region. + * @param height {number} Height of the new region. + * @param [speedX] {number} x-axis scrolling speed. + * @param [speedY] {number} y-axis scrolling speed. + * @return {ScrollRegion} The newly added region. + */ + function (x, y, width, height, speedX, speedY) { + if (typeof speedX === "undefined") { speedX = 0; } + if (typeof speedY === "undefined") { speedY = 0; } + if(x > this.width || y > this.height || x < 0 || y < 0 || (x + width) > this.width || (y + height) > this.height) { + throw Error('Invalid ScrollRegion defined. Cannot be larger than parent ScrollZone'); + return; + } + this.currentRegion = new Phaser.ScrollRegion(x, y, width, height, speedX, speedY); + this.regions.push(this.currentRegion); + return this.currentRegion; + }; + ScrollZone.prototype.setSpeed = /** + * Set scrolling speed of current region. + * @param x {number} X speed of current region. + * @param y {number} Y speed of current region. + */ + function (x, y) { + if(this.currentRegion) { + this.currentRegion.scrollSpeed.setTo(x, y); + } + return this; + }; + ScrollZone.prototype.update = /** + * Update regions. + */ + function () { + for(var i = 0; i < this.regions.length; i++) { + this.regions[i].update(this.game.time.delta); + } + }; + ScrollZone.prototype.createRepeatingTexture = /** + * Create repeating texture with _texture, and store it into the _dynamicTexture. + * Used to create texture when texture image is small than size of the zone. + */ + function (regionWidth, regionHeight) { + console.log('create repeat'); + // Work out how many we'll need of the source image to make it tile properly + var tileWidth = Math.ceil(this.width / regionWidth) * regionWidth; + var tileHeight = Math.ceil(this.height / regionHeight) * regionHeight; + var dt = new Phaser.DynamicTexture(this.game, tileWidth, tileHeight); + dt.context.rect(0, 0, tileWidth, tileHeight); + dt.context.fillStyle = dt.context.createPattern(this.texture.imageTexture, "repeat"); + dt.context.fill(); + this.texture.loadDynamicTexture(dt); + }; + return ScrollZone; + })(Phaser.Sprite); + Phaser.ScrollZone = ScrollZone; +})(Phaser || (Phaser = {})); /// /// +/// /// /// var Phaser; @@ -11034,6 +11324,89 @@ var Phaser; } return true; }; + CanvasRenderer.prototype.renderScrollZone = function (camera, scrollZone) { + // Render checks (needs inCamera check added) + if(scrollZone.scale.x == 0 || scrollZone.scale.y == 0 || scrollZone.texture.alpha < 0.1) { + return false; + } + // Reset our temp vars + this._ga = -1; + this._sx = 0; + this._sy = 0; + this._sw = scrollZone.frameBounds.width; + this._sh = scrollZone.frameBounds.height; + this._fx = scrollZone.scale.x; + this._fy = scrollZone.scale.y; + this._sin = 0; + this._cos = 1; + this._dx = (camera.scaledX * scrollZone.scrollFactor.x) + scrollZone.frameBounds.x - (camera.worldView.x * scrollZone.scrollFactor.x); + this._dy = (camera.scaledY * scrollZone.scrollFactor.y) + scrollZone.frameBounds.y - (camera.worldView.y * scrollZone.scrollFactor.y); + this._dw = scrollZone.frameBounds.width; + this._dh = scrollZone.frameBounds.height; + // Alpha + if(scrollZone.texture.alpha !== 1) { + this._ga = scrollZone.texture.context.globalAlpha; + scrollZone.texture.context.globalAlpha = scrollZone.texture.alpha; + } + // Sprite Flip X + if(scrollZone.texture.flippedX) { + this._fx = -scrollZone.scale.x; + } + // Sprite Flip Y + if(scrollZone.texture.flippedY) { + this._fy = -scrollZone.scale.y; + } + // Rotation and Flipped + if(scrollZone.modified) { + if(scrollZone.texture.renderRotation == true && (scrollZone.rotation !== 0 || scrollZone.rotationOffset !== 0)) { + this._sin = Math.sin(scrollZone.game.math.degreesToRadians(scrollZone.rotationOffset + scrollZone.rotation)); + this._cos = Math.cos(scrollZone.game.math.degreesToRadians(scrollZone.rotationOffset + scrollZone.rotation)); + } + // setTransform(a, b, c, d, e, f); + // a = scale x + // b = skew x + // c = skew y + // d = scale y + // e = translate x + // f = translate y + scrollZone.texture.context.save(); + scrollZone.texture.context.setTransform(this._cos * this._fx, (this._sin * this._fx) + scrollZone.skew.x, -(this._sin * this._fy) + scrollZone.skew.y, this._cos * this._fy, this._dx, this._dy); + this._dx = -scrollZone.origin.x; + this._dy = -scrollZone.origin.y; + } else { + if(!scrollZone.origin.equals(0)) { + this._dx -= scrollZone.origin.x; + this._dy -= scrollZone.origin.y; + } + } + this._sx = Math.round(this._sx); + this._sy = Math.round(this._sy); + this._sw = Math.round(this._sw); + this._sh = Math.round(this._sh); + this._dx = Math.round(this._dx); + this._dy = Math.round(this._dy); + this._dw = Math.round(this._dw); + this._dh = Math.round(this._dh); + for(var i = 0; i < scrollZone.regions.length; i++) { + if(scrollZone.texture.isDynamic) { + scrollZone.regions[i].render(scrollZone.texture.context, scrollZone.texture.texture, this._dx, this._dy, this._dw, this._dh); + } else { + scrollZone.regions[i].render(scrollZone.texture.context, scrollZone.texture.texture, this._dx, this._dy, this._dw, this._dh); + } + } + if(scrollZone.modified) { + scrollZone.texture.context.restore(); + } + //if (this.renderDebug) + //{ + // this.renderBounds(camera, cameraOffsetX, cameraOffsetY); + //this.collisionMask.render(camera, cameraOffsetX, cameraOffsetY); + //} + if(this._ga > -1) { + scrollZone.texture.context.globalAlpha = this._ga; + } + return true; + }; return CanvasRenderer; })(); Phaser.CanvasRenderer = CanvasRenderer; @@ -11685,11 +12058,10 @@ var Phaser; (function (Phaser) { /// /// + /// /// /** * Phaser - Components - Physics - * - * */ (function (Components) { var Physics = (function () { @@ -11699,17 +12071,15 @@ var Phaser; * @type {boolean} */ this.moves = true; - this._game = parent.game; + this.game = parent.game; this._sprite = parent; - // Copy from PhysicsManager? - this.gravity = new Phaser.Vec2(); - this.drag = new Phaser.Vec2(); - this.bounce = new Phaser.Vec2(); - this.friction = new Phaser.Vec2(); + this.gravity = Phaser.Vec2Utils.clone(this.game.world.physics.gravity); + this.drag = Phaser.Vec2Utils.clone(this.game.world.physics.drag); + this.bounce = Phaser.Vec2Utils.clone(this.game.world.physics.bounce); + this.friction = Phaser.Vec2Utils.clone(this.game.world.physics.friction); this.velocity = new Phaser.Vec2(); this.acceleration = new Phaser.Vec2(); - //this.AABB = new Phaser.Physics.AABB(this._game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height); - this.shape = this._game.world.physics.add(new Phaser.Physics.AABB(this._game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height)); + this.shape = this.game.world.physics.add(new Phaser.Physics.AABB(this.game, this._sprite, this._sprite.x, this._sprite.y, this._sprite.width, this._sprite.height)); } Physics.prototype.update = /** * Internal function for updating the position and speed of this object. @@ -11718,11 +12088,7 @@ var Phaser; if(this.moves) { this._sprite.x = (this.shape.position.x - this.shape.bounds.halfWidth) - this.shape.offset.x; this._sprite.y = (this.shape.position.y - this.shape.bounds.halfHeight) - this.shape.offset.y; - //this._sprite.x = (this.shape.position.x - this.shape.bounds.halfWidth); - //this._sprite.y = (this.shape.position.y - this.shape.bounds.halfHeight); - //this._sprite.x = (this.shape.position.x); - //this._sprite.y = (this.shape.position.y); - } + } }; Physics.prototype.renderDebugInfo = /** * Render debug infos. (including name, bounds info, position and some other properties) @@ -11896,11 +12262,6 @@ var Phaser; })(); Phaser.LinkedList = LinkedList; })(Phaser || (Phaser = {})); -var __extends = this.__extends || function (d, b) { - function __() { this.constructor = d; } - __.prototype = b.prototype; - d.prototype = new __(); -}; /// /// ///