Finally fixed a really annoying bug in ScrollZone and it now works perfectly across the board.

This commit is contained in:
Richard Davey
2013-04-23 15:15:34 +01:00
parent f2678104fa
commit 332f715943
22 changed files with 720 additions and 402 deletions
+146
View File
@@ -0,0 +1,146 @@
/// <reference path="../Game.ts" />
/// <reference path="../geom/Quad.ts" />
/**
* 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);
}
}
}
}
+64 -145
View File
@@ -1,12 +1,13 @@
/// <reference path="../Game.ts" />
/// <reference path="../geom/Quad.ts" />
/// <reference path="ScrollRegion.ts" />
/**
* 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;
}
}