diff --git a/examples/assets/audio/Scyphe - Goldrunner (Maccie Pimp Me Up Remix).mp3 b/examples/assets/audio/Scyphe - Goldrunner (Maccie Pimp Me Up Remix).mp3 new file mode 100644 index 00000000..350d28cb Binary files /dev/null and b/examples/assets/audio/Scyphe - Goldrunner (Maccie Pimp Me Up Remix).mp3 differ diff --git a/examples/assets/audio/Totta - Hero Quest - Pophousedub remix.mp3 b/examples/assets/audio/Totta - Hero Quest - Pophousedub remix.mp3 new file mode 100644 index 00000000..ec23dc42 Binary files /dev/null and b/examples/assets/audio/Totta - Hero Quest - Pophousedub remix.mp3 differ diff --git a/examples/assets/sprites/p2.jpeg b/examples/assets/sprites/p2.jpeg new file mode 100644 index 00000000..49432887 Binary files /dev/null and b/examples/assets/sprites/p2.jpeg differ diff --git a/examples/js.php b/examples/js.php index 9b85d154..c4b086f3 100644 --- a/examples/js.php +++ b/examples/js.php @@ -63,6 +63,7 @@ + diff --git a/examples/tilesprite1.php b/examples/tilesprite1.php new file mode 100644 index 00000000..44a75653 --- /dev/null +++ b/examples/tilesprite1.php @@ -0,0 +1,76 @@ + + + + phaser.js - a new beginning + + + + + + + + \ No newline at end of file diff --git a/examples/tilesprite2.php b/examples/tilesprite2.php new file mode 100644 index 00000000..5ad09c6f --- /dev/null +++ b/examples/tilesprite2.php @@ -0,0 +1,54 @@ + + + + phaser.js - a new beginning + + + + + + + + \ No newline at end of file diff --git a/src/gameobjects/GameObjectFactory.js b/src/gameobjects/GameObjectFactory.js index 0e8ee585..e29b484c 100644 --- a/src/gameobjects/GameObjectFactory.js +++ b/src/gameobjects/GameObjectFactory.js @@ -21,9 +21,6 @@ Phaser.GameObjectFactory.prototype = { */ sprite: function (x, y, key, frame) { - if (typeof key === "undefined") { key = ''; } - if (typeof frame === "undefined") { frame = null; } - return this.world.add(new Phaser.Sprite(this.game, x, y, key, frame)); }, @@ -37,20 +34,22 @@ Phaser.GameObjectFactory.prototype = { */ tween: function (obj, localReference) { - if (typeof localReference === "undefined") { localReference = false; } - return this.game.tweens.create(obj, localReference); }, audio: function (key, volume, loop) { - volume = volume || 1; - loop = loop || false; - return this.game.sound.add(key, volume, loop); - } + }, + + tileSprite: function (x, y, width, height, key, frame) { + + return this.world.add(new Phaser.TileSprite(this.game, x, y, width, height, key, frame)); + + }, + }; \ No newline at end of file diff --git a/src/gameobjects/Sprite.js b/src/gameobjects/Sprite.js index 18056d06..31863238 100644 --- a/src/gameobjects/Sprite.js +++ b/src/gameobjects/Sprite.js @@ -70,13 +70,13 @@ Phaser.Sprite = function (game, x, y, key, frame) { * @property blendMode * @type Number */ - this.blendMode = PIXI.blendModes.NORMAL; + // this.blendMode = PIXI.blendModes.NORMAL; this.x = x; this.y = y; - this.updateFrame = true; - this.renderable = true; + // this.updateFrame = true; + // this.renderable = true; this.position.x = x; this.position.y = y; @@ -355,5 +355,4 @@ Object.defineProperty(Phaser.Sprite.prototype, "inCamera", { return this._cache.cameraVisible; } - }); diff --git a/src/gameobjects/TileSprite.js b/src/gameobjects/TileSprite.js new file mode 100644 index 00000000..e2fa4331 --- /dev/null +++ b/src/gameobjects/TileSprite.js @@ -0,0 +1,380 @@ +Phaser.TileSprite = function (game, x, y, width, height, key, frame) { + + x = x || 0; + y = y || 0; + width = width || 256; + height = height || 256; + key = key || null; + frame = frame || null; + + this.game = game; + + this.exists = true; + this.active = true; + this.visible = true; + this.alive = true; + + this.group = null; + + this.name = ''; + + /** + * This manages animations of the sprite. You can modify animations through it. (see AnimationManager) + * @type AnimationManager + */ + this.animations = new Phaser.AnimationManager(this); + + // Phaser.Sprite.call(this); + PIXI.TilingSprite.call(this); + + /** + * The texture that the sprite is using + * + * @property texture + * @type Texture + */ + this.texture = PIXI.TextureCache[key]; + + if (this.game.cache.isSpriteSheet(key)) + { + this.animations.loadFrameData(this.game.cache.getFrameData(key)); + } + + if (frame !== null) + { + if (typeof frame === 'string') + { + this.frameName = frame; + } + else + { + this.frame = frame; + } + } + + /** + * The width of the tiling sprite + * + * @property width + * @type Number + */ + this.width = width; + + /** + * The height of the tiling sprite + * + * @property height + * @type Number + */ + this.height = height; + + /** + * Should this Sprite be automatically culled if out of range of the camera? + * A culled sprite has its visible property set to 'false'. + * Note that this check doesn't look at this Sprites children, which may still be in camera range. + * So you should set autoCull to false if the Sprite will have children likely to still be in camera range. + * + * @property autoCull + * @type Boolean + */ + this.autoCull = false; + + // Replaces the PIXI.Point with a slightly more flexible one + this.scale = new Phaser.Point(1, 1); + + // Influence of camera movement upon the position + this.scrollFactor = new Phaser.Point(1, 1); + + /** + * The anchor sets the origin point of the texture. + * The default is 0,0 this means the textures origin is the top left + * Setting than anchor to 0.5,0.5 means the textures origin is centered + * Setting the anchor to 1,1 would mean the textures origin points will be the bottom right + * + * @property anchor + * @type Point + */ + // this.anchor = new Phaser.Point(); + + /** + * The scaling of the image that is being tiled + * + * @property tileScale + * @type Point + */ + this.tileScale = new Phaser.Point(1,1); + + /** + * The offset position of the image that is being tiled + * + * @property tilePosition + * @type Point + */ + this.tilePosition = new Phaser.Point(0,0); + + this.bounds = new Phaser.Rectangle(x, y, this.width, this.height); + + this.x = x; + this.y = y; + this.position.x = x; + this.position.y = y; + + // A mini cache for storing all of the calculated values + this._cache = { + + dirty: false, + + // Transform cache + a00: 1, a01: 0, a02: x, a10: 0, a11: 1, a12: y, id: 1, + + // Bounds check + left: null, right: null, top: null, bottom: null, + + // The previous calculated position inc. camera x/y and scrollFactor + x: -1, y: -1, + + // The actual scale values based on the worldTransform + scaleX: 1, scaleY: 1, + + // The width/height of the image, based on the un-modified frame size multiplied by the final calculated scale size + width: width, height: height, + + // The current frame index, used to check for bounds updates + frameWidth: 0, frameHeight: 0, + + boundsX: 0, boundsY: 0, + + // If this sprite visible to the camera (regardless of being set to visible or not) + cameraVisible: true + + }; + + // Corner points + this.offset = new Phaser.Point(); + this.topLeft = new Phaser.Point(); + this.topRight = new Phaser.Point(); + this.bottomRight = new Phaser.Point(); + this.bottomLeft = new Phaser.Point(); + this.bounds = new Phaser.Rectangle(x, y, this.width, this.height); + + this.getLocalPosition(this.topLeft, this.offset.x, this.offset.y); + this.getLocalPosition(this.topRight, this.offset.x + this.width, this.offset.y); + this.getLocalPosition(this.bottomLeft, this.offset.x, this.offset.y + this.height); + this.getLocalPosition(this.bottomRight, this.offset.x + this.width, this.offset.y + this.height); + +}; + +Phaser.TileSprite.prototype = Object.create(PIXI.TilingSprite.prototype); +Phaser.TileSprite.prototype.constructor = Phaser.TileSprite; + +/** + * Automatically called by the game loop. + */ +Phaser.TileSprite.prototype.update = function () { + + this._cache.dirty = false; + + this.animations.update(); + + this._cache.x = this.x - (this.game.world.camera.x * this.scrollFactor.x); + this._cache.y = this.y - (this.game.world.camera.y * this.scrollFactor.y); + + // If this sprite or the camera have moved then let's update everything + // It may have rotated though ... + if (this.position.x != this._cache.x || this.position.y != this._cache.y) + { + this.position.x = this._cache.x; + this.position.y = this._cache.y; + this._cache.dirty = true; + } + + if (this.visible) + { + // |a c tx| + // |b d ty| + // |0 0 1| + + // Only update the values we need + if (this.worldTransform[0] != this._cache.a00 || this.worldTransform[1] != this._cache.a01) + { + this._cache.a00 = this.worldTransform[0]; // scaleX a + this._cache.a01 = this.worldTransform[1]; // skewY c + this._cache.scaleX = Math.sqrt((this._cache.a00 * this._cache.a00) + (this._cache.a01 * this._cache.a01)); + this._cache.a01 *= -1; + this._cache.dirty = true; + } + + // Need to test, but probably highly unlikely that a scaleX would happen without effecting the Y skew + if (this.worldTransform[3] != this._cache.a10 || this.worldTransform[4] != this._cache.a11) + { + this._cache.a10 = this.worldTransform[3]; // skewX b + this._cache.a11 = this.worldTransform[4]; // scaleY d + this._cache.scaleY = Math.sqrt((this._cache.a10 * this._cache.a10) + (this._cache.a11 * this._cache.a11)); + this._cache.a10 *= -1; + this._cache.dirty = true; + } + + if (this.worldTransform[2] != this._cache.a02 || this.worldTransform[5] != this._cache.a12) + { + this._cache.a02 = this.worldTransform[2]; // translateX tx + this._cache.a12 = this.worldTransform[5]; // translateY ty + this._cache.dirty = true; + } + + if (this._cache.dirty || this.texture.frame.width != this._cache.frameWidth || this.texture.frame.height != this._cache.frameHeight) + { + this._cache.frameWidth = this.texture.frame.width; + this._cache.frameHeight = this.texture.frame.height; + + this._cache.width = this.width * this._cache.scaleX; + this._cache.height = this.height * this._cache.scaleY; + + this._cache.dirty = true; + } + + if (this._cache.dirty) + { + this._cache.id = 1 / (this._cache.a00 * this._cache.a11 + this._cache.a01 * -this._cache.a10); + this.updateBounds(); + } + } + else + { + // We still need to work out the bounds in case the camera has moved + // but we can't use the local or worldTransform to do it, as Pixi resets that if a Sprite is invisible. + // So we'll compare against the cached state + new position. + if (this._cache.dirty && this.visible == false) + { + this.bounds.x -= this._cache.boundsX - this._cache.x; + this._cache.boundsX = this._cache.x; + + this.bounds.y -= this._cache.boundsy - this._cache.y; + this._cache.boundsY = this._cache.y; + } + } + + // Re-run the camera visibility check + if (this._cache.dirty) + { + this._cache.cameraVisible = Phaser.Rectangle.intersects(this.game.world.camera.screenView, this.bounds, 0); + + if (this.autoCull == true) + { + this.visible = this._cache.cameraVisible; + } + } + + // Check our bounds + +} + +Phaser.TileSprite.prototype.updateBounds = function() { + + // Update the edge points + + this.offset.setTo(this._cache.a02, this._cache.a12); + + this.getLocalPosition(this.topLeft, this.offset.x, this.offset.y); + this.getLocalPosition(this.topRight, this.offset.x + this._cache.width, this.offset.y); + this.getLocalPosition(this.bottomLeft, this.offset.x, this.offset.y + this._cache.height); + this.getLocalPosition(this.bottomRight, this.offset.x + this._cache.width, this.offset.y + this._cache.height); + + this._cache.left = Phaser.Math.min(this.topLeft.x, this.topRight.x, this.bottomLeft.x, this.bottomRight.x); + this._cache.right = Phaser.Math.max(this.topLeft.x, this.topRight.x, this.bottomLeft.x, this.bottomRight.x); + this._cache.top = Phaser.Math.min(this.topLeft.y, this.topRight.y, this.bottomLeft.y, this.bottomRight.y); + this._cache.bottom = Phaser.Math.max(this.topLeft.y, this.topRight.y, this.bottomLeft.y, this.bottomRight.y); + + this.bounds.setTo(this._cache.left, this._cache.top, this._cache.right - this._cache.left, this._cache.bottom - this._cache.top); + + // This is the coordinate the Sprite was at when the last bounds was created + this._cache.boundsX = this._cache.x; + this._cache.boundsY = this._cache.y; + +} + +Phaser.TileSprite.prototype.getLocalPosition = function(p, x, y) { + + p.x = ((this._cache.a11 * this._cache.id * x + -this._cache.a01 * this._cache.id * y + (this._cache.a12 * this._cache.a01 - this._cache.a02 * this._cache.a11) * this._cache.id) * this._cache.scaleX) + this._cache.a02; + p.y = ((this._cache.a00 * this._cache.id * y + -this._cache.a10 * this._cache.id * x + (-this._cache.a12 * this._cache.a00 + this._cache.a02 * this._cache.a10) * this._cache.id) * this._cache.scaleY) + this._cache.a12; + + return p; + +} + +Phaser.TileSprite.prototype.getBounds = function(rect) { + + rect = rect || new Phaser.Rectangle; + + var left = Phaser.Math.min(this.topLeft.x, this.topRight.x, this.bottomLeft.x, this.bottomRight.x); + var right = Phaser.Math.max(this.topLeft.x, this.topRight.x, this.bottomLeft.x, this.bottomRight.x); + var top = Phaser.Math.min(this.topLeft.y, this.topRight.y, this.bottomLeft.y, this.bottomRight.y); + var bottom = Phaser.Math.max(this.topLeft.y, this.topRight.y, this.bottomLeft.y, this.bottomRight.y); + + rect.x = left; + rect.y = top; + rect.width = right - left; + rect.height = bottom - top; + + return rect; + +} + +Object.defineProperty(Phaser.TileSprite.prototype, 'angle', { + + get: function() { + return Phaser.Math.radToDeg(this.rotation); + }, + + set: function(value) { + this.rotation = Phaser.Math.degToRad(value); + } + +}); + +Object.defineProperty(Phaser.TileSprite.prototype, "frame", { + + /** + * Get the animation frame number. + */ + get: function () { + return this.animations.frame; + }, + + /** + * Set the animation frame by frame number. + */ + set: function (value) { + this.animations.frame = value; + } + +}); + +Object.defineProperty(Phaser.TileSprite.prototype, "frameName", { + + /** + * Get the animation frame name. + */ + get: function () { + return this.animations.frameName; + }, + + /** + * Set the animation frame by frame name. + */ + set: function (value) { + this.animations.frameName = value; + } + +}); + +Object.defineProperty(Phaser.TileSprite.prototype, "inCamera", { + + /** + * Is this sprite visible to the camera or not? + */ + get: function () { + return this._cache.cameraVisible; + } + +}); + diff --git a/src/loader/Loader.js b/src/loader/Loader.js index 1fd66419..4e09954f 100644 --- a/src/loader/Loader.js +++ b/src/loader/Loader.js @@ -474,7 +474,7 @@ Phaser.Loader.prototype = { this.onFileError.dispatch(key); - throw new Error("Phaser.Loader error loading file: " + key); + console.warn("Phaser.Loader error loading file: " + key); this.nextFile(key, false); @@ -488,7 +488,7 @@ Phaser.Loader.prototype = { if (!this._fileList[key]) { - throw new Error('Phaser.Loader fileComplete invalid key ' + key); + console.warn('Phaser.Loader fileComplete invalid key ' + key); return; }