Preparing for new release

This commit is contained in:
Richard Davey
2013-04-18 14:16:18 +01:00
parent 72a4809dd8
commit 6bb4c5e3fc
165 changed files with 37278 additions and 29038 deletions
+461
View File
@@ -0,0 +1,461 @@
/// <reference path="../Game.ts" />
/// <reference path="../Group.ts" />
/**
* <code>Emitter</code> is a lightweight particle emitter.
* It can be used for one-time explosions or for
* continuous fx like rain and fire. <code>Emitter</code>
* is not optimized or anything; all it does is launch
* <code>Particle</code> objects out at set intervals
* by setting their positions and velocities accordingly.
* It is easy to use and relatively efficient,
* relying on <code>Group</code>'s RECYCLE POWERS.
*
* @author Adam Atomic
* @author Richard Davey
*/
/**
* Phaser
*/
module Phaser {
export class Emitter extends Group {
/**
* Creates a new <code>FlxEmitter</code> object at a specific position.
* Does NOT automatically generate or attach particles!
*
* @param X The X position of the emitter.
* @param Y The Y position of the emitter.
* @param Size Optional, specifies a maximum capacity for this emitter.
*/
constructor(game: Game, X: number = 0, Y: number = 0, Size: number = 0) {
super(game, Size);
this.x = X;
this.y = Y;
this.width = 0;
this.height = 0;
this.minParticleSpeed = new Point(-100, -100);
this.maxParticleSpeed = new Point(100, 100);
this.minRotation = -360;
this.maxRotation = 360;
this.gravity = 0;
this.particleClass = null;
this.particleDrag = new Point();
this.frequency = 0.1;
this.lifespan = 3;
this.bounce = 0;
this._quantity = 0;
this._counter = 0;
this._explode = true;
this.on = false;
this._point = new Point();
}
/**
* The X position of the top left corner of the emitter in world space.
*/
public x: number;
/**
* The Y position of the top left corner of emitter in world space.
*/
public y: number;
/**
* The width of the emitter. Particles can be randomly generated from anywhere within this box.
*/
public width: number;
/**
* The height of the emitter. Particles can be randomly generated from anywhere within this box.
*/
public height: number;
/**
* The minimum possible velocity of a particle.
* The default value is (-100,-100).
*/
public minParticleSpeed: Point;
/**
* The maximum possible velocity of a particle.
* The default value is (100,100).
*/
public maxParticleSpeed: Point;
/**
* The X and Y drag component of particles launched from the emitter.
*/
public particleDrag: Point;
/**
* The minimum possible angular velocity of a particle. The default value is -360.
* NOTE: rotating particles are more expensive to draw than non-rotating ones!
*/
public minRotation: number;
/**
* The maximum possible angular velocity of a particle. The default value is 360.
* NOTE: rotating particles are more expensive to draw than non-rotating ones!
*/
public maxRotation: number;
/**
* Sets the <code>acceleration.y</code> member of each particle to this value on launch.
*/
public gravity: number;
/**
* Determines whether the emitter is currently emitting particles.
* It is totally safe to directly toggle this.
*/
public on: bool;
/**
* How often a particle is emitted (if emitter is started with Explode == false).
*/
public frequency: number;
/**
* How long each particle lives once it is emitted.
* Set lifespan to 'zero' for particles to live forever.
*/
public lifespan: number;
/**
* How much each particle should bounce. 1 = full bounce, 0 = no bounce.
*/
public bounce: number;
/**
* Set your own particle class type here.
* Default is <code>Particle</code>.
*/
public particleClass;
/**
* Internal helper for deciding how many particles to launch.
*/
private _quantity: number;
/**
* Internal helper for the style of particle emission (all at once, or one at a time).
*/
private _explode: bool;
/**
* Internal helper for deciding when to launch particles or kill them.
*/
private _timer: number;
/**
* Internal counter for figuring out how many particles to launch.
*/
private _counter: number;
/**
* Internal point object, handy for reusing for memory mgmt purposes.
*/
private _point: Point;
/**
* Clean up memory.
*/
public destroy() {
this.minParticleSpeed = null;
this.maxParticleSpeed = null;
this.particleDrag = null;
this.particleClass = null;
this._point = null;
super.destroy();
}
/**
* This function generates a new array of particle sprites to attach to the emitter.
*
* @param Graphics If you opted to not pre-configure an array of FlxSprite objects, you can simply pass in a particle image or sprite sheet.
* @param Quantity The number of particles to generate when using the "create from image" option.
* @param BakedRotations How many frames of baked rotation to use (boosts performance). Set to zero to not use baked rotations.
* @param Multiple Whether the image in the Graphics param is a single particle or a bunch of particles (if it's a bunch, they need to be square!).
* @param Collide Whether the particles should be flagged as not 'dead' (non-colliding particles are higher performance). 0 means no collisions, 0-1 controls scale of particle's bounding box.
*
* @return This FlxEmitter instance (nice for chaining stuff together, if you're into that).
*/
public makeParticles(Graphics, Quantity: number = 50, BakedRotations: number = 16, Multiple: bool = false, Collide: number = 0.8): Emitter {
this.maxSize = Quantity;
var totalFrames: number = 1;
/*
if(Multiple)
{
var sprite:Sprite = new Sprite(this._game);
sprite.loadGraphic(Graphics,true);
totalFrames = sprite.frames;
sprite.destroy();
}
*/
var randomFrame: number;
var particle: Particle;
var i: number = 0;
while (i < Quantity)
{
if (this.particleClass == null)
{
particle = new Particle(this._game);
}
else
{
particle = new this.particleClass(this._game);
}
if (Multiple)
{
/*
randomFrame = this._game.math.random()*totalFrames;
if(BakedRotations > 0)
particle.loadRotatedGraphic(Graphics,BakedRotations,randomFrame);
else
{
particle.loadGraphic(Graphics,true);
particle.frame = randomFrame;
}
*/
}
else
{
/*
if (BakedRotations > 0)
particle.loadRotatedGraphic(Graphics,BakedRotations);
else
particle.loadGraphic(Graphics);
*/
if (Graphics)
{
particle.loadGraphic(Graphics);
}
}
if (Collide > 0)
{
particle.width *= Collide;
particle.height *= Collide;
//particle.centerOffsets();
}
else
{
particle.allowCollisions = Collision.NONE;
}
particle.exists = false;
this.add(particle);
i++;
}
return this;
}
/**
* Called automatically by the game loop, decides when to launch particles and when to "die".
*/
public update() {
if (this.on)
{
if (this._explode)
{
this.on = false;
var i: number = 0;
var l: number = this._quantity;
if ((l <= 0) || (l > this.length))
{
l = this.length;
}
while (i < l)
{
this.emitParticle();
i++;
}
this._quantity = 0;
}
else
{
this._timer += this._game.time.elapsed;
while ((this.frequency > 0) && (this._timer > this.frequency) && this.on)
{
this._timer -= this.frequency;
this.emitParticle();
if ((this._quantity > 0) && (++this._counter >= this._quantity))
{
this.on = false;
this._quantity = 0;
}
}
}
}
super.update();
}
/**
* Call this function to turn off all the particles and the emitter.
*/
public kill() {
this.on = false;
super.kill();
}
/**
* Call this function to start emitting particles.
*
* @param Explode Whether the particles should all burst out at once.
* @param Lifespan How long each particle lives once emitted. 0 = forever.
* @param Frequency Ignored if Explode is set to true. Frequency is how often to emit a particle. 0 = never emit, 0.1 = 1 particle every 0.1 seconds, 5 = 1 particle every 5 seconds.
* @param Quantity How many particles to launch. 0 = "all of the particles".
*/
public start(Explode: bool = true, Lifespan: number = 0, Frequency: number = 0.1, Quantity: number = 0) {
this.revive();
this.visible = true;
this.on = true;
this._explode = Explode;
this.lifespan = Lifespan;
this.frequency = Frequency;
this._quantity += Quantity;
this._counter = 0;
this._timer = 0;
}
/**
* This function can be used both internally and externally to emit the next particle.
*/
public emitParticle() {
var particle: Particle = this.recycle(Particle);
particle.lifespan = this.lifespan;
particle.elasticity = this.bounce;
particle.reset(this.x - (particle.width >> 1) + this._game.math.random() * this.width, this.y - (particle.height >> 1) + this._game.math.random() * this.height);
particle.visible = true;
if (this.minParticleSpeed.x != this.maxParticleSpeed.x)
{
particle.velocity.x = this.minParticleSpeed.x + this._game.math.random() * (this.maxParticleSpeed.x - this.minParticleSpeed.x);
}
else
{
particle.velocity.x = this.minParticleSpeed.x;
}
if (this.minParticleSpeed.y != this.maxParticleSpeed.y)
{
particle.velocity.y = this.minParticleSpeed.y + this._game.math.random() * (this.maxParticleSpeed.y - this.minParticleSpeed.y);
}
else
{
particle.velocity.y = this.minParticleSpeed.y;
}
particle.acceleration.y = this.gravity;
if (this.minRotation != this.maxRotation)
{
particle.angularVelocity = this.minRotation + this._game.math.random() * (this.maxRotation - this.minRotation);
}
else
{
particle.angularVelocity = this.minRotation;
}
if (particle.angularVelocity != 0)
{
particle.angle = this._game.math.random() * 360 - 180;
}
particle.drag.x = this.particleDrag.x;
particle.drag.y = this.particleDrag.y;
particle.onEmit();
}
/**
* A more compact way of setting the width and height of the emitter.
*
* @param Width The desired width of the emitter (particles are spawned randomly within these dimensions).
* @param Height The desired height of the emitter.
*/
public setSize(Width: number, Height: number) {
this.width = Width;
this.height = Height;
}
/**
* A more compact way of setting the X velocity range of the emitter.
*
* @param Min The minimum value for this range.
* @param Max The maximum value for this range.
*/
public setXSpeed(Min: number = 0, Max: number = 0) {
this.minParticleSpeed.x = Min;
this.maxParticleSpeed.x = Max;
}
/**
* A more compact way of setting the Y velocity range of the emitter.
*
* @param Min The minimum value for this range.
* @param Max The maximum value for this range.
*/
public setYSpeed(Min: number = 0, Max: number = 0) {
this.minParticleSpeed.y = Min;
this.maxParticleSpeed.y = Max;
}
/**
* A more compact way of setting the angular velocity constraints of the emitter.
*
* @param Min The minimum value for this range.
* @param Max The maximum value for this range.
*/
public setRotation(Min: number = 0, Max: number = 0) {
this.minRotation = Min;
this.maxRotation = Max;
}
/**
* Change the emitter's midpoint to match the midpoint of a <code>FlxObject</code>.
*
* @param Object The <code>FlxObject</code> that you want to sync up with.
*/
public at(Object) {
Object.getMidpoint(this._point);
this.x = this._point.x - (this.width >> 1);
this.y = this._point.y - (this.height >> 1);
}
}
}
+494
View File
@@ -0,0 +1,494 @@
/// <reference path="../Game.ts" />
/// <reference path="../Basic.ts" />
/**
* Phaser
*/
module Phaser {
export class GameObject extends Basic {
constructor(game: Game, x?: number = 0, y?: number = 0, width?: number = 16, height?: number = 16) {
super(game);
this.bounds = new Rectangle(x, y, width, height);
this.exists = true;
this.active = true;
this.visible = true;
this.alive = true;
this.isGroup = false;
this.alpha = 1;
this.scale = new Point(1, 1);
this.last = new Point(x, y);
this.origin = new Point(this.bounds.halfWidth, this.bounds.halfHeight);
this.mass = 1.0;
this.elasticity = 0.0;
this.health = 1;
this.immovable = false;
this.moves = true;
this.touching = Collision.NONE;
this.wasTouching = Collision.NONE;
this.allowCollisions = Collision.ANY;
this.velocity = new Point();
this.acceleration = new Point();
this.drag = new Point();
this.maxVelocity = new Point(10000, 10000);
this.angle = 0;
this.angularVelocity = 0;
this.angularAcceleration = 0;
this.angularDrag = 0;
this.maxAngular = 10000;
this.scrollFactor = new Point(1.0, 1.0);
}
private _angle: number = 0;
public _point: Point;
public bounds: Rectangle;
public facing: number;
public alpha: number;
public scale: Point;
public origin: Point;
public z: number = 0;
// Physics properties
public immovable: bool;
public velocity: Point;
public mass: number;
public elasticity: number;
public acceleration: Point;
public drag: Point;
public maxVelocity: Point;
public angularVelocity: number;
public angularAcceleration: number;
public angularDrag: number;
public maxAngular: number;
public scrollFactor: Point;
public health: number;
public moves: bool = true;
public touching: number;
public wasTouching: number;
public allowCollisions: number;
public last: Point;
public preUpdate() {
// flicker time
this.last.x = this.bounds.x;
this.last.y = this.bounds.y;
}
public update() {
}
public postUpdate() {
if (this.moves)
{
this.updateMotion();
}
this.wasTouching = this.touching;
this.touching = Collision.NONE;
}
private updateMotion() {
var delta: number;
var velocityDelta: number;
velocityDelta = (this._game.motion.computeVelocity(this.angularVelocity, this.angularAcceleration, this.angularDrag, this.maxAngular) - this.angularVelocity) / 2;
this.angularVelocity += velocityDelta;
this._angle += this.angularVelocity * this._game.time.elapsed;
this.angularVelocity += velocityDelta;
velocityDelta = (this._game.motion.computeVelocity(this.velocity.x, this.acceleration.x, this.drag.x, this.maxVelocity.x) - this.velocity.x) / 2;
this.velocity.x += velocityDelta;
delta = this.velocity.x * this._game.time.elapsed;
this.velocity.x += velocityDelta;
this.bounds.x += delta;
velocityDelta = (this._game.motion.computeVelocity(this.velocity.y, this.acceleration.y, this.drag.y, this.maxVelocity.y) - this.velocity.y) / 2;
this.velocity.y += velocityDelta;
delta = this.velocity.y * this._game.time.elapsed;
this.velocity.y += velocityDelta;
this.bounds.y += delta;
}
/**
* Checks to see if some <code>GameObject</code> overlaps this <code>GameObject</code> or <code>FlxGroup</code>.
* If the group has a LOT of things in it, it might be faster to use <code>FlxG.overlaps()</code>.
* WARNING: Currently tilemaps do NOT support screen space overlap checks!
*
* @param ObjectOrGroup The object or group being tested.
* @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the two objects overlap.
*/
public overlaps(ObjectOrGroup, InScreenSpace: bool = false, Camera: Camera = null): bool {
if (ObjectOrGroup.isGroup)
{
var results: bool = false;
var i: number = 0;
var members = <Group> ObjectOrGroup.members;
while (i < length)
{
if (this.overlaps(members[i++], InScreenSpace, Camera))
{
results = true;
}
}
return results;
}
/*
if (typeof ObjectOrGroup === 'FlxTilemap')
{
//Since tilemap's have to be the caller, not the target, to do proper tile-based collisions,
// we redirect the call to the tilemap overlap here.
return ObjectOrGroup.overlaps(this, InScreenSpace, Camera);
}
*/
//var object: GameObject = ObjectOrGroup;
if (!InScreenSpace)
{
return (ObjectOrGroup.x + ObjectOrGroup.width > this.x) && (ObjectOrGroup.x < this.x + this.width) &&
(ObjectOrGroup.y + ObjectOrGroup.height > this.y) && (ObjectOrGroup.y < this.y + this.height);
}
if (Camera == null)
{
Camera = this._game.camera;
}
var objectScreenPos: Point = ObjectOrGroup.getScreenXY(null, Camera);
this.getScreenXY(this._point, Camera);
return (objectScreenPos.x + ObjectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) &&
(objectScreenPos.y + ObjectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
}
/**
* Checks to see if this <code>GameObject</code> were located at the given position, would it overlap the <code>GameObject</code> or <code>FlxGroup</code>?
* This is distinct from overlapsPoint(), which just checks that ponumber, rather than taking the object's size numbero account.
* WARNING: Currently tilemaps do NOT support screen space overlap checks!
*
* @param X The X position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param Y The Y position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param ObjectOrGroup The object or group being tested.
* @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the two objects overlap.
*/
public overlapsAt(X: number, Y: number, ObjectOrGroup, InScreenSpace: bool = false, Camera: Camera = null): bool {
if (ObjectOrGroup.isGroup)
{
var results: bool = false;
var basic;
var i: number = 0;
var members = ObjectOrGroup.members;
while (i < length)
{
if (this.overlapsAt(X, Y, members[i++], InScreenSpace, Camera))
{
results = true;
}
}
return results;
}
/*
if (typeof ObjectOrGroup === 'FlxTilemap')
{
//Since tilemap's have to be the caller, not the target, to do proper tile-based collisions,
// we redirect the call to the tilemap overlap here.
//However, since this is overlapsAt(), we also have to invent the appropriate position for the tilemap.
//So we calculate the offset between the player and the requested position, and subtract that from the tilemap.
var tilemap: FlxTilemap = ObjectOrGroup;
return tilemap.overlapsAt(tilemap.x - (X - this.x), tilemap.y - (Y - this.y), this, InScreenSpace, Camera);
}
*/
//var object: GameObject = ObjectOrGroup;
if (!InScreenSpace)
{
return (ObjectOrGroup.x + ObjectOrGroup.width > X) && (ObjectOrGroup.x < X + this.width) &&
(ObjectOrGroup.y + ObjectOrGroup.height > Y) && (ObjectOrGroup.y < Y + this.height);
}
if (Camera == null)
{
Camera = this._game.camera;
}
var objectScreenPos: Point = ObjectOrGroup.getScreenXY(null, Camera);
this._point.x = X - Camera.scroll.x * this.scrollFactor.x; //copied from getScreenXY()
this._point.y = Y - Camera.scroll.y * this.scrollFactor.y;
this._point.x += (this._point.x > 0) ? 0.0000001 : -0.0000001;
this._point.y += (this._point.y > 0) ? 0.0000001 : -0.0000001;
return (objectScreenPos.x + ObjectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) &&
(objectScreenPos.y + ObjectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
}
/**
* Checks to see if a ponumber in 2D world space overlaps this <code>GameObject</code> object.
*
* @param Point The ponumber in world space you want to check.
* @param InScreenSpace Whether to take scroll factors numbero account when checking for overlap.
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the ponumber overlaps this object.
*/
public overlapsPoint(point: Point, InScreenSpace: bool = false, Camera: Camera = null): bool {
if (!InScreenSpace)
{
return (point.x > this.x) && (point.x < this.x + this.width) && (point.y > this.y) && (point.y < this.y + this.height);
}
if (Camera == null)
{
Camera = this._game.camera;
}
var X: number = point.x - Camera.scroll.x;
var Y: number = point.y - Camera.scroll.y;
this.getScreenXY(this._point, Camera);
return (X > this._point.x) && (X < this._point.x + this.width) && (Y > this._point.y) && (Y < this._point.y + this.height);
}
/**
* Check and see if this object is currently on screen.
*
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether the object is on screen or not.
*/
public onScreen(Camera: Camera = null): bool {
if (Camera == null)
{
Camera = this._game.camera;
}
this.getScreenXY(this._point, Camera);
return (this._point.x + this.width > 0) && (this._point.x < Camera.width) && (this._point.y + this.height > 0) && (this._point.y < Camera.height);
}
/**
* Call this to figure out the on-screen position of the object.
*
* @param Camera Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
* @param Point Takes a <code>Point</code> object and assigns the post-scrolled X and Y values of this object to it.
*
* @return The <code>Point</code> you passed in, or a new <code>Point</code> if you didn't pass one, containing the screen X and Y position of this object.
*/
public getScreenXY(point: Point = null, Camera: Camera = null): Point {
if (point == null)
{
point = new Point();
}
if (Camera == null)
{
Camera = this._game.camera;
}
point.x = this.x - Camera.scroll.x * this.scrollFactor.x;
point.y = this.y - Camera.scroll.y * this.scrollFactor.y;
point.x += (point.x > 0) ? 0.0000001 : -0.0000001;
point.y += (point.y > 0) ? 0.0000001 : -0.0000001;
return point;
}
/**
* Whether the object collides or not. For more control over what directions
* the object will collide from, use collision constants (like LEFT, FLOOR, etc)
* to set the value of allowCollisions directly.
*/
public get solid(): bool {
return (this.allowCollisions & Collision.ANY) > Collision.NONE;
}
/**
* @private
*/
public set solid(Solid: bool) {
if (Solid)
{
this.allowCollisions = Collision.ANY;
}
else
{
this.allowCollisions = Collision.NONE;
}
}
/**
* Retrieve the midponumber of this object in world coordinates.
*
* @Point Allows you to pass in an existing <code>Point</code> object if you're so inclined. Otherwise a new one is created.
*
* @return A <code>Point</code> object containing the midponumber of this object in world coordinates.
*/
public getMidpoint(point: Point = null): Point {
if (point == null)
{
point = new Point();
}
point.x = this.x + this.width * 0.5;
point.y = this.y + this.height * 0.5;
return point;
}
/**
* Handy for reviving game objects.
* Resets their existence flags and position.
*
* @param X The new X position of this object.
* @param Y The new Y position of this object.
*/
public reset(X: number, Y: number) {
this.revive();
this.touching = Collision.NONE;
this.wasTouching = Collision.NONE;
this.x = X;
this.y = Y;
this.last.x = X;
this.last.y = Y;
this.velocity.x = 0;
this.velocity.y = 0;
}
/**
* Handy for checking if this object is touching a particular surface.
* For slightly better performance you can just &amp; the value directly numbero <code>touching</code>.
* However, this method is good for readability and accessibility.
*
* @param Direction Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @return Whether the object is touching an object in (any of) the specified direction(s) this frame.
*/
public isTouching(Direction: number): bool {
return (this.touching & Direction) > Collision.NONE;
}
/**
* Handy for checking if this object is just landed on a particular surface.
*
* @param Direction Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @return Whether the object just landed on (any of) the specified surface(s) this frame.
*/
public justTouched(Direction: number): bool {
return ((this.touching & Direction) > Collision.NONE) && ((this.wasTouching & Direction) <= Collision.NONE);
}
/**
* Reduces the "health" variable of this sprite by the amount specified in Damage.
* Calls kill() if health drops to or below zero.
*
* @param Damage How much health to take away (use a negative number to give a health bonus).
*/
public hurt(Damage: number) {
this.health = this.health - Damage;
if (this.health <= 0)
{
this.kill();
}
}
public destroy() {
}
public get x(): number {
return this.bounds.x;
}
public set x(value: number) {
this.bounds.x = value;
}
public get y(): number {
return this.bounds.y;
}
public set y(value: number) {
this.bounds.y = value;
}
public get rotation(): number {
return this._angle;
}
public set rotation(value: number) {
this._angle = this._game.math.wrap(value, 360, 0);
}
public get angle(): number {
return this._angle;
}
public set angle(value: number) {
this._angle = this._game.math.wrap(value, 360, 0);
}
public get width(): number {
return this.bounds.width;
}
public get height(): number {
return this.bounds.height;
}
}
}
+431
View File
@@ -0,0 +1,431 @@
/// <reference path="../Game.ts" />
/**
* Phaser
*/
module Phaser {
export class GeomSprite extends GameObject {
constructor(game: Game, x?: number = 0, y?: number = 0) {
super(game, x, y);
this.type = GeomSprite.UNASSIGNED;
return this;
}
// 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;
public type: number = 0;
public static UNASSIGNED: number = 0;
public static CIRCLE: number = 1;
public static LINE: number = 2;
public static POINT: number = 3;
public static RECTANGLE: number = 4;
public circle: Circle;
public line: Line;
public point: Point;
public rect: Rectangle;
public renderOutline: bool = true;
public renderFill: bool = true;
public lineWidth: number = 1;
public lineColor: string = 'rgb(0,255,0)';
public fillColor: string = 'rgb(0,100,0)';
loadCircle(circle:Circle): GeomSprite {
this.refresh();
this.circle = circle;
this.type = GeomSprite.CIRCLE;
return this;
}
loadLine(line:Line): GeomSprite {
this.refresh();
this.line = line;
this.type = GeomSprite.LINE;
return this;
}
loadPoint(point:Point): GeomSprite {
this.refresh();
this.point = point;
this.type = GeomSprite.POINT;
return this;
}
loadRectangle(rect:Rectangle): GeomSprite {
this.refresh();
this.rect = rect;
this.type = GeomSprite.RECTANGLE;
return this;
}
createCircle(diameter: number): GeomSprite {
this.refresh();
this.circle = new Circle(this.x, this.y, diameter);
this.type = GeomSprite.CIRCLE;
this.bounds.setTo(this.circle.x - this.circle.radius, this.circle.y - this.circle.radius, this.circle.diameter, this.circle.diameter);
return this;
}
createLine(x: number, y: number): GeomSprite {
this.refresh();
this.line = new Line(this.x, this.y, x, y);
this.type = GeomSprite.LINE;
this.bounds.setTo(this.x, this.y, this.line.width, this.line.height);
return this;
}
createPoint(): GeomSprite {
this.refresh();
this.point = new Point(this.x, this.y);
this.type = GeomSprite.POINT;
this.bounds.width = 1;
this.bounds.height = 1;
return this;
}
createRectangle(width: number, height: number): GeomSprite {
this.refresh();
this.rect = new Rectangle(this.x, this.y, width, height);
this.type = GeomSprite.RECTANGLE;
this.bounds.copyFrom(this.rect);
return this;
}
refresh() {
this.circle = null;
this.line = null;
this.point = null;
this.rect = null;
}
update() {
// Update bounds and position?
if (this.type == GeomSprite.UNASSIGNED)
{
return;
}
else if (this.type == GeomSprite.CIRCLE)
{
this.circle.x = this.x;
this.circle.y = this.y;
this.bounds.width = this.circle.diameter;
this.bounds.height = this.circle.diameter;
}
else if (this.type == GeomSprite.LINE)
{
this.line.x1 = this.x;
this.line.y1 = this.y;
this.bounds.setTo(this.x, this.y, this.line.width, this.line.height);
}
else if (this.type == GeomSprite.POINT)
{
this.point.x = this.x;
this.point.y = this.y;
}
else if (this.type == GeomSprite.RECTANGLE)
{
this.rect.x = this.x;
this.rect.y = this.y;
this.bounds.copyFrom(this.rect);
}
}
public inCamera(camera: Rectangle): bool {
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{
this._dx = this.bounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.bounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.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.overlap(this.bounds);
}
}
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool {
// Render checks
if (this.type == GeomSprite.UNASSIGNED || this.visible === false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1 || this.inCamera(camera.worldView) == false)
{
return false;
}
// Alpha
if (this.alpha !== 1)
{
var globalAlpha = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
}
this._dx = cameraOffsetX + (this.bounds.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
// Circles are drawn center based
if (this.type == GeomSprite.CIRCLE)
{
this._dx += this.circle.radius;
this._dy += this.circle.radius;
}
// 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 (misleading?)
if (this.angle !== 0)
{
this._game.stage.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y);
this._game.stage.context.rotate(this.angle * (Math.PI / 180));
this._dx = -(this._dw / 2);
this._dy = -(this._dh / 2);
}
this._dx = Math.round(this._dx);
this._dy = Math.round(this._dy);
this._dw = Math.round(this._dw);
this._dh = Math.round(this._dh);
this._game.stage.saveCanvasValues();
// Debug
this._game.stage.context.fillStyle = 'rgba(255,0,0,0.5)';
this._game.stage.context.fillRect(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height);
this._game.stage.context.lineWidth = this.lineWidth;
this._game.stage.context.strokeStyle = this.lineColor;
this._game.stage.context.fillStyle = this.fillColor;
if (this._game.stage.fillStyle !== this.fillColor)
{
}
// Primitive Renderer
if (this.type == GeomSprite.CIRCLE)
{
this._game.stage.context.beginPath();
this._game.stage.context.arc(this._dx, this._dy, this.circle.radius, 0, Math.PI * 2);
this._game.stage.context.stroke();
if (this.renderFill)
{
this._game.stage.context.fill();
}
this._game.stage.context.closePath();
}
else if (this.type == GeomSprite.LINE)
{
this._game.stage.context.beginPath();
this._game.stage.context.moveTo(this._dx, this._dy);
this._game.stage.context.lineTo(this.line.x2, this.line.y2);
this._game.stage.context.stroke();
this._game.stage.context.closePath();
}
else if (this.type == GeomSprite.POINT)
{
this._game.stage.context.fillRect(this._dx, this._dy, 2, 2);
}
else if (this.type == GeomSprite.RECTANGLE)
{
// We can use the faster fillRect if we don't need the outline
if (this.renderOutline == false)
{
this._game.stage.context.fillRect(this._dx, this._dy, this.rect.width, this.rect.height);
}
else
{
this._game.stage.context.beginPath();
this._game.stage.context.rect(this._dx, this._dy, this.rect.width, this.rect.height);
this._game.stage.context.stroke();
if (this.renderFill)
{
this._game.stage.context.fill();
}
this._game.stage.context.closePath();
}
}
this._game.stage.restoreCanvasValues();
if (this.rotation !== 0)
{
this._game.stage.context.translate(0, 0);
this._game.stage.context.restore();
}
if (globalAlpha > -1)
{
this._game.stage.context.globalAlpha = globalAlpha;
}
return true;
}
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
//this._game.stage.context.fillStyle = color;
//this._game.stage.context.fillText('Sprite: ' + this.name + ' (' + this.bounds.width + ' x ' + this.bounds.height + ')', x, y);
//this._game.stage.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
//this._game.stage.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
//this._game.stage.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
}
// Gives a basic boolean response to a geometric collision.
// If you need the details of the collision use the Collision functions instead and inspect the IntersectResult object.
public collide(source: GeomSprite): bool {
// Circle vs. Circle
if (this.type == GeomSprite.CIRCLE && source.type == GeomSprite.CIRCLE)
{
return Collision.circleToCircle(this.circle, source.circle).result;
}
// Circle vs. Rect
if (this.type == GeomSprite.CIRCLE && source.type == GeomSprite.RECTANGLE)
{
return Collision.circleToRectangle(this.circle, source.rect).result;
}
// Circle vs. Point
if (this.type == GeomSprite.CIRCLE && source.type == GeomSprite.POINT)
{
return Collision.circleContainsPoint(this.circle, source.point).result;
}
// Circle vs. Line
if (this.type == GeomSprite.CIRCLE && source.type == GeomSprite.LINE)
{
return Collision.lineToCircle(source.line, this.circle).result;
}
// Rect vs. Rect
if (this.type == GeomSprite.RECTANGLE && source.type == GeomSprite.RECTANGLE)
{
return Collision.rectangleToRectangle(this.rect, source.rect).result;
}
// Rect vs. Circle
if (this.type == GeomSprite.RECTANGLE && source.type == GeomSprite.CIRCLE)
{
return Collision.circleToRectangle(source.circle, this.rect).result;
}
// Rect vs. Point
if (this.type == GeomSprite.RECTANGLE && source.type == GeomSprite.POINT)
{
return Collision.pointToRectangle(source.point, this.rect).result;
}
// Rect vs. Line
if (this.type == GeomSprite.RECTANGLE && source.type == GeomSprite.LINE)
{
return Collision.lineToRectangle(source.line, this.rect).result;
}
// Point vs. Point
if (this.type == GeomSprite.POINT && source.type == GeomSprite.POINT)
{
return this.point.equals(source.point);
}
// Point vs. Circle
if (this.type == GeomSprite.POINT && source.type == GeomSprite.CIRCLE)
{
return Collision.circleContainsPoint(source.circle, this.point).result;
}
// Point vs. Rect
if (this.type == GeomSprite.POINT && source.type == GeomSprite.RECTANGLE)
{
return Collision.pointToRectangle(this.point, source.rect).result;
}
// Point vs. Line
if (this.type == GeomSprite.POINT && source.type == GeomSprite.LINE)
{
return source.line.isPointOnLine(this.point.x, this.point.y);
}
// Line vs. Line
if (this.type == GeomSprite.LINE && source.type == GeomSprite.LINE)
{
return Collision.lineSegmentToLineSegment(this.line, source.line).result;
}
// Line vs. Circle
if (this.type == GeomSprite.LINE && source.type == GeomSprite.LINE)
{
return Collision.lineToCircle(this.line, source.circle).result;
}
// Line vs. Rect
if (this.type == GeomSprite.LINE && source.type == GeomSprite.RECTANGLE)
{
return Collision.lineSegmentToRectangle(this.line, source.rect).result;
}
// Line vs. Point
if (this.type == GeomSprite.LINE && source.type == GeomSprite.LINE)
{
return this.line.isPointOnLine(source.point.x, source.point.y);
}
return false;
}
}
}
+115
View File
@@ -0,0 +1,115 @@
/// <reference path="../Game.ts" />
/// <reference path="Sprite.ts" />
/**
* This is a simple particle class that extends the default behavior
* of <code>Sprite</code> to have slightly more specialized behavior
* common to many game scenarios. You can override and extend this class
* just like you would <code>Sprite</code>. While <code>Emitter</code>
* used to work with just any old sprite, it now requires a
* <code>Particle</code> based class.
*
* @author Adam Atomic
* @author Richard Davey
*/
/**
* Phaser
*/
module Phaser {
export class Particle extends Sprite {
/**
* Instantiate a new particle. Like <code>Sprite</code>, all meaningful creation
* happens during <code>loadGraphic()</code> or <code>makeGraphic()</code> or whatever.
*/
constructor(game: Game) {
super(game);
this.lifespan = 0;
this.friction = 500;
}
/**
* How long this particle lives before it disappears.
* NOTE: this is a maximum, not a minimum; the object
* could get recycled before its lifespan is up.
*/
public lifespan: number;
/**
* Determines how quickly the particles come to rest on the ground.
* Only used if the particle has gravity-like acceleration applied.
* @default 500
*/
public friction: number;
/**
* The particle's main update logic. Basically it checks to see if it should
* be dead yet, and then has some special bounce behavior if there is some gravity on it.
*/
public update() {
//lifespan behavior
if (this.lifespan <= 0)
{
return;
}
this.lifespan -= this._game.time.elapsed;
if (this.lifespan <= 0)
{
this.kill();
}
//simpler bounce/spin behavior for now
if (this.touching)
{
if (this.angularVelocity != 0)
{
this.angularVelocity = -this.angularVelocity;
}
}
if (this.acceleration.y > 0) //special behavior for particles with gravity
{
if (this.touching & Collision.FLOOR)
{
this.drag.x = this.friction;
if (!(this.wasTouching & Collision.FLOOR))
{
if (this.velocity.y < -this.elasticity * 10)
{
if (this.angularVelocity != 0)
{
this.angularVelocity *= -this.elasticity;
}
}
else
{
this.velocity.y = 0;
this.angularVelocity = 0;
}
}
}
else
{
this.drag.x = 0;
}
}
}
/**
* Triggered whenever this object is launched by a <code>Emitter</code>.
* You can override this to add custom behavior like a sound or AI or something.
*/
public onEmit() {
}
}
}
+276
View File
@@ -0,0 +1,276 @@
/// <reference path="../Game.ts" />
/// <reference path="GameObject.ts" />
/**
* Phaser
*/
module Phaser {
export class Sprite extends GameObject {
constructor(game: Game, x?: number = 0, y?: number = 0, key?: string = null) {
super(game, x, y);
this._texture = null;
this.animations = new Animations(this._game, this);
if (key !== null)
{
this.loadGraphic(key);
}
else
{
this.bounds.width = 16;
this.bounds.height = 16;
}
}
private _texture;
private _canvas: HTMLCanvasElement;
private _context: CanvasRenderingContext2D;
private _dynamicTexture: bool = false;
public animations: Animations;
// local rendering related temp vars to help avoid gc spikes
private _sx: number = 0;
private _sy: number = 0;
private _sw: number = 0;
private _sh: number = 0;
private _dx: number = 0;
private _dy: number = 0;
private _dw: number = 0;
private _dh: number = 0;
public loadGraphic(key: string): Sprite {
if (this._game.cache.getImage(key) !== null)
{
if (this._game.cache.isSpriteSheet(key) == false)
{
this._texture = this._game.cache.getImage(key);
this.bounds.width = this._texture.width;
this.bounds.height = this._texture.height;
}
else
{
this._texture = this._game.cache.getImage(key);
this.animations.loadFrameData(this._game.cache.getFrameData(key));
}
this._dynamicTexture = false;
}
return this;
}
public loadDynamicTexture(texture: DynamicTexture): Sprite {
this._texture = texture;
this.bounds.width = this._texture.width;
this.bounds.height = this._texture.height;
this._dynamicTexture = true;
return this;
}
public makeGraphic(width: number, height: number, color: number = 0xffffffff): Sprite {
this._texture = null;
this.width = width;
this.height = height;
this._dynamicTexture = false;
return this;
}
public inCamera(camera: Rectangle): bool {
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{
this._dx = this.bounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.bounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.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.overlap(this.bounds);
}
}
public postUpdate() {
this.animations.update();
super.postUpdate();
}
public set frame(value?: number) {
this.animations.frame = value;
}
public get frame(): number {
return this.animations.frame;
}
public set frameName(value?: string) {
this.animations.frameName = value;
}
public get frameName(): string {
return this.animations.frameName;
}
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool {
// Render checks
if (this.visible === false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1 || this.inCamera(camera.worldView) == false)
{
return false;
}
// Alpha
if (this.alpha !== 1)
{
var globalAlpha = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
}
//if (this.flip === true)
//{
// this.context.save();
// this.context.translate(game.canvas.width, 0);
// this.context.scale(-1, 1);
//}
this._sx = 0;
this._sy = 0;
this._sw = this.bounds.width;
this._sh = this.bounds.height;
this._dx = cameraOffsetX + (this.bounds.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
if (this._dynamicTexture == false && this.animations.currentFrame !== null)
{
this._sx = this.animations.currentFrame.x;
this._sy = this.animations.currentFrame.y;
if (this.animations.currentFrame.trimmed)
{
this._dx += this.animations.currentFrame.spriteSourceSizeX;
this._dy += this.animations.currentFrame.spriteSourceSizeY;
}
}
// 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
if (this.angle !== 0)
{
this._game.stage.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y);
this._game.stage.context.rotate(this.angle * (Math.PI / 180));
this._dx = -(this._dw / 2);
this._dy = -(this._dh / 2);
}
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);
// Debug test
//this._game.stage.context.fillStyle = 'rgba(255,0,0,0.3)';
//this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh);
if (this._texture != null)
{
if (this._dynamicTexture)
{
this._game.stage.context.drawImage(
this._texture.canvas, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
this._sw, // Source Width
this._sh, // Source Height
this._dx, // Destination X (where on the canvas it'll be drawn)
this._dy, // Destination Y
this._dw, // Destination Width (always same as Source Width unless scaled)
this._dh // Destination Height (always same as Source Height unless scaled)
);
}
else
{
this._game.stage.context.drawImage(
this._texture, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
this._sw, // Source Width
this._sh, // Source Height
this._dx, // Destination X (where on the canvas it'll be drawn)
this._dy, // Destination Y
this._dw, // Destination Width (always same as Source Width unless scaled)
this._dh // Destination Height (always same as Source Height unless scaled)
);
}
}
else
{
this._game.stage.context.fillStyle = 'rgb(255,255,255)';
this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh);
}
//if (this.flip === true || this.rotation !== 0)
if (this.rotation !== 0)
{
this._game.stage.context.translate(0, 0);
this._game.stage.context.restore();
}
if (globalAlpha > -1)
{
this._game.stage.context.globalAlpha = globalAlpha;
}
return true;
}
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
this._game.stage.context.fillStyle = color;
this._game.stage.context.fillText('Sprite: ' + this.name + ' (' + this.bounds.width + ' x ' + this.bounds.height + ')', x, y);
this._game.stage.context.fillText('x: ' + this.bounds.x.toFixed(1) + ' y: ' + this.bounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
this._game.stage.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
this._game.stage.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
}
}
}
+268
View File
@@ -0,0 +1,268 @@
/// <reference path="../Game.ts" />
/// <reference path="GameObject.ts" />
/// <reference path="../system/Tile.ts" />
/// <reference path="../system/TilemapBuffer.ts" />
/**
* Phaser
*/
module Phaser {
export class Tilemap extends GameObject {
constructor(game: Game, key: string, mapData: string, format: number, tileWidth?: number = 0, tileHeight?: number = 0) {
super(game);
this._texture = this._game.cache.getImage(key);
this._tilemapBuffers = [];
this.isGroup = false;
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
this.boundsInTiles = new Rectangle();
this.mapFormat = format;
switch (format)
{
case Tilemap.FORMAT_CSV:
this.parseCSV(game.cache.getText(mapData));
break;
case Tilemap.FORMAT_TILED_JSON:
this.parseTiledJSON(game.cache.getText(mapData));
break;
}
this.parseTileOffsets();
this.createTilemapBuffers();
}
private _texture;
private _tileOffsets;
private _tilemapBuffers: TilemapBuffer[];
private _dx: number = 0;
private _dy: number = 0;
public static FORMAT_CSV: number = 0;
public static FORMAT_TILED_JSON: number = 1;
public mapData;
public mapFormat: number;
public boundsInTiles: Rectangle;
public tileWidth: number;
public tileHeight: number;
public widthInTiles: number = 0;
public heightInTiles: number = 0;
public widthInPixels: number = 0;
public heightInPixels: number = 0;
// How many extra tiles to draw around the edge of the screen (for fast scrolling games, or to optimise mobile performance try increasing this)
// The number is the amount of extra tiles PER SIDE, so a value of 10 would be (10 tiles + screen size + 10 tiles)
public tileBoundary: number = 10;
private parseCSV(data: string) {
//console.log('parseMapData');
this.mapData = [];
// Trim any rogue whitespace from the data
data = data.trim();
var rows = data.split("\n");
//console.log('rows', rows);
for (var i = 0; i < rows.length; i++)
{
var column = rows[i].split(",");
//console.log('column', column);
var output = [];
if (column.length > 0)
{
// Set the width based on the first row
if (this.widthInTiles == 0)
{
// Maybe -1?
this.widthInTiles = column.length;
}
// We have a new row of tiles
this.heightInTiles++;
// Parse it
for (var c = 0; c < column.length; c++)
{
output[c] = parseInt(column[c]);
}
this.mapData.push(output);
}
}
//console.log('final map array');
//console.log(this.mapData);
if (this.widthInTiles > 0)
{
this.widthInPixels = this.tileWidth * this.widthInTiles;
}
if (this.heightInTiles > 0)
{
this.heightInPixels = this.tileHeight * this.heightInTiles;
}
this.boundsInTiles.setTo(0, 0, this.widthInTiles, this.heightInTiles);
}
private parseTiledJSON(data: string) {
//console.log('parseTiledJSON');
this.mapData = [];
// Trim any rogue whitespace from the data
data = data.trim();
// We ought to change this soon, so we have layer support, but for now let's just get it working
var json = JSON.parse(data);
// Right now we assume no errors at all with the parsing (safe I know)
this.tileWidth = json.tilewidth;
this.tileHeight = json.tileheight;
// Parse the first layer only
this.widthInTiles = json.layers[0].width;
this.heightInTiles = json.layers[0].height;
this.widthInPixels = this.widthInTiles * this.tileWidth;
this.heightInPixels = this.heightInTiles * this.tileHeight;
this.boundsInTiles.setTo(0, 0, this.widthInTiles, this.heightInTiles);
//console.log('width in tiles', this.widthInTiles);
//console.log('height in tiles', this.heightInTiles);
//console.log('width in px', this.widthInPixels);
//console.log('height in px', this.heightInPixels);
// Now let's get the data
var c = 0;
var row;
for (var i = 0; i < json.layers[0].data.length; i++)
{
if (c == 0)
{
row = [];
}
row.push(json.layers[0].data[i]);
c++;
if (c == this.widthInTiles)
{
this.mapData.push(row);
c = 0;
}
}
//console.log('mapData');
//console.log(this.mapData);
}
public getMapSegment(area: Rectangle) {
}
private createTilemapBuffers() {
var cams = this._game.world.getAllCameras();
for (var i = 0; i < cams.length; i++)
{
this._tilemapBuffers[cams[i].ID] = new TilemapBuffer(this._game, cams[i], this, this._texture, this._tileOffsets);
}
}
private parseTileOffsets() {
this._tileOffsets = [];
var i = 0;
if (this.mapFormat == Tilemap.FORMAT_TILED_JSON)
{
// For some reason Tiled counts from 1 not 0
this._tileOffsets[0] = null;
i = 1;
}
for (var ty = 0; ty < this._texture.height; ty += this.tileHeight)
{
for (var tx = 0; tx < this._texture.width; tx += this.tileWidth)
{
this._tileOffsets[i] = { x: tx, y: ty };
i++;
}
}
}
/*
// Use a Signal?
public addTilemapBuffers(camera:Camera) {
console.log('added new camera to tilemap');
this._tilemapBuffers[camera.ID] = new TilemapBuffer(this._game, camera, this, this._texture, this._tileOffsets);
}
*/
public update() {
// Check if any of the cameras have scrolled far enough for us to need to refresh a TilemapBuffer
this._tilemapBuffers[0].update();
}
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
this._tilemapBuffers[0].renderDebugInfo(x, y, color);
}
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number): bool {
if (this.visible === false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1)
{
return false;
}
this._dx = cameraOffsetX + (this.bounds.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.y - camera.worldView.y);
this._dx = Math.round(this._dx);
this._dy = Math.round(this._dy);
if (this._tilemapBuffers[camera.ID])
{
//this._tilemapBuffers[camera.ID].render(this._dx, this._dy);
this._tilemapBuffers[camera.ID].render(cameraOffsetX, cameraOffsetY);
}
return true;
}
}
}