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

View file

@ -1,145 +1,167 @@
/// <reference path="Cache.ts" />
/// <reference path="Game.ts" />
/// <reference path="Sprite.ts" />
/// <reference path="gameobjects/Sprite.ts" />
/// <reference path="system/animation/Animation.ts" />
/// <reference path="system/animation/AnimationLoader.ts" />
/// <reference path="system/animation/Frame.ts" />
/// <reference path="system/animation/FrameData.ts" />
class Animations {
module Phaser {
constructor(game: Game, parent: Sprite) {
export class Animations {
this._game = game;
this._parent = parent;
this._anims = {};
constructor(game: Game, parent: Sprite) {
}
this._game = game;
this._parent = parent;
this._anims = {};
private _game: Game;
private _parent: Sprite;
private _anims: {};
private _frameIndex: number;
private _frameData: FrameData = null;
public currentAnim: Animation;
public currentFrame: Frame = null;
public loadFrameData(frameData: FrameData) {
this._frameData = frameData;
this.frame = 0;
}
public add(name: string, frames:number[] = null, frameRate: number = 60, loop: bool = false) {
if (this._frameData == null)
{
return;
}
if (frames == null)
{
frames = this._frameData.getFrameIndexes();
private _game: Game;
private _parent: Sprite;
private _anims: {};
private _frameIndex: number;
private _frameData: FrameData = null;
public currentAnim: Animation;
public currentFrame: Frame = null;
public loadFrameData(frameData: FrameData) {
this._frameData = frameData;
this.frame = 0;
}
else
{
if (this.validateFrames(frames) == false)
public add(name: string, frames: any[] = null, frameRate: number = 60, loop: bool = false, useNumericIndex: bool = true) {
if (this._frameData == null)
{
return;
}
}
this._anims[name] = new Animation(this._game, this._parent, this._frameData, name, frames, frameRate, loop);
this.currentAnim = this._anims[name];
}
private validateFrames(frames:number[]):bool {
var result = true;
for (var i = 0; i < frames.length; i++)
{
if (frames[i] > this._frameData.total)
if (frames == null)
{
return false;
frames = this._frameData.getFrameIndexes();
}
else
{
if (this.validateFrames(frames, useNumericIndex) == false)
{
return;
}
}
}
}
if (useNumericIndex == false)
{
frames = this._frameData.getFrameIndexesByName(frames);
}
public play(name: string, frameRate?: number = null, loop?: bool) {
this._anims[name] = new Animation(this._game, this._parent, this._frameData, name, frames, frameRate, loop);
if (this._anims[name])
{
this.currentAnim = this._anims[name];
this.currentAnim.play(frameRate, loop);
}
}
public stop(name: string) {
private validateFrames(frames: any[], useNumericIndex: bool): bool {
for (var i = 0; i < frames.length; i++)
{
if (useNumericIndex == true)
{
if (frames[i] > this._frameData.total)
{
return false;
}
}
else
{
if (this._frameData.checkFrameName(frames[i]) == false)
{
return false;
}
}
}
return true;
if (this._anims[name])
{
this.currentAnim = this._anims[name];
this.currentAnim.stop();
}
}
public update() {
public play(name: string, frameRate?: number = null, loop?: bool) {
if (this._anims[name])
{
this.currentAnim = this._anims[name];
this.currentAnim.play(frameRate, loop);
}
}
public stop(name: string) {
if (this._anims[name])
{
this.currentAnim = this._anims[name];
this.currentAnim.stop();
}
}
public update() {
if (this.currentAnim && this.currentAnim.update() == true)
{
this.currentFrame = this.currentAnim.currentFrame;
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
}
}
public get frameData(): FrameData {
return this._frameData;
}
public get frameTotal(): number {
return this._frameData.total;
}
public get frame(): number {
return this._frameIndex;
}
public set frame(value: number) {
this.currentFrame = this._frameData.getFrame(value);
if (this.currentFrame !== null)
{
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._frameIndex = value;
}
}
public get frameName(): string {
return this.currentFrame.name;
}
public set frameName(value: string) {
this.currentFrame = this._frameData.getFrameByName(value);
if (this.currentFrame !== null)
{
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._frameIndex = this.currentFrame.index;
}
if (this.currentAnim && this.currentAnim.update() == true)
{
this.currentFrame = this.currentAnim.currentFrame;
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
}
}
public get frameTotal(): number {
return this._frameData.total;
}
public get frame(): number {
return this._frameIndex;
}
public set frame(value: number) {
this.currentFrame = this._frameData.getFrame(value);
if (this.currentFrame !== null)
{
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._frameIndex = value;
}
}
public get frameName(): string {
return this.currentFrame.name;
}
public set frameName(value: string) {
this.currentFrame = this._frameData.getFrameByName(value);
if (this.currentFrame !== null)
{
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._frameIndex = this.currentFrame.index;
}
}
}
}

View file

@ -9,130 +9,136 @@
* @author Richard Davey
*/
class Basic {
/**
* Phaser
*/
/**
* Instantiate the basic object.
*/
constructor(game:Game) {
module Phaser {
this._game = game;
this.ID = -1;
this.exists = true;
this.active = true;
this.visible = true;
this.alive = true;
this.isGroup = false;
this.ignoreDrawDebug = false;
export class Basic {
/**
* Instantiate the basic object.
*/
constructor(game: Game) {
this._game = game;
this.ID = -1;
this.exists = true;
this.active = true;
this.visible = true;
this.alive = true;
this.isGroup = false;
this.ignoreDrawDebug = false;
}
/**
* The essential reference to the main game object
*/
public _game: Game;
/**
* Allows you to give this object a name. Useful for debugging, but not actually used internally.
*/
public name: string = '';
/**
* IDs seem like they could be pretty useful, huh?
* They're not actually used for anything yet though.
*/
public ID: number;
/**
* A boolean to store if this object is a Group or not.
* Saves us an expensive typeof check inside of core loops.
*/
public isGroup: bool;
/**
* Controls whether <code>update()</code> and <code>draw()</code> are automatically called by FlxState/FlxGroup.
*/
public exists: bool;
/**
* Controls whether <code>update()</code> is automatically called by FlxState/FlxGroup.
*/
public active: bool;
/**
* Controls whether <code>draw()</code> is automatically called by FlxState/FlxGroup.
*/
public visible: bool;
/**
* Useful state for many game objects - "dead" (!alive) vs alive.
* <code>kill()</code> and <code>revive()</code> both flip this switch (along with exists, but you can override that).
*/
public alive: bool;
/**
* Setting this to true will prevent the object from appearing
* when the visual debug mode in the debugger overlay is toggled on.
*/
public ignoreDrawDebug: bool;
/**
* Override this to null out iables or manually call
* <code>destroy()</code> on class members if necessary.
* Don't forget to call <code>super.destroy()</code>!
*/
public destroy() { }
/**
* Pre-update is called right before <code>update()</code> on each object in the game loop.
*/
public preUpdate() {
}
/**
* Override this to update your class's position and appearance.
* This is where most of your game rules and behavioral code will go.
*/
public update() {
}
/**
* Post-update is called right after <code>update()</code> on each object in the game loop.
*/
public postUpdate() {
}
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
}
/**
* Handy for "killing" game objects.
* Default behavior is to flag them as nonexistent AND dead.
* However, if you want the "corpse" to remain in the game,
* like to animate an effect or whatever, you should override this,
* setting only alive to false, and leaving exists true.
*/
public kill() {
this.alive = false;
this.exists = false;
}
/**
* Handy for bringing game objects "back to life". Just sets alive and exists back to true.
* In practice, this is most often called by <code>FlxObject.reset()</code>.
*/
public revive() {
this.alive = true;
this.exists = true;
}
/**
* Convert object to readable string name. Useful for debugging, save games, etc.
*/
public toString(): string {
return "";
}
}
/**
* The essential reference to the main game object
*/
public _game: Game;
/**
* Allows you to give this object a name. Useful for debugging, but not actually used internally.
*/
public name: string = '';
/**
* IDs seem like they could be pretty useful, huh?
* They're not actually used for anything yet though.
*/
public ID: number;
/**
* A boolean to store if this object is a Group or not.
* Saves us an expensive typeof check inside of core loops.
*/
public isGroup: bool;
/**
* Controls whether <code>update()</code> and <code>draw()</code> are automatically called by FlxState/FlxGroup.
*/
public exists: bool;
/**
* Controls whether <code>update()</code> is automatically called by FlxState/FlxGroup.
*/
public active: bool;
/**
* Controls whether <code>draw()</code> is automatically called by FlxState/FlxGroup.
*/
public visible: bool;
/**
* Useful state for many game objects - "dead" (!alive) vs alive.
* <code>kill()</code> and <code>revive()</code> both flip this switch (along with exists, but you can override that).
*/
public alive: bool;
/**
* Setting this to true will prevent the object from appearing
* when the visual debug mode in the debugger overlay is toggled on.
*/
public ignoreDrawDebug: bool;
/**
* Override this to null out iables or manually call
* <code>destroy()</code> on class members if necessary.
* Don't forget to call <code>super.destroy()</code>!
*/
public destroy() { }
/**
* Pre-update is called right before <code>update()</code> on each object in the game loop.
*/
public preUpdate() {
}
/**
* Override this to update your class's position and appearance.
* This is where most of your game rules and behavioral code will go.
*/
public update() {
}
/**
* Post-update is called right after <code>update()</code> on each object in the game loop.
*/
public postUpdate() {
}
public render(camera:Camera, cameraOffsetX: number, cameraOffsetY: number) {
}
/**
* Handy for "killing" game objects.
* Default behavior is to flag them as nonexistent AND dead.
* However, if you want the "corpse" to remain in the game,
* like to animate an effect or whatever, you should override this,
* setting only alive to false, and leaving exists true.
*/
public kill() {
this.alive = false;
this.exists = false;
}
/**
* Handy for bringing game objects "back to life". Just sets alive and exists back to true.
* In practice, this is most often called by <code>FlxObject.reset()</code>.
*/
public revive() {
this.alive = true;
this.exists = true;
}
/**
* Convert object to readable string name. Useful for debugging, save games, etc.
*/
public toString(): string {
//return FlxU.getClassName(this, true);
return "";
}
}
}

View file

@ -1,163 +1,171 @@
/// <reference path="system/animation/AnimationLoader.ts" />
/// <reference path="Game.ts" />
class Cache {
/**
* Phaser
*/
constructor(game: Game) {
module Phaser {
this._game = game;
export class Cache {
this._canvases = {};
this._images = {};
this._sounds = {};
this._text = {};
constructor(game: Game) {
}
this._game = game;
private _game: Game;
private _canvases;
private _images;
private _sounds;
private _text;
this._canvases = {};
this._images = {};
this._sounds = {};
this._text = {};
public addCanvas(key: string, canvas:HTMLCanvasElement, context:CanvasRenderingContext2D) {
this._canvases[key] = { canvas: canvas, context: context };
}
public addSpriteSheet(key: string, url:string, data, frameWidth:number, frameHeight:number, frameMax:number) {
this._images[key] = { url: url, data: data, spriteSheet: true, frameWidth: frameWidth, frameHeight: frameHeight };
this._images[key].frameData = AnimationLoader.parseSpriteSheet(this._game, key, frameWidth, frameHeight, frameMax);
}
public addTextureAtlas(key: string, url:string, data, jsonData) {
this._images[key] = { url: url, data: data, spriteSheet: true };
this._images[key].frameData = AnimationLoader.parseJSONData(this._game, jsonData);
}
public addImage(key: string, url:string, data) {
this._images[key] = { url: url, data: data, spriteSheet: false };
}
public addSound(key: string, url:string, data) {
this._sounds[key] = { url: url, data: data, decoded: false };
}
public decodedSound(key: string, data) {
this._sounds[key].data = data;
this._sounds[key].decoded = true;
}
public addText(key: string, url:string, data) {
this._text[key] = { url: url, data: data };
}
public getCanvas(key: string) {
if (this._canvases[key])
{
return this._canvases[key].canvas;
}
return null;
private _game: Game;
}
private _canvases;
private _images;
private _sounds;
private _text;
public getImage(key: string) {
public addCanvas(key: string, canvas: HTMLCanvasElement, context: CanvasRenderingContext2D) {
this._canvases[key] = { canvas: canvas, context: context };
if (this._images[key])
{
return this._images[key].data;
}
return null;
public addSpriteSheet(key: string, url: string, data, frameWidth: number, frameHeight: number, frameMax: number) {
}
this._images[key] = { url: url, data: data, spriteSheet: true, frameWidth: frameWidth, frameHeight: frameHeight };
this._images[key].frameData = AnimationLoader.parseSpriteSheet(this._game, key, frameWidth, frameHeight, frameMax);
public getFrameData(key: string):FrameData {
if (this._images[key] && this._images[key].spriteSheet == true)
{
return this._images[key].frameData;
}
return null;
public addTextureAtlas(key: string, url: string, data, jsonData) {
}
this._images[key] = { url: url, data: data, spriteSheet: true };
this._images[key].frameData = AnimationLoader.parseJSONData(this._game, jsonData);
public getSound(key: string) {
if (this._sounds[key])
{
return this._sounds[key].data;
}
return null;
public addImage(key: string, url: string, data) {
}
this._images[key] = { url: url, data: data, spriteSheet: false };
public isSoundDecoded(key: string): bool {
if (this._sounds[key])
{
return this._sounds[key].decoded;
}
}
public addSound(key: string, url: string, data) {
public isSpriteSheet(key: string): bool {
this._sounds[key] = { url: url, data: data, decoded: false };
if (this._images[key])
{
return this._images[key].spriteSheet;
}
}
public decodedSound(key: string, data) {
public getText(key: string) {
this._sounds[key].data = data;
this._sounds[key].decoded = true;
if (this._text[key])
{
return this._text[key].data;
}
return null;
public addText(key: string, url: string, data) {
}
this._text[key] = { url: url, data: data };
public destroy() {
for (var item in this._canvases)
{
delete this._canvases[item['key']];
}
for (var item in this._images)
{
delete this._images[item['key']];
public getCanvas(key: string) {
if (this._canvases[key])
{
return this._canvases[key].canvas;
}
return null;
}
for (var item in this._sounds)
{
delete this._sounds[item['key']];
public getImage(key: string) {
if (this._images[key])
{
return this._images[key].data;
}
return null;
}
for (var item in this._text)
{
delete this._text[item['key']];
public getFrameData(key: string): FrameData {
if (this._images[key] && this._images[key].spriteSheet == true)
{
return this._images[key].frameData;
}
return null;
}
public getSound(key: string) {
if (this._sounds[key])
{
return this._sounds[key].data;
}
return null;
}
public isSoundDecoded(key: string): bool {
if (this._sounds[key])
{
return this._sounds[key].decoded;
}
}
public isSpriteSheet(key: string): bool {
if (this._images[key])
{
return this._images[key].spriteSheet;
}
}
public getText(key: string) {
if (this._text[key])
{
return this._text[key].data;
}
return null;
}
public destroy() {
for (var item in this._canvases)
{
delete this._canvases[item['key']];
}
for (var item in this._images)
{
delete this._images[item['key']];
}
for (var item in this._sounds)
{
delete this._sounds[item['key']];
}
for (var item in this._text)
{
delete this._text[item['key']];
}
}
}

View file

@ -1,79 +1,83 @@
/// <reference path="Game.ts" />
/// <reference path="GameMath.ts" />
/// <reference path="geom/Rectangle.ts" />
/// <reference path="geom/Point.ts" />
/// <reference path="system/Camera.ts" />
// TODO: If the Camera is larger than the Stage size then the rotation offset isn't correct
// TODO: Texture Repeat doesn't scroll, because it's part of the camera not the world, need to think about this more
class Cameras {
/**
* Phaser
*/
constructor(game: Game, x: number, y: number, width: number, height: number) {
module Phaser {
this._game = game;
export class Cameras {
this._cameras = [];
constructor(game: Game, x: number, y: number, width: number, height: number) {
this.current = this.addCamera(x, y, width, height);
this._game = game;
}
this._cameras = [];
private _game: Game;
this.current = this.addCamera(x, y, width, height);
private _cameras: Camera[];
}
public current: Camera;
private _game: Game;
public getAll(): Camera[] {
return this._cameras;
}
private _cameras: Camera[];
public update() {
this._cameras.forEach((camera) => camera.update());
}
public current: Camera;
public render() {
this._cameras.forEach((camera) => camera.render());
}
public getAll(): Camera[] {
return this._cameras;
}
public addCamera(x: number, y: number, width: number, height: number): Camera {
public update() {
this._cameras.forEach((camera) => camera.update());
}
var newCam: Camera = new Camera(this._game, this._cameras.length, x, y, width, height);
public render() {
this._cameras.forEach((camera) => camera.render());
}
this._cameras.push(newCam);
public addCamera(x: number, y: number, width: number, height: number): Camera {
return newCam;
var newCam: Camera = new Camera(this._game, this._cameras.length, x, y, width, height);
}
this._cameras.push(newCam);
public removeCamera(id: number): bool {
return newCam;
if (this._cameras[id])
{
if (this.current === this._cameras[id])
}
public removeCamera(id: number): bool {
if (this._cameras[id])
{
this.current = null;
if (this.current === this._cameras[id])
{
this.current = null;
}
this._cameras.splice(id, 1);
return true;
}
else
{
return false;
}
this._cameras.splice(id, 1);
return true;
}
else
{
return false;
public destroy() {
this._cameras.length = 0;
this.current = this.addCamera(0, 0, this._game.stage.width, this._game.stage.height);
}
}
public destroy() {
this._cameras.length = 0;
this.current = this.addCamera(0, 0, this._game.stage.width, this._game.stage.height);
}
}
}

891
Phaser/Collision.ts Normal file
View file

@ -0,0 +1,891 @@
/// <reference path="Game.ts" />
/// <reference path="geom/Point.ts" />
/// <reference path="geom/Rectangle.ts" />
/// <reference path="geom/Circle.ts" />
/// <reference path="geom/Line.ts" />
/// <reference path="geom/IntersectResult.ts" />
/// <reference path="system/QuadTree.ts" />
/**
* Phaser - Collision
*/
module Phaser {
export class Collision {
constructor(game: Game) {
this._game = game;
}
private _game: Game;
public static LEFT: number = 0x0001;
public static RIGHT: number = 0x0010;
public static UP: number = 0x0100;
public static DOWN: number = 0x1000;
public static NONE: number = 0;
public static CEILING: number = Collision.UP;
public static FLOOR: number = Collision.DOWN;
public static WALL: number = Collision.LEFT | Collision.RIGHT;
public static ANY: number = Collision.LEFT | Collision.RIGHT | Collision.UP | Collision.DOWN;
public static OVERLAP_BIAS: number = 4;
/**
* -------------------------------------------------------------------------------------------
* Lines
* -------------------------------------------------------------------------------------------
**/
/**
* Check if the two given Line objects intersect
* @method lineToLine
* @param {Phaser.Line} The first line object to check
* @param {Phaser.Line} The second line object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
**/
public static lineToLine(line1: Line, line2: Line, output?: IntersectResult = new IntersectResult): IntersectResult {
var denom = (line1.x1 - line1.x2) * (line2.y1 - line2.y2) - (line1.y1 - line1.y2) * (line2.x1 - line2.x2);
if (denom !== 0)
{
output.result = true;
output.x = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (line2.x1 - line2.x2) - (line1.x1 - line1.x2) * (line2.x1 * line2.y2 - line2.y1 * line2.x2)) / denom;
output.y = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (line2.y1 - line2.y2) - (line1.y1 - line1.y2) * (line2.x1 * line2.y2 - line2.y1 * line2.x2)) / denom;
}
return output;
}
/**
* Check if the Line and Line Segment intersects
* @method lineToLineSegment
* @param {Phaser.Line} The line object to check
* @param {Phaser.Line} The line segment object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
**/
public static lineToLineSegment(line1: Line, seg: Line, output?: IntersectResult = new IntersectResult): IntersectResult {
var denom = (line1.x1 - line1.x2) * (seg.y1 - seg.y2) - (line1.y1 - line1.y2) * (seg.x1 - seg.x2);
if (denom !== 0)
{
output.x = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (seg.x1 - seg.x2) - (line1.x1 - line1.x2) * (seg.x1 * seg.y2 - seg.y1 * seg.x2)) / denom;
output.y = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (seg.y1 - seg.y2) - (line1.y1 - line1.y2) * (seg.x1 * seg.y2 - seg.y1 * seg.x2)) / denom;
var maxX = Math.max(seg.x1, seg.x2);
var minX = Math.min(seg.x1, seg.x2);
var maxY = Math.max(seg.y1, seg.y2);
var minY = Math.min(seg.y1, seg.y2);
//if (!(output.x <= maxX && output.x >= minX) || !(output.y <= maxY && output.y >= minY))
if ((output.x <= maxX && output.x >= minX) === true || (output.y <= maxY && output.y >= minY) === true)
{
output.result = true;
}
}
return output;
}
/**
* Check if the Line and Line Segment intersects
* @method lineToLineSegment
* @param {Phaser.Line} The line object to check
* @param {number} The x1 value
* @param {number} The y1 value
* @param {number} The x2 value
* @param {number} The y2 value
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
**/
public static lineToRawSegment(line: Line, x1: number, y1: number, x2: number, y2: number, output?: IntersectResult = new IntersectResult): IntersectResult {
var denom = (line.x1 - line.x2) * (y1 - y2) - (line.y1 - line.y2) * (x1 - x2);
if (denom !== 0)
{
output.x = ((line.x1 * line.y2 - line.y1 * line.x2) * (x1 - x2) - (line.x1 - line.x2) * (x1 * y2 - y1 * x2)) / denom;
output.y = ((line.x1 * line.y2 - line.y1 * line.x2) * (y1 - y2) - (line.y1 - line.y2) * (x1 * y2 - y1 * x2)) / denom;
var maxX = Math.max(x1, x2);
var minX = Math.min(x1, x2);
var maxY = Math.max(y1, y2);
var minY = Math.min(y1, y2);
if ((output.x <= maxX && output.x >= minX) === true || (output.y <= maxY && output.y >= minY) === true)
{
output.result = true;
}
}
return output;
}
/**
* Check if the Line and Ray intersects
* @method lineToRay
* @param {Phaser.Line} The Line object to check
* @param {Phaser.Line} The Ray object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
**/
public static lineToRay(line1: Line, ray: Line, output?: IntersectResult = new IntersectResult): IntersectResult {
var denom = (line1.x1 - line1.x2) * (ray.y1 - ray.y2) - (line1.y1 - line1.y2) * (ray.x1 - ray.x2);
if (denom !== 0)
{
output.x = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (ray.x1 - ray.x2) - (line1.x1 - line1.x2) * (ray.x1 * ray.y2 - ray.y1 * ray.x2)) / denom;
output.y = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (ray.y1 - ray.y2) - (line1.y1 - line1.y2) * (ray.x1 * ray.y2 - ray.y1 * ray.x2)) / denom;
output.result = true; // true unless either of the 2 following conditions are met
if (!(ray.x1 >= ray.x2) && output.x < ray.x1)
{
output.result = false;
}
if (!(ray.y1 >= ray.y2) && output.y < ray.y1)
{
output.result = false;
}
}
return output;
}
/**
* Check if the Line and Circle intersects
* @method lineToCircle
* @param {Phaser.Line} The Line object to check
* @param {Phaser.Circle} The Circle object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection
**/
public static lineToCircle(line: Line, circle: Circle, output?: IntersectResult = new IntersectResult): IntersectResult {
// Get a perpendicular line running to the center of the circle
if (line.perp(circle.x, circle.y).length <= circle.radius)
{
output.result = true;
}
return output;
}
/**
* Check if the Line intersects each side of the Rectangle
* @method lineToRectangle
* @param {Phaser.Line} The Line object to check
* @param {Phaser.Rectangle} The Rectangle object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection
**/
public static lineToRectangle(line: Line, rect: Rectangle, output?: IntersectResult = new IntersectResult): IntersectResult {
// Top of the Rectangle vs the Line
this.lineToRawSegment(line, rect.x, rect.y, rect.right, rect.y, output);
if (output.result === true)
{
return output;
}
// Left of the Rectangle vs the Line
this.lineToRawSegment(line, rect.x, rect.y, rect.x, rect.bottom, output);
if (output.result === true)
{
return output;
}
// Bottom of the Rectangle vs the Line
this.lineToRawSegment(line, rect.x, rect.bottom, rect.right, rect.bottom, output);
if (output.result === true)
{
return output;
}
// Right of the Rectangle vs the Line
this.lineToRawSegment(line, rect.right, rect.y, rect.right, rect.bottom, output);
return output;
}
/**
* -------------------------------------------------------------------------------------------
* Line Segment
* -------------------------------------------------------------------------------------------
**/
/**
* Check if Line1 intersects with Line2
* @method lineSegmentToLineSegment
* @param {Phaser.Line} The first line object to check
* @param {Phaser.Line} The second line object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
**/
public static lineSegmentToLineSegment(line1: Line, line2: Line, output?: IntersectResult = new IntersectResult): IntersectResult {
this.lineToLineSegment(line1, line2, output);
if (output.result === true)
{
if (!(output.x >= Math.min(line1.x1, line1.x2) && output.x <= Math.max(line1.x1, line1.x2)
&& output.y >= Math.min(line1.y1, line1.y2) && output.y <= Math.max(line1.y1, line1.y2)))
{
output.result = false;
}
}
return output;
}
/**
* Check if the Line Segment intersects with the Ray
* @method lineSegmentToRay
* @param {Phaser.Line} The Line object to check
* @param {Phaser.Line} The Line Ray object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
**/
public static lineSegmentToRay(line1: Line, ray: Line, output?: IntersectResult = new IntersectResult): IntersectResult {
this.lineToRay(line1, ray, output);
if (output.result === true)
{
if (!(output.x >= Math.min(line1.x1, line1.x2) && output.x <= Math.max(line1.x1, line1.x2)
&& output.y >= Math.min(line1.y1, line1.y2) && output.y <= Math.max(line1.y1, line1.y2)))
{
output.result = false;
}
}
return output;
}
/**
* Check if the Line Segment intersects with the Circle
* @method lineSegmentToCircle
* @param {Phaser.Line} The Line object to check
* @param {Phaser.Circle} The Circle object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
**/
public static lineSegmentToCircle(seg: Line, circle: Circle, output?: IntersectResult = new IntersectResult): IntersectResult {
var perp = seg.perp(circle.x, circle.y);
if (perp.length <= circle.radius)
{
// Line intersects circle - check if segment does
var maxX = Math.max(seg.x1, seg.x2);
var minX = Math.min(seg.x1, seg.x2);
var maxY = Math.max(seg.y1, seg.y2);
var minY = Math.min(seg.y1, seg.y2);
if ((perp.x2 <= maxX && perp.x2 >= minX) && (perp.y2 <= maxY && perp.y2 >= minY))
{
output.result = true;
}
else
{
// Worst case - segment doesn't traverse center, so no perpendicular connection.
if (this.circleContainsPoint(circle, <Point> { x: seg.x1, y: seg.y1 }) || this.circleContainsPoint(circle, <Point> { x: seg.x2, y: seg.y2 }))
{
output.result = true;
}
}
}
return output;
}
/**
* Check if the Line Segment intersects with the Rectangle
* @method lineSegmentToCircle
* @param {Phaser.Line} The Line object to check
* @param {Phaser.Circle} The Circle object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
**/
public static lineSegmentToRectangle(seg: Line, rect: Rectangle, output?: IntersectResult = new IntersectResult): IntersectResult {
if (rect.contains(seg.x1, seg.y1) && rect.contains(seg.x2, seg.y2))
{
output.result = true;
}
else
{
// Top of the Rectangle vs the Line
this.lineToRawSegment(seg, rect.x, rect.y, rect.right, rect.bottom, output);
if (output.result === true)
{
return output;
}
// Left of the Rectangle vs the Line
this.lineToRawSegment(seg, rect.x, rect.y, rect.x, rect.bottom, output);
if (output.result === true)
{
return output;
}
// Bottom of the Rectangle vs the Line
this.lineToRawSegment(seg, rect.x, rect.bottom, rect.right, rect.bottom, output);
if (output.result === true)
{
return output;
}
// Right of the Rectangle vs the Line
this.lineToRawSegment(seg, rect.right, rect.y, rect.right, rect.bottom, output);
return output;
}
return output;
}
/**
* -------------------------------------------------------------------------------------------
* Ray
* -------------------------------------------------------------------------------------------
**/
/**
* Check if the two given Circle objects intersect
* @method circleToCircle
* @param {Phaser.Circle} The first circle object to check
* @param {Phaser.Circle} The second circle object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection
**/
public static rayToRectangle(ray: Line, rect: Rectangle, output?: IntersectResult = new IntersectResult): IntersectResult {
// Currently just finds first intersection - might not be closest to ray pt1
this.lineToRectangle(ray, rect, output);
return output;
}
/**
* Check whether a ray intersects a line segment, returns the parametric value where the intersection occurs.
* @method rayToLineSegment
* @static
* @param {Number} rayx1. The origin x of the ray.
* @param {Number} rayy1. The origin y of the ray.
* @param {Number} rayx2. The direction x of the ray.
* @param {Number} rayy2. The direction y of the ray.
* @param {Number} linex1. The x of the first point of the line segment.
* @param {Number} liney1. The y of the first point of the line segment.
* @param {Number} linex2. The x of the second point of the line segment.
* @param {Number} liney2. The y of the second point of the line segment.
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection stored in x
**/
public static rayToLineSegment(rayx1, rayy1, rayx2, rayy2, linex1, liney1, linex2, liney2, output?: IntersectResult = new IntersectResult): IntersectResult {
var r, s, d;
// Check lines are not parallel
if ((rayy2 - rayy1) / (rayx2 - rayx1) != (liney2 - liney1) / (linex2 - linex1))
{
d = (((rayx2 - rayx1) * (liney2 - liney1)) - (rayy2 - rayy1) * (linex2 - linex1));
if (d != 0)
{
r = (((rayy1 - liney1) * (linex2 - linex1)) - (rayx1 - linex1) * (liney2 - liney1)) / d;
s = (((rayy1 - liney1) * (rayx2 - rayx1)) - (rayx1 - linex1) * (rayy2 - rayy1)) / d;
if (r >= 0)
{
if (s >= 0 && s <= 1)
{
output.result = true;
output.x = rayx1 + r * (rayx2 - rayx1), rayy1 + r * (rayy2 - rayy1);
}
}
}
}
return output;
}
/**
* -------------------------------------------------------------------------------------------
* Rectangles
* -------------------------------------------------------------------------------------------
**/
/**
* Determines whether the specified point is contained within the rectangular region defined by the Rectangle object.
* @method pointToRectangle
* @param {Point} point The point object being checked.
* @param {Rectangle} rect The rectangle object being checked.
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection in x/y/result
**/
public static pointToRectangle(point: Point, rect: Rectangle, output?: IntersectResult = new IntersectResult): IntersectResult {
output.setTo(point.x, point.y);
output.result = rect.containsPoint(point);
return output;
}
/**
* Check whether two axis aligned rectangles intersect. Return the intersecting rectangle dimensions if they do.
* @method rectangleToRectangle
* @param {Phaser.Rectangle} The first Rectangle object
* @param {Phaser.Rectangle} The second Rectangle object
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection in x/y/width/height
**/
public static rectangleToRectangle(rect1: Rectangle, rect2: Rectangle, output?: IntersectResult = new IntersectResult): IntersectResult {
var leftX = Math.max(rect1.x, rect2.x);
var rightX = Math.min(rect1.right, rect2.right);
var topY = Math.max(rect1.y, rect2.y);
var bottomY = Math.min(rect1.bottom, rect2.bottom);
output.setTo(leftX, topY, rightX - leftX, bottomY - topY, rightX - leftX, bottomY - topY);
var cx = output.x + output.width * .5;
var cy = output.y + output.height * .5;
if ((cx > rect1.x && cx < rect1.right) && (cy > rect1.y && cy < rect1.bottom))
{
output.result = true;
}
return output;
}
public static rectangleToCircle(rect: Rectangle, circle: Circle, output?: IntersectResult = new IntersectResult): IntersectResult {
return this.circleToRectangle(circle, rect, output);
}
/**
* -------------------------------------------------------------------------------------------
* Circle
* -------------------------------------------------------------------------------------------
**/
/**
* Check if the two given Circle objects intersect
* @method circleToCircle
* @param {Phaser.Circle} The first circle object to check
* @param {Phaser.Circle} The second circle object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection
**/
public static circleToCircle(circle1: Circle, circle2: Circle, output?: IntersectResult = new IntersectResult): IntersectResult {
output.result = ((circle1.radius + circle2.radius) * (circle1.radius + circle2.radius)) >= this.distanceSquared(circle1.x, circle1.y, circle2.x, circle2.y);
return output;
}
/**
* Check if the given Rectangle intersects with the given Circle
* @method circleToRectangle
* @param {Phaser.Circle} The circle object to check
* @param {Phaser.Rectangle} The Rectangle object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection
**/
public static circleToRectangle(circle: Circle, rect: Rectangle, output?: IntersectResult = new IntersectResult): IntersectResult {
var inflatedRect: Rectangle = rect.clone();
inflatedRect.inflate(circle.radius, circle.radius);
output.result = inflatedRect.contains(circle.x, circle.y);
return output;
}
/**
* Check if the given Point is found within the given Circle
* @method circleContainsPoint
* @param {Phaser.Circle} The circle object to check
* @param {Phaser.Point} The point object to check
* @param {Phaser.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
* @return {Phaser.IntersectResult} An IntersectResult object containing the results of this intersection
**/
public static circleContainsPoint(circle: Circle, point: Point, output?: IntersectResult = new IntersectResult): IntersectResult {
output.result = circle.radius * circle.radius >= this.distanceSquared(circle.x, circle.y, point.x, point.y);
return output;
}
/**
* -------------------------------------------------------------------------------------------
* Game Object Collision
* -------------------------------------------------------------------------------------------
**/
/**
* Call this function to see if one <code>GameObject</code> overlaps another.
* Can be called with one object and one group, or two groups, or two objects,
* whatever floats your boat! For maximum performance try bundling a lot of objects
* together using a <code>Group</code> (or even bundling groups together!).
*
* <p>NOTE: does NOT take objects' scrollfactor into account, all overlaps are checked in world space.</p>
*
* @param ObjectOrGroup1 The first object or group you want to check.
* @param ObjectOrGroup2 The second object or group you want to check. If it is the same as the first it knows to just do a comparison within that group.
* @param NotifyCallback A function with two <code>GameObject</code> parameters - e.g. <code>myOverlapFunction(Object1:GameObject,Object2:GameObject)</code> - that is called if those two objects overlap.
* @param ProcessCallback A function with two <code>GameObject</code> parameters - e.g. <code>myOverlapFunction(Object1:GameObject,Object2:GameObject)</code> - that is called if those two objects overlap. If a ProcessCallback is provided, then NotifyCallback will only be called if ProcessCallback returns true for those objects!
*
* @return Whether any overlaps were detected.
*/
public overlap(ObjectOrGroup1: Basic = null, ObjectOrGroup2: Basic = null, NotifyCallback = null, ProcessCallback = null): bool {
if (ObjectOrGroup1 == null)
{
ObjectOrGroup1 = this._game.world.group;
}
if (ObjectOrGroup2 == ObjectOrGroup1)
{
ObjectOrGroup2 = null;
}
QuadTree.divisions = this._game.world.worldDivisions;
var quadTree: QuadTree = new QuadTree(this._game.world.bounds.x, this._game.world.bounds.y, this._game.world.bounds.width, this._game.world.bounds.height);
quadTree.load(ObjectOrGroup1, ObjectOrGroup2, NotifyCallback, ProcessCallback);
var result: bool = quadTree.execute();
quadTree.destroy();
quadTree = null;
return result;
}
/**
* The main collision resolution in flixel.
*
* @param Object1 Any <code>Sprite</code>.
* @param Object2 Any other <code>Sprite</code>.
*
* @return Whether the objects in fact touched and were separated.
*/
public static separate(Object1, Object2): bool {
var separatedX: bool = Collision.separateX(Object1, Object2);
var separatedY: bool = Collision.separateY(Object1, Object2);
return separatedX || separatedY;
}
/**
* The X-axis component of the object separation process.
*
* @param Object1 Any <code>Sprite</code>.
* @param Object2 Any other <code>Sprite</code>.
*
* @return Whether the objects in fact touched and were separated along the X axis.
*/
public static separateX(Object1, Object2): bool {
//can't separate two immovable objects
var obj1immovable: bool = Object1.immovable;
var obj2immovable: bool = Object2.immovable;
if (obj1immovable && obj2immovable)
{
return false;
}
//If one of the objects is a tilemap, just pass it off.
/*
if (typeof Object1 === 'Tilemap')
{
return Object1.overlapsWithCallback(Object2, separateX);
}
if (typeof Object2 === 'Tilemap')
{
return Object2.overlapsWithCallback(Object1, separateX, true);
}
*/
//First, get the two object deltas
var overlap: number = 0;
var obj1delta: number = Object1.x - Object1.last.x;
var obj2delta: number = Object2.x - Object2.last.x;
if (obj1delta != obj2delta)
{
//Check if the X hulls actually overlap
var obj1deltaAbs: number = (obj1delta > 0) ? obj1delta : -obj1delta;
var obj2deltaAbs: number = (obj2delta > 0) ? obj2delta : -obj2delta;
var obj1rect: Rectangle = new Rectangle(Object1.x - ((obj1delta > 0) ? obj1delta : 0), Object1.last.y, Object1.width + ((obj1delta > 0) ? obj1delta : -obj1delta), Object1.height);
var obj2rect: Rectangle = new Rectangle(Object2.x - ((obj2delta > 0) ? obj2delta : 0), Object2.last.y, Object2.width + ((obj2delta > 0) ? obj2delta : -obj2delta), Object2.height);
if ((obj1rect.x + obj1rect.width > obj2rect.x) && (obj1rect.x < obj2rect.x + obj2rect.width) && (obj1rect.y + obj1rect.height > obj2rect.y) && (obj1rect.y < obj2rect.y + obj2rect.height))
{
var maxOverlap: number = obj1deltaAbs + obj2deltaAbs + Collision.OVERLAP_BIAS;
//If they did overlap (and can), figure out by how much and flip the corresponding flags
if (obj1delta > obj2delta)
{
overlap = Object1.x + Object1.width - Object2.x;
if ((overlap > maxOverlap) || !(Object1.allowCollisions & Collision.RIGHT) || !(Object2.allowCollisions & Collision.LEFT))
{
overlap = 0;
}
else
{
Object1.touching |= Collision.RIGHT;
Object2.touching |= Collision.LEFT;
}
}
else if (obj1delta < obj2delta)
{
overlap = Object1.x - Object2.width - Object2.x;
if ((-overlap > maxOverlap) || !(Object1.allowCollisions & Collision.LEFT) || !(Object2.allowCollisions & Collision.RIGHT))
{
overlap = 0;
}
else
{
Object1.touching |= Collision.LEFT;
Object2.touching |= Collision.RIGHT;
}
}
}
}
//Then adjust their positions and velocities accordingly (if there was any overlap)
if (overlap != 0)
{
var obj1v: number = Object1.velocity.x;
var obj2v: number = Object2.velocity.x;
if (!obj1immovable && !obj2immovable)
{
overlap *= 0.5;
Object1.x = Object1.x - overlap;
Object2.x += overlap;
var obj1velocity: number = Math.sqrt((obj2v * obj2v * Object2.mass) / Object1.mass) * ((obj2v > 0) ? 1 : -1);
var obj2velocity: number = Math.sqrt((obj1v * obj1v * Object1.mass) / Object2.mass) * ((obj1v > 0) ? 1 : -1);
var average: number = (obj1velocity + obj2velocity) * 0.5;
obj1velocity -= average;
obj2velocity -= average;
Object1.velocity.x = average + obj1velocity * Object1.elasticity;
Object2.velocity.x = average + obj2velocity * Object2.elasticity;
}
else if (!obj1immovable)
{
Object1.x = Object1.x - overlap;
Object1.velocity.x = obj2v - obj1v * Object1.elasticity;
}
else if (!obj2immovable)
{
Object2.x += overlap;
Object2.velocity.x = obj1v - obj2v * Object2.elasticity;
}
return true;
}
else
{
return false;
}
}
/**
* The Y-axis component of the object separation process.
*
* @param Object1 Any <code>Sprite</code>.
* @param Object2 Any other <code>Sprite</code>.
*
* @return Whether the objects in fact touched and were separated along the Y axis.
*/
public static separateY(Object1, Object2): bool {
//can't separate two immovable objects
var obj1immovable: bool = Object1.immovable;
var obj2immovable: bool = Object2.immovable;
if (obj1immovable && obj2immovable)
return false;
//If one of the objects is a tilemap, just pass it off.
/*
if (typeof Object1 === 'Tilemap')
{
return Object1.overlapsWithCallback(Object2, separateY);
}
if (typeof Object2 === 'Tilemap')
{
return Object2.overlapsWithCallback(Object1, separateY, true);
}
*/
//First, get the two object deltas
var overlap: number = 0;
var obj1delta: number = Object1.y - Object1.last.y;
var obj2delta: number = Object2.y - Object2.last.y;
if (obj1delta != obj2delta)
{
//Check if the Y hulls actually overlap
var obj1deltaAbs: number = (obj1delta > 0) ? obj1delta : -obj1delta;
var obj2deltaAbs: number = (obj2delta > 0) ? obj2delta : -obj2delta;
var obj1rect: Rectangle = new Rectangle(Object1.x, Object1.y - ((obj1delta > 0) ? obj1delta : 0), Object1.width, Object1.height + obj1deltaAbs);
var obj2rect: Rectangle = new Rectangle(Object2.x, Object2.y - ((obj2delta > 0) ? obj2delta : 0), Object2.width, Object2.height + obj2deltaAbs);
if ((obj1rect.x + obj1rect.width > obj2rect.x) && (obj1rect.x < obj2rect.x + obj2rect.width) && (obj1rect.y + obj1rect.height > obj2rect.y) && (obj1rect.y < obj2rect.y + obj2rect.height))
{
var maxOverlap: number = obj1deltaAbs + obj2deltaAbs + Collision.OVERLAP_BIAS;
//If they did overlap (and can), figure out by how much and flip the corresponding flags
if (obj1delta > obj2delta)
{
overlap = Object1.y + Object1.height - Object2.y;
if ((overlap > maxOverlap) || !(Object1.allowCollisions & Collision.DOWN) || !(Object2.allowCollisions & Collision.UP))
{
overlap = 0;
}
else
{
Object1.touching |= Collision.DOWN;
Object2.touching |= Collision.UP;
}
}
else if (obj1delta < obj2delta)
{
overlap = Object1.y - Object2.height - Object2.y;
if ((-overlap > maxOverlap) || !(Object1.allowCollisions & Collision.UP) || !(Object2.allowCollisions & Collision.DOWN))
{
overlap = 0;
}
else
{
Object1.touching |= Collision.UP;
Object2.touching |= Collision.DOWN;
}
}
}
}
//Then adjust their positions and velocities accordingly (if there was any overlap)
if (overlap != 0)
{
var obj1v: number = Object1.velocity.y;
var obj2v: number = Object2.velocity.y;
if (!obj1immovable && !obj2immovable)
{
overlap *= 0.5;
Object1.y = Object1.y - overlap;
Object2.y += overlap;
var obj1velocity: number = Math.sqrt((obj2v * obj2v * Object2.mass) / Object1.mass) * ((obj2v > 0) ? 1 : -1);
var obj2velocity: number = Math.sqrt((obj1v * obj1v * Object1.mass) / Object2.mass) * ((obj1v > 0) ? 1 : -1);
var average: number = (obj1velocity + obj2velocity) * 0.5;
obj1velocity -= average;
obj2velocity -= average;
Object1.velocity.y = average + obj1velocity * Object1.elasticity;
Object2.velocity.y = average + obj2velocity * Object2.elasticity;
}
else if (!obj1immovable)
{
Object1.y = Object1.y - overlap;
Object1.velocity.y = obj2v - obj1v * Object1.elasticity;
//This is special case code that handles cases like horizontal moving platforms you can ride
if (Object2.active && Object2.moves && (obj1delta > obj2delta))
{
Object1.x += Object2.x - Object2.last.x;
}
}
else if (!obj2immovable)
{
Object2.y += overlap;
Object2.velocity.y = obj1v - obj2v * Object2.elasticity;
//This is special case code that handles cases like horizontal moving platforms you can ride
if (Object1.active && Object1.moves && (obj1delta < obj2delta))
{
Object2.x += Object1.x - Object1.last.x;
}
}
return true;
}
else
{
return false;
}
}
/**
* -------------------------------------------------------------------------------------------
* Distance
* -------------------------------------------------------------------------------------------
**/
public static distance(x1: number, y1: number, x2: number, y2: number) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
public static distanceSquared(x1: number, y1: number, x2: number, y2: number) {
return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
}
}
}

View file

@ -1,205 +1,212 @@
/// <reference path="Game.ts" />
class DynamicTexture {
/**
* Phaser
*/
constructor(game: Game, key: string, width: number, height: number) {
module Phaser {
this._game = game;
export class DynamicTexture {
this.canvas = <HTMLCanvasElement> document.createElement('canvas');
this.canvas.width = width;
this.canvas.height = height;
this.context = this.canvas.getContext('2d');
constructor(game: Game, key: string, width: number, height: number) {
this.bounds = new Rectangle(0, 0, width, height);
this._game = game;
}
this.canvas = <HTMLCanvasElement> document.createElement('canvas');
this.canvas.width = width;
this.canvas.height = height;
this.context = this.canvas.getContext('2d');
private _game: Game;
this.bounds = new Rectangle(0, 0, width, height);
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;
}
// Input / Output nodes?
private _game: Game;
public bounds: Rectangle;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
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 getPixel(x: number, y: number): number {
// Input / Output nodes?
//r = imageData.data[0];
//g = imageData.data[1];
//b = imageData.data[2];
//a = imageData.data[3];
var imageData = this.context.getImageData(x, y, 1, 1);
public bounds: Rectangle;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
return this.getColor(imageData.data[0], imageData.data[1], imageData.data[2]);
public getPixel(x: number, y: number): number {
}
//r = imageData.data[0];
//g = imageData.data[1];
//b = imageData.data[2];
//a = imageData.data[3];
var imageData = this.context.getImageData(x, y, 1, 1);
public getPixel32(x: number, y: number) {
return this.getColor(imageData.data[0], imageData.data[1], imageData.data[2]);
var imageData = this.context.getImageData(x, y, 1, 1);
}
return this.getColor32(imageData.data[3], imageData.data[0], imageData.data[1], imageData.data[2]);
}
public getPixel32(x: number, y: number) {
// Returns a CanvasPixelArray
public getPixels(rect:Rectangle) {
return this.context.getImageData(rect.x, rect.y, rect.width, rect.height);
}
var imageData = this.context.getImageData(x, y, 1, 1);
public setPixel(x: number, y: number, color:number) {
this.context.fillStyle = color;
this.context.fillRect(x, y, 1, 1);
}
return this.getColor32(imageData.data[3], imageData.data[0], imageData.data[1], imageData.data[2]);
public setPixel32(x: number, y: number, color:number) {
this.context.fillStyle = color;
this.context.fillRect(x, y, 1, 1);
}
}
public setPixels(rect:Rectangle, input) {
// Returns a CanvasPixelArray
public getPixels(rect: Rectangle) {
this.context.putImageData(input, rect.x, rect.y);
}
return this.context.getImageData(rect.x, rect.y, rect.width, rect.height);
public fillRect(rect: Rectangle, color: number) {
}
this.context.fillStyle = color;
this.context.fillRect(rect.x, rect.y, rect.width, rect.height);
public setPixel(x: number, y: number, color: number) {
}
this.context.fillStyle = color;
this.context.fillRect(x, y, 1, 1);
public pasteImage(key: string, frame?: number = -1, destX?: number = 0, destY?: number = 0, destWidth?: number = null, destHeight?: number = null) {
}
var texture = null;
var frameData;
public setPixel32(x: number, y: number, color: number) {
this._sx = 0;
this._sy = 0;
this._dx = destX;
this._dy = destY;
this.context.fillStyle = color;
this.context.fillRect(x, y, 1, 1);
// TODO - Load a frame from a sprite sheet, otherwise we'll draw the whole lot
if (frame > -1)
{
//if (this._game.cache.isSpriteSheet(key))
//{
// texture = this._game.cache.getImage(key);
}
public setPixels(rect: Rectangle, input) {
this.context.putImageData(input, rect.x, rect.y);
}
public fillRect(rect: Rectangle, color: number) {
this.context.fillStyle = color;
this.context.fillRect(rect.x, rect.y, rect.width, rect.height);
}
public pasteImage(key: string, frame?: number = -1, destX?: number = 0, destY?: number = 0, destWidth?: number = null, destHeight?: number = null) {
var texture = null;
var frameData;
this._sx = 0;
this._sy = 0;
this._dx = destX;
this._dy = destY;
// TODO - Load a frame from a sprite sheet, otherwise we'll draw the whole lot
if (frame > -1)
{
//if (this._game.cache.isSpriteSheet(key))
//{
// texture = this._game.cache.getImage(key);
//this.animations.loadFrameData(this._game.cache.getFrameData(key));
//}
}
else
{
texture = this._game.cache.getImage(key);
this._sw = texture.width;
this._sh = texture.height;
this._dw = texture.width;
this._dh = texture.height;
//}
}
else
{
texture = this._game.cache.getImage(key);
this._sw = texture.width;
this._sh = texture.height;
this._dw = texture.width;
this._dh = texture.height;
}
if (destWidth !== null)
{
this._dw = destWidth;
}
if (destHeight !== null)
{
this._dh = destHeight;
}
if (texture != null)
{
this.context.drawImage(
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)
);
}
}
if (destWidth !== null)
{
this._dw = destWidth;
// TODO - Add in support for: alphaBitmapData: BitmapData = null, alphaPoint: Point = null, mergeAlpha: bool = false
public copyPixels(sourceTexture: DynamicTexture, sourceRect: Rectangle, destPoint: Point) {
// Swap for drawImage if the sourceRect is the same size as the sourceTexture to avoid a costly getImageData call
if (sourceRect.equals(this.bounds) == true)
{
this.context.drawImage(sourceTexture.canvas, destPoint.x, destPoint.y);
}
else
{
this.context.putImageData(sourceTexture.getPixels(sourceRect), destPoint.x, destPoint.y);
}
}
if (destHeight !== null)
{
this._dh = destHeight;
public clear() {
this.context.clearRect(0, 0, this.bounds.width, this.bounds.height);
}
if (texture != null)
{
this.context.drawImage(
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)
);
public get width(): number {
return this.bounds.width;
}
public get height(): number {
return this.bounds.height;
}
/**
* Given an alpha and 3 color values this will return an integer representation of it
*
* @param alpha The Alpha value (between 0 and 255)
* @param red The Red channel value (between 0 and 255)
* @param green The Green channel value (between 0 and 255)
* @param blue The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xAARRGGBB)
*/
private getColor32(alpha: number, red: number, green: number, blue: number): number {
return alpha << 24 | red << 16 | green << 8 | blue;
}
/**
* Given 3 color values this will return an integer representation of it
*
* @param red The Red channel value (between 0 and 255)
* @param green The Green channel value (between 0 and 255)
* @param blue The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xRRGGBB)
*/
private getColor(red: number, green: number, blue: number): number {
return red << 16 | green << 8 | blue;
}
}
// TODO - Add in support for: alphaBitmapData: BitmapData = null, alphaPoint: Point = null, mergeAlpha: bool = false
public copyPixels(sourceTexture: DynamicTexture, sourceRect: Rectangle, destPoint: Point) {
// Swap for drawImage if the sourceRect is the same size as the sourceTexture to avoid a costly getImageData call
if (sourceRect.equals(this.bounds) == true)
{
this.context.drawImage(sourceTexture.canvas, destPoint.x, destPoint.y);
}
else
{
this.context.putImageData(sourceTexture.getPixels(sourceRect), destPoint.x, destPoint.y);
}
}
public clear() {
this.context.clearRect(0, 0, this.bounds.width, this.bounds.height);
}
public get width(): number {
return this.bounds.width;
}
public get height(): number {
return this.bounds.height;
}
/**
* Given an alpha and 3 color values this will return an integer representation of it
*
* @param alpha The Alpha value (between 0 and 255)
* @param red The Red channel value (between 0 and 255)
* @param green The Green channel value (between 0 and 255)
* @param blue The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xAARRGGBB)
*/
private getColor32(alpha: number, red: number, green: number, blue: number): number {
return alpha << 24 | red << 16 | green << 8 | blue;
}
/**
* Given 3 color values this will return an integer representation of it
*
* @param red The Red channel value (between 0 and 255)
* @param green The Green channel value (between 0 and 255)
* @param blue The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xRRGGBB)
*/
private getColor(red: number, green: number, blue: number): number {
return red << 16 | green << 8 | blue;
}
}

View file

@ -1,453 +0,0 @@
/// <reference path="Group.ts" />
/// <reference path="Particle.ts" />
/// <reference path="geom/Point.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
*/
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 = GameObject.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);
}
}

View file

@ -1,377 +1,401 @@
/// <reference path="Animations.ts" />
/// <reference path="Basic.ts" />
/// <reference path="Cache.ts" />
/// <reference path="Cameras.ts" />
/// <reference path="Emitter.ts" />
/// <reference path="Collision.ts" />
/// <reference path="DynamicTexture.ts" />
/// <reference path="GameMath.ts" />
/// <reference path="Group.ts" />
/// <reference path="Loader.ts" />
/// <reference path="Motion.ts" />
/// <reference path="Signal.ts" />
/// <reference path="SignalBinding.ts" />
/// <reference path="Sound.ts" />
/// <reference path="Sprite.ts" />
/// <reference path="Stage.ts" />
/// <reference path="Time.ts" />
/// <reference path="GameMath.ts" />
/// <reference path="TweenManager.ts" />
/// <reference path="World.ts" />
/// <reference path="system/input/Input.ts" />
/// <reference path="system/RequestAnimationFrame.ts" />
/// <reference path="system/RandomDataGenerator.ts" />
/// <reference path="system/Device.ts" />
/// <reference path="system/RandomDataGenerator.ts" />
/// <reference path="system/RequestAnimationFrame.ts" />
/// <reference path="system/input/Input.ts" />
/// <reference path="system/input/Keyboard.ts" />
/// <reference path="system/input/Mouse.ts" />
/// <reference path="system/input/Touch.ts" />
/// <reference path="gameobjects/Emitter.ts" />
/// <reference path="gameobjects/GameObject.ts" />
/// <reference path="gameobjects/GeomSprite.ts" />
/// <reference path="gameobjects/Particle.ts" />
/// <reference path="gameobjects/Sprite.ts" />
/// <reference path="gameobjects/Tilemap.ts" />
/**
* Phaser
*
* v0.8 - April 15th 2013
*
* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi.
*
* Richard Davey (@photonstorm)
* Adam Saltsman (@ADAMATOMIC) (original Flixel code)
*
* "If you want your children to be intelligent, read them fairy tales."
* "If you want them to be more intelligent, read them more fairy tales."
* -- Albert Einstein
*/
class Game {
module Phaser {
constructor(callbackContext, parent?:string = '', width?: number = 800, height?: number = 600, initCallback = null, createCallback = null, updateCallback = null, renderCallback = null) {
export class Game {
this.callbackContext = callbackContext;
this.onInitCallback = initCallback;
this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback;
constructor(callbackContext, parent?: string = '', width?: number = 800, height?: number = 600, initCallback = null, createCallback = null, updateCallback = null, renderCallback = null) {
if (document.readyState === 'complete' || document.readyState === 'interactive')
{
this.boot(parent, width, height);
}
else
{
document.addEventListener('DOMContentLoaded', () => this.boot(parent, width, height), false);
}
}
this.callbackContext = callbackContext;
this.onInitCallback = initCallback;
this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback;
public static VERSION: string = 'Phaser version 0.8';
private _raf: RequestAnimationFrame;
private _maxAccumulation: number = 32;
private _accumulator: number = 0;
private _step: number = 0;
private _loadComplete: bool = false;
private _paused: bool = false;
private _pendingState = null;
// Event callbacks
public callbackContext;
public onInitCallback = null;
public onCreateCallback = null;
public onUpdateCallback = null;
public onRenderCallback = null;
public onPausedCallback = null;
public camera: Camera; // quick reference to the default created camera, access the rest via .world
public cache: Cache;
public input: Input;
public loader: Loader;
public sound: SoundManager;
public stage: Stage;
public time: Time;
public math: GameMath;
public world: World;
public rnd: RandomDataGenerator;
public device: Device;
public isBooted: bool = false;
private boot(parent:string, width: number, height: number) {
if (!document.body)
{
window.setTimeout(() => this.boot(parent, width, height), 13);
}
else
{
this.device = new Device();
this.stage = new Stage(this, parent, width, height);
this.world = new World(this, width, height);
this.sound = new SoundManager(this);
this.cache = new Cache(this);
this.loader = new Loader(this, this.loadComplete);
this.time = new Time(this);
this.input = new Input(this);
this.math = new GameMath(this);
this.rnd = new RandomDataGenerator([(Date.now() * Math.random()).toString()]);
this.framerate = 60;
// Display the default game screen?
if (this.onInitCallback == null && this.onCreateCallback == null && this.onUpdateCallback == null && this.onRenderCallback == null && this._pendingState == null)
if (document.readyState === 'complete' || document.readyState === 'interactive')
{
this.isBooted = false;
this.stage.drawInitScreen();
this.boot(parent, width, height);
}
else
{
this.isBooted = true;
this._loadComplete = false;
document.addEventListener('DOMContentLoaded', () => this.boot(parent, width, height), false);
}
this._raf = new RequestAnimationFrame(this.loop, this);
}
if (this._pendingState)
private _raf: RequestAnimationFrame;
private _maxAccumulation: number = 32;
private _accumulator: number = 0;
private _step: number = 0;
private _loadComplete: bool = false;
private _paused: bool = false;
private _pendingState = null;
// Event callbacks
public callbackContext;
public onInitCallback = null;
public onCreateCallback = null;
public onUpdateCallback = null;
public onRenderCallback = null;
public onPausedCallback = null;
public camera: Camera; // quick reference to the default created camera, access the rest via .world
public cache: Cache;
public collision: Collision;
public input: Input;
public loader: Loader;
public math: GameMath;
public motion: Motion;
public sound: SoundManager;
public stage: Stage;
public time: Time;
public tweens: TweenManager;
public world: World;
public rnd: RandomDataGenerator;
public device: Device;
public isBooted: bool = false;
private boot(parent: string, width: number, height: number) {
if (!document.body)
{
window.setTimeout(() => this.boot(parent, width, height), 13);
}
else
{
this.device = new Device();
this.motion = new Motion(this);
this.math = new GameMath(this);
this.stage = new Stage(this, parent, width, height);
this.world = new World(this, width, height);
this.sound = new SoundManager(this);
this.cache = new Cache(this);
this.collision = new Collision(this);
this.loader = new Loader(this, this.loadComplete);
this.time = new Time(this);
this.tweens = new TweenManager(this);
this.input = new Input(this);
this.rnd = new RandomDataGenerator([(Date.now() * Math.random()).toString()]);
this.framerate = 60;
// Display the default game screen?
if (this.onInitCallback == null && this.onCreateCallback == null && this.onUpdateCallback == null && this.onRenderCallback == null && this._pendingState == null)
{
this.switchState(this._pendingState, false, false);
this.isBooted = false;
this.stage.drawInitScreen();
}
else
{
this.startState();
this.isBooted = true;
this._loadComplete = false;
this._raf = new RequestAnimationFrame(this.loop, this);
if (this._pendingState)
{
this.switchState(this._pendingState, false, false);
}
else
{
this.startState();
}
}
}
}
}
private loadComplete() {
// Called when the loader has finished after init was run
this._loadComplete = true;
}
private loop() {
if (this._paused == true)
{
if (this.onPausedCallback !== null)
{
this.onPausedCallback.call(this.callbackContext);
}
return;
}
this.time.update();
this.input.update();
this.stage.update();
this._accumulator += this.time.delta;
if (this._accumulator > this._maxAccumulation)
{
this._accumulator = this._maxAccumulation;
}
while (this._accumulator >= this._step)
{
this.time.elapsed = this.time.timeScale * (this._step / 1000);
this.world.update();
this._accumulator = this._accumulator - this._step;
}
if (this._loadComplete && this.onUpdateCallback)
{
this.onUpdateCallback.call(this.callbackContext);
}
this.world.render();
if (this._loadComplete && this.onRenderCallback)
{
this.onRenderCallback.call(this.callbackContext);
}
}
private startState() {
if (this.onInitCallback !== null)
{
this.onInitCallback.call(this.callbackContext);
}
else
{
// No init? Then there was nothing to load either
if (this.onCreateCallback !== null)
{
this.onCreateCallback.call(this.callbackContext);
}
private loadComplete() {
// Called when the loader has finished after init was run
this._loadComplete = true;
}
}
private loop() {
public setCallbacks(initCallback = null, createCallback = null, updateCallback = null, renderCallback = null) {
this.time.update();
this.tweens.update();
this.onInitCallback = initCallback;
this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback;
if (this._paused == true)
{
if (this.onPausedCallback !== null)
{
this.onPausedCallback.call(this.callbackContext);
}
}
return;
public switchState(state, clearWorld: bool = true, clearCache:bool = false) {
}
this.input.update();
this.stage.update();
this._accumulator += this.time.delta;
if (this._accumulator > this._maxAccumulation)
{
this._accumulator = this._maxAccumulation;
}
while (this._accumulator >= this._step)
{
this.time.elapsed = this.time.timeScale * (this._step / 1000);
this.world.update();
this._accumulator = this._accumulator - this._step;
}
if (this._loadComplete && this.onUpdateCallback)
{
this.onUpdateCallback.call(this.callbackContext);
}
this.world.render();
if (this._loadComplete && this.onRenderCallback)
{
this.onRenderCallback.call(this.callbackContext);
}
if (this.isBooted == false)
{
this._pendingState = state;
return;
}
// Prototype?
if (typeof state === 'function')
{
state = new state(this);
private startState() {
if (this.onInitCallback !== null)
{
this.onInitCallback.call(this.callbackContext);
}
else
{
// No init? Then there was nothing to load either
if (this.onCreateCallback !== null)
{
this.onCreateCallback.call(this.callbackContext);
}
this._loadComplete = true;
}
}
// Ok, have we got the right functions?
if (state['create'] || state['update'])
{
this.callbackContext = state;
public setCallbacks(initCallback = null, createCallback = null, updateCallback = null, renderCallback = null) {
this.onInitCallback = initCallback;
this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback;
}
public switchState(state, clearWorld: bool = true, clearCache: bool = false) {
if (this.isBooted == false)
{
this._pendingState = state;
return;
}
// Prototype?
if (typeof state === 'function')
{
state = new state(this);
}
// Ok, have we got the right functions?
if (state['create'] || state['update'])
{
this.callbackContext = state;
this.onInitCallback = null;
this.onCreateCallback = null;
this.onUpdateCallback = null;
this.onRenderCallback = null;
this.onPausedCallback = null;
// Bingo, let's set them up
if (state['init'])
{
this.onInitCallback = state['init'];
}
if (state['create'])
{
this.onCreateCallback = state['create'];
}
if (state['update'])
{
this.onUpdateCallback = state['update'];
}
if (state['render'])
{
this.onRenderCallback = state['render'];
}
if (state['paused'])
{
this.onPausedCallback = state['paused'];
}
if (clearWorld)
{
this.world.destroy();
if (clearCache == true)
{
this.cache.destroy();
}
}
this._loadComplete = false;
this.startState();
}
else
{
throw Error("Invalid State object given. Must contain at least a create or update function.");
return;
}
}
// Nuke the whole game from orbit
public destroy() {
this.callbackContext = null;
this.onInitCallback = null;
this.onCreateCallback = null;
this.onUpdateCallback = null;
this.onRenderCallback = null;
this.onPausedCallback = null;
this.camera = null;
this.cache = null;
this.input = null;
this.loader = null;
this.sound = null;
this.stage = null;
this.time = null;
this.world = null;
this.isBooted = false;
// Bingo, let's set them up
if (state['init'])
{
this.onInitCallback = state['init'];
}
if (state['create'])
{
this.onCreateCallback = state['create'];
}
if (state['update'])
{
this.onUpdateCallback = state['update'];
}
if (state['render'])
{
this.onRenderCallback = state['render'];
}
if (state['paused'])
{
this.onPausedCallback = state['paused'];
}
if (clearWorld)
{
this.world.destroy();
if (clearCache == true)
{
this.cache.destroy();
}
}
this._loadComplete = false;
this.startState();
}
else
{
throw Error("Invalid State object given. Must contain at least a create or update function.");
return;
public get paused(): bool {
return this._paused;
}
public set paused(value: bool) {
if (value == true && this._paused == false)
{
this._paused = true;
}
else if (value == false && this._paused == true)
{
this._paused = false;
this.time.time = Date.now();
this.input.reset();
}
}
public get framerate(): number {
return 1000 / this._step;
}
public set framerate(value: number) {
this._step = 1000 / value;
if (this._maxAccumulation < this._step)
{
this._maxAccumulation = this._step;
}
}
// Handy Proxy methods
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this.world.createCamera(x, y, width, height);
}
public createGeomSprite(x: number, y: number): GeomSprite {
return this.world.createGeomSprite(x, y);
}
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return this.world.createSprite(x, y, key);
}
public createDynamicTexture(key: string, width: number, height: number): DynamicTexture {
return this.world.createDynamicTexture(key, width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return this.world.createGroup(MaxSize);
}
public createParticle(): Particle {
return this.world.createParticle();
}
public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return this.world.createEmitter(x, y, size);
}
public createTilemap(key: string, mapData: string, format: number, tileWidth?: number, tileHeight?: number): Tilemap {
return this.world.createTilemap(key, mapData, format, tileWidth, tileHeight);
}
public createTween(obj): Tween {
return this.tweens.create(obj);
}
public collide(ObjectOrGroup1: Basic = null, ObjectOrGroup2: Basic = null, NotifyCallback = null): bool {
return this.collision.overlap(ObjectOrGroup1, ObjectOrGroup2, NotifyCallback, Collision.separate);
}
}
// Nuke the whole game from orbit
public destroy() {
this.callbackContext = null;
this.onInitCallback = null;
this.onCreateCallback = null;
this.onUpdateCallback = null;
this.onRenderCallback = null;
this.onPausedCallback = null;
this.camera = null;
this.cache = null;
this.input = null;
this.loader = null;
this.sound = null;
this.stage = null;
this.time = null;
this.math = null;
this.world = null;
this.isBooted = false;
}
public get pause(): bool {
return this._paused;
}
public set pause(value:bool) {
if (value == true && this._paused == false)
{
this._paused = true;
}
else if (value == false && this._paused == true)
{
this._paused = false;
this.time.time = Date.now();
this.input.reset();
}
}
public get framerate(): number {
return 1000 / this._step;
}
public set framerate(value: number) {
this._step = 1000 / value;
if (this._maxAccumulation < this._step)
{
this._maxAccumulation = this._step;
}
}
// Handy Proxy methods
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this.world.createCamera(x, y, width, height);
}
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return this.world.createSprite(x, y, key);
}
public createDynamicTexture(key: string, width: number, height: number): DynamicTexture {
return this.world.createDynamicTexture(key, width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return this.world.createGroup(MaxSize);
}
public createParticle(): Particle {
return this.world.createParticle();
}
public createEmitter(x?: number = 0, y?: number = 0, size?:number = 0): Emitter {
return this.world.createEmitter(x, y, size);
}
public createTilemap(key:string, mapData:string, format:number, tileWidth?:number,tileHeight?:number): Tilemap {
return this.world.createTilemap(key, mapData, format, tileWidth, tileHeight);
}
public collide(ObjectOrGroup1: Basic = null, ObjectOrGroup2: Basic = null, NotifyCallback = null): bool {
return this.world.overlap(ObjectOrGroup1, ObjectOrGroup2, NotifyCallback, World.separate);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,499 +0,0 @@
/// <reference path="Basic.ts" />
/// <reference path="Game.ts" />
/// <reference path="GameMath.ts" />
/// <reference path="geom/Rectangle.ts" />
/// <reference path="geom/Point.ts" />
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 = GameObject.NONE;
this.wasTouching = GameObject.NONE;
this.allowCollisions = GameObject.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 static LEFT: number = 0x0001;
public static RIGHT: number = 0x0010;
public static UP: number = 0x0100;
public static DOWN: number = 0x1000;
public static NONE: number = 0;
public static CEILING: number = GameObject.UP;
public static FLOOR: number = GameObject.DOWN;
public static WALL: number = GameObject.LEFT | GameObject.RIGHT;
public static ANY: number = GameObject.LEFT | GameObject.RIGHT | GameObject.UP | GameObject.DOWN;
public static OVERLAP_BIAS: number = 4;
public bounds: Rectangle;
public alpha: number;
public scale: Point;
public origin: Point;
// 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 = GameObject.NONE;
}
private updateMotion() {
var delta: number;
var velocityDelta: number;
velocityDelta = (this._game.math.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.math.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.math.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 & GameObject.ANY) > GameObject.NONE;
}
/**
* @private
*/
public set solid(Solid: bool) {
if (Solid)
{
this.allowCollisions = GameObject.ANY;
}
else
{
this.allowCollisions = GameObject.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 = GameObject.NONE;
this.wasTouching = GameObject.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) > GameObject.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) > GameObject.NONE) && ((this.wasTouching & Direction) <= GameObject.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;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,327 +1,335 @@
/// <reference path="Cache.ts" />
/// <reference path="Game.ts" />
class Loader {
/**
* Phaser
*/
constructor(game: Game, callback) {
module Phaser {
this._game = game;
this._gameCreateComplete = callback;
this._keys = [];
this._fileList = {};
this._xhr = new XMLHttpRequest();
export class Loader {
}
constructor(game: Game, callback) {
private _game: Game;
private _keys: string [];
private _fileList;
private _gameCreateComplete;
private _onComplete;
private _onFileLoad;
private _progressChunk: number;
private _xhr: XMLHttpRequest;
this._game = game;
this._gameCreateComplete = callback;
this._keys = [];
this._fileList = {};
this._xhr = new XMLHttpRequest();
public hasLoaded: bool;
public progress: number;
private checkKeyExists(key: string): bool {
if (this._fileList[key])
{
return true;
}
else
{
return false;
}
}
private _game: Game;
private _keys: string[];
private _fileList;
private _gameCreateComplete;
private _onComplete;
private _onFileLoad;
private _progressChunk: number;
private _xhr: XMLHttpRequest;
public addImageFile(key:string, url: string) {
public hasLoaded: bool;
public progress: number;
if (this.checkKeyExists(key) === false)
{
this._fileList[key] = { type: 'image', key: key, url: url, data: null, error: false, loaded: false };
this._keys.push(key);
}
private checkKeyExists(key: string): bool {
}
public addSpriteSheet(key:string, url: string, frameWidth:number, frameHeight:number, frameMax?:number = -1) {
if (this.checkKeyExists(key) === false)
{
this._fileList[key] = { type: 'spritesheet', key: key, url: url, data: null, frameWidth: frameWidth, frameHeight: frameHeight, frameMax: frameMax, error: false, loaded: false };
this._keys.push(key);
}
}
public addTextureAtlas(key: string, url: string, jsonURL?:string = null, jsonData? = null) {
//console.log('addTextureAtlas');
//console.log(typeof jsonData);
if (this.checkKeyExists(key) === false)
{
if (jsonURL !== null)
if (this._fileList[key])
{
//console.log('A URL to a json file has been given');
// A URL to a json file has been given
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: jsonURL, jsonData: null, error: false, loaded: false };
this._keys.push(key);
return true;
}
else
{
// A json string or object has been given
if (typeof jsonData === 'string')
{
//console.log('A json string has been given');
var data = JSON.parse(jsonData);
//console.log(data);
// Malformed?
if (data['frames'])
{
//console.log('frames array found');
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: data['frames'], error: false, loaded: false };
this._keys.push(key);
}
}
else
{
//console.log('A json object has been given', jsonData);
// Malformed?
if (jsonData['frames'])
{
//console.log('frames array found');
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: jsonData['frames'], error: false, loaded: false };
this._keys.push(key);
}
}
return false;
}
}
}
public addAudioFile(key:string, url: string) {
public addImageFile(key: string, url: string) {
if (this.checkKeyExists(key) === false)
{
this._fileList[key] = { type: 'audio', key: key, url: url, data: null, buffer: null, error: false, loaded: false };
this._keys.push(key);
}
}
public addTextFile(key:string, url: string) {
if (this.checkKeyExists(key) === false)
{
this._fileList[key] = { type: 'text', key: key, url: url, data: null, error: false, loaded: false };
this._keys.push(key);
}
}
public removeFile(key: string) {
delete this._fileList[key];
}
public removeAll() {
this._fileList = {};
}
public load(onFileLoadCallback = null, onCompleteCallback = null) {
this.progress = 0;
this.hasLoaded = false;
this._onComplete = onCompleteCallback;
if (onCompleteCallback == null)
{
this._onComplete = this._game.onCreateCallback;
}
this._onFileLoad = onFileLoadCallback;
if (this._keys.length > 0)
{
this._progressChunk = 100 / this._keys.length;
this.loadFile();
}
else
{
this.progress = 1;
this.hasLoaded = true;
this._gameCreateComplete.call(this._game);
if (this._onComplete !== null)
if (this.checkKeyExists(key) === false)
{
this._onComplete.call(this._game.callbackContext);
this._fileList[key] = { type: 'image', key: key, url: url, data: null, error: false, loaded: false };
this._keys.push(key);
}
}
}
public addSpriteSheet(key: string, url: string, frameWidth: number, frameHeight: number, frameMax?: number = -1) {
private loadFile() {
if (this.checkKeyExists(key) === false)
{
this._fileList[key] = { type: 'spritesheet', key: key, url: url, data: null, frameWidth: frameWidth, frameHeight: frameHeight, frameMax: frameMax, error: false, loaded: false };
this._keys.push(key);
}
var file = this._fileList[this._keys.pop()];
// Image or Data?
switch (file.type)
{
case 'image':
case 'spritesheet':
case 'textureatlas':
file.data = new Image();
file.data.name = file.key;
file.data.onload = () => this.fileComplete(file.key);
file.data.onerror = () => this.fileError(file.key);
file.data.src = file.url;
break;
case 'audio':
this._xhr.open("GET", file.url, true);
this._xhr.responseType = "arraybuffer";
this._xhr.onload = () => this.fileComplete(file.key);
this._xhr.onerror = () => this.fileError(file.key);
this._xhr.send();
break;
case 'text':
this._xhr.open("GET", file.url, true);
this._xhr.responseType = "text";
this._xhr.onload = () => this.fileComplete(file.key);
this._xhr.onerror = () => this.fileError(file.key);
this._xhr.send();
break;
}
}
public addTextureAtlas(key: string, url: string, jsonURL?: string = null, jsonData? = null) {
private fileError(key: string) {
//console.log('addTextureAtlas');
//console.log(typeof jsonData);
this._fileList[key].loaded = true;
this._fileList[key].error = true;
this.nextFile(key, false);
}
private fileComplete(key:string) {
this._fileList[key].loaded = true;
var file = this._fileList[key];
var loadNext: bool = true;
switch (file.type)
{
case 'image':
this._game.cache.addImage(file.key, file.url, file.data);
break;
case 'spritesheet':
this._game.cache.addSpriteSheet(file.key, file.url, file.data, file.frameWidth, file.frameHeight, file.frameMax);
break;
case 'textureatlas':
//console.log('texture atlas loaded');
if (file.jsonURL == null)
if (this.checkKeyExists(key) === false)
{
if (jsonURL !== null)
{
this._game.cache.addTextureAtlas(file.key, file.url, file.data, file.jsonData);
//console.log('A URL to a json file has been given');
// A URL to a json file has been given
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: jsonURL, jsonData: null, error: false, loaded: false };
this._keys.push(key);
}
else
{
// Load the JSON before carrying on with the next file
//console.log('Loading the JSON before carrying on with the next file');
loadNext = false;
this._xhr.open("GET", file.jsonURL, true);
this._xhr.responseType = "text";
this._xhr.onload = () => this.jsonLoadComplete(file.key);
this._xhr.onerror = () => this.jsonLoadError(file.key);
// A json string or object has been given
if (typeof jsonData === 'string')
{
//console.log('A json string has been given');
var data = JSON.parse(jsonData);
//console.log(data);
// Malformed?
if (data['frames'])
{
//console.log('frames array found');
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: data['frames'], error: false, loaded: false };
this._keys.push(key);
}
}
else
{
//console.log('A json object has been given', jsonData);
// Malformed?
if (jsonData['frames'])
{
//console.log('frames array found');
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: jsonData['frames'], error: false, loaded: false };
this._keys.push(key);
}
}
}
}
}
public addAudioFile(key: string, url: string) {
if (this.checkKeyExists(key) === false)
{
this._fileList[key] = { type: 'audio', key: key, url: url, data: null, buffer: null, error: false, loaded: false };
this._keys.push(key);
}
}
public addTextFile(key: string, url: string) {
if (this.checkKeyExists(key) === false)
{
this._fileList[key] = { type: 'text', key: key, url: url, data: null, error: false, loaded: false };
this._keys.push(key);
}
}
public removeFile(key: string) {
delete this._fileList[key];
}
public removeAll() {
this._fileList = {};
}
public load(onFileLoadCallback = null, onCompleteCallback = null) {
this.progress = 0;
this.hasLoaded = false;
this._onComplete = onCompleteCallback;
if (onCompleteCallback == null)
{
this._onComplete = this._game.onCreateCallback;
}
this._onFileLoad = onFileLoadCallback;
if (this._keys.length > 0)
{
this._progressChunk = 100 / this._keys.length;
this.loadFile();
}
else
{
this.progress = 1;
this.hasLoaded = true;
this._gameCreateComplete.call(this._game);
if (this._onComplete !== null)
{
this._onComplete.call(this._game.callbackContext);
}
}
}
private loadFile() {
var file = this._fileList[this._keys.pop()];
// Image or Data?
switch (file.type)
{
case 'image':
case 'spritesheet':
case 'textureatlas':
file.data = new Image();
file.data.name = file.key;
file.data.onload = () => this.fileComplete(file.key);
file.data.onerror = () => this.fileError(file.key);
file.data.src = file.url;
break;
case 'audio':
this._xhr.open("GET", file.url, true);
this._xhr.responseType = "arraybuffer";
this._xhr.onload = () => this.fileComplete(file.key);
this._xhr.onerror = () => this.fileError(file.key);
this._xhr.send();
}
break;
break;
case 'audio':
file.data = this._xhr.response;
this._game.cache.addSound(file.key, file.url, file.data);
break;
case 'text':
file.data = this._xhr.response;
this._game.cache.addText(file.key, file.url, file.data);
break;
}
if (loadNext)
{
this.nextFile(key, true);
}
}
private jsonLoadComplete(key:string) {
//console.log('json load complete');
var data = JSON.parse(this._xhr.response);
//console.log(data);
// Malformed?
if (data['frames'])
{
var file = this._fileList[key];
this._game.cache.addTextureAtlas(file.key, file.url, file.data, data['frames']);
}
this.nextFile(key, true);
}
private jsonLoadError(key:string) {
//console.log('json load error');
var file = this._fileList[key];
file.error = true;
this.nextFile(key, true);
}
private nextFile(previousKey:string, success:bool) {
this.progress = Math.round(this.progress + this._progressChunk);
if (this._onFileLoad)
{
this._onFileLoad.call(this._game.callbackContext, this.progress, previousKey, success);
}
if (this._keys.length > 0)
{
this.loadFile();
}
else
{
this.hasLoaded = true;
this.removeAll();
this._gameCreateComplete.call(this._game);
if (this._onComplete !== null)
{
this._onComplete.call(this._game.callbackContext);
case 'text':
this._xhr.open("GET", file.url, true);
this._xhr.responseType = "text";
this._xhr.onload = () => this.fileComplete(file.key);
this._xhr.onerror = () => this.fileError(file.key);
this._xhr.send();
break;
}
}
private fileError(key: string) {
this._fileList[key].loaded = true;
this._fileList[key].error = true;
this.nextFile(key, false);
}
private fileComplete(key: string) {
this._fileList[key].loaded = true;
var file = this._fileList[key];
var loadNext: bool = true;
switch (file.type)
{
case 'image':
this._game.cache.addImage(file.key, file.url, file.data);
break;
case 'spritesheet':
this._game.cache.addSpriteSheet(file.key, file.url, file.data, file.frameWidth, file.frameHeight, file.frameMax);
break;
case 'textureatlas':
//console.log('texture atlas loaded');
if (file.jsonURL == null)
{
this._game.cache.addTextureAtlas(file.key, file.url, file.data, file.jsonData);
}
else
{
// Load the JSON before carrying on with the next file
//console.log('Loading the JSON before carrying on with the next file');
loadNext = false;
this._xhr.open("GET", file.jsonURL, true);
this._xhr.responseType = "text";
this._xhr.onload = () => this.jsonLoadComplete(file.key);
this._xhr.onerror = () => this.jsonLoadError(file.key);
this._xhr.send();
}
break;
case 'audio':
file.data = this._xhr.response;
this._game.cache.addSound(file.key, file.url, file.data);
break;
case 'text':
file.data = this._xhr.response;
this._game.cache.addText(file.key, file.url, file.data);
break;
}
if (loadNext)
{
this.nextFile(key, true);
}
}
private jsonLoadComplete(key: string) {
//console.log('json load complete');
var data = JSON.parse(this._xhr.response);
//console.log(data);
// Malformed?
if (data['frames'])
{
var file = this._fileList[key];
this._game.cache.addTextureAtlas(file.key, file.url, file.data, data['frames']);
}
this.nextFile(key, true);
}
private jsonLoadError(key: string) {
//console.log('json load error');
var file = this._fileList[key];
file.error = true;
this.nextFile(key, true);
}
private nextFile(previousKey: string, success: bool) {
this.progress = Math.round(this.progress + this._progressChunk);
if (this._onFileLoad)
{
this._onFileLoad.call(this._game.callbackContext, this.progress, previousKey, success);
}
if (this._keys.length > 0)
{
this.loadFile();
}
else
{
this.hasLoaded = true;
this.removeAll();
this._gameCreateComplete.call(this._game);
if (this._onComplete !== null)
{
this._onComplete.call(this._game.callbackContext);
}
}
}
}

403
Phaser/Motion.ts Normal file
View file

@ -0,0 +1,403 @@
/// <reference path="Game.ts" />
/// <reference path="gameobjects/GameObject.ts" />
/**
* Phaser - Motion
*/
module Phaser {
export class Motion {
constructor(game: Game) {
this._game = game;
}
private _game: Game;
/**
* A tween-like function that takes a starting velocity
* and some other factors and returns an altered velocity.
*
* @param Velocity Any component of velocity (e.g. 20).
* @param Acceleration Rate at which the velocity is changing.
* @param Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set.
* @param Max An absolute value cap for the velocity.
*
* @return The altered Velocity value.
*/
public computeVelocity(Velocity: number, Acceleration: number = 0, Drag: number = 0, Max: number = 10000): number {
if (Acceleration !== 0)
{
Velocity += Acceleration * this._game.time.elapsed;
}
else if (Drag !== 0)
{
var drag: number = Drag * this._game.time.elapsed;
if (Velocity - drag > 0)
{
Velocity = Velocity - drag;
}
else if (Velocity + drag < 0)
{
Velocity += drag;
}
else
{
Velocity = 0;
}
}
if ((Velocity != 0) && (Max != 10000))
{
if (Velocity > Max)
{
Velocity = Max;
}
else if (Velocity < -Max)
{
Velocity = -Max;
}
}
return Velocity;
}
/**
* Given the angle and speed calculate the velocity and return it as a Point
*
* @param angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
* @param speed The speed it will move, in pixels per second sq
*
* @return A Point where Point.x contains the velocity x value and Point.y contains the velocity y value
*/
public velocityFromAngle(angle: number, speed: number): Point {
var a: number = this._game.math.degreesToRadians(angle);
return new Point((Math.cos(a) * speed), (Math.sin(a) * speed));
}
/**
* Sets the source Sprite x/y velocity so it will move directly towards the destination Sprite at the speed given (in pixels per second)<br>
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.<br>
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<br>
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
* If you need the object to accelerate, see accelerateTowardsObject() instead
* Note: Doesn't take into account acceleration, maxVelocity or drag (if you set drag or acceleration too high this object may not move at all)
*
* @param source The Sprite on which the velocity will be set
* @param dest The Sprite where the source object will move to
* @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*/
public moveTowardsObject(source:GameObject, dest:GameObject, speed:number= 60, maxTime:number = 0)
{
var a:number = this.angleBetween(source, dest);
if (maxTime > 0)
{
var d:number = this.distanceBetween(source, dest);
// We know how many pixels we need to move, but how fast?
speed = d / (maxTime / 1000);
}
source.velocity.x = Math.cos(a) * speed;
source.velocity.y = Math.sin(a) * speed;
}
/**
* Sets the x/y acceleration on the source Sprite so it will move towards the destination Sprite at the speed given (in pixels per second)<br>
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
* If you don't need acceleration look at moveTowardsObject() instead.
*
* @param source The Sprite on which the acceleration will be set
* @param dest The Sprite where the source object will move towards
* @param speed The speed it will accelerate in pixels per second
* @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*/
public accelerateTowardsObject(source:GameObject, dest:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
{
var a:number = this.angleBetween(source, dest);
source.velocity.x = 0;
source.velocity.y = 0;
source.acceleration.x = Math.cos(a) * speed;
source.acceleration.y = Math.sin(a) * speed;
source.maxVelocity.x = xSpeedMax;
source.maxVelocity.y = ySpeedMax;
}
/**
* Move the given Sprite towards the mouse pointer coordinates at a steady velocity
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.<br>
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<br>
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
*
* @param source The Sprite to move
* @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*/
public moveTowardsMouse(source:GameObject, speed:number = 60, maxTime:number = 0)
{
var a:number = this.angleBetweenMouse(source);
if (maxTime > 0)
{
var d:number = this.distanceToMouse(source);
// We know how many pixels we need to move, but how fast?
speed = d / (maxTime / 1000);
}
source.velocity.x = Math.cos(a) * speed;
source.velocity.y = Math.sin(a) * speed;
}
/**
* Sets the x/y acceleration on the source Sprite so it will move towards the mouse coordinates at the speed given (in pixels per second)<br>
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
* If you don't need acceleration look at moveTowardsMouse() instead.
*
* @param source The Sprite on which the acceleration will be set
* @param speed The speed it will accelerate in pixels per second
* @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*/
public accelerateTowardsMouse(source:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
{
var a:number = this.angleBetweenMouse(source);
source.velocity.x = 0;
source.velocity.y = 0;
source.acceleration.x = Math.cos(a) * speed;
source.acceleration.y = Math.sin(a) * speed;
source.maxVelocity.x = xSpeedMax;
source.maxVelocity.y = ySpeedMax;
}
/**
* Sets the x/y velocity on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)<br>
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.<br>
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<br>
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
*
* @param source The Sprite to move
* @param target The Point coordinates to move the source Sprite towards
* @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms
*/
public moveTowardsPoint(source:GameObject, target:Point, speed:number = 60, maxTime:number = 0)
{
var a:number = this.angleBetweenPoint(source, target);
if (maxTime > 0)
{
var d:number = this.distanceToPoint(source, target);
// We know how many pixels we need to move, but how fast?
speed = d / (maxTime / 1000);
}
source.velocity.x = Math.cos(a) * speed;
source.velocity.y = Math.sin(a) * speed;
}
/**
* Sets the x/y acceleration on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)<br>
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
* If you don't need acceleration look at moveTowardsPoint() instead.
*
* @param source The Sprite on which the acceleration will be set
* @param target The Point coordinates to move the source Sprite towards
* @param speed The speed it will accelerate in pixels per second
* @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
*/
public accelerateTowardsPoint(source:GameObject, target:Point, speed:number, xSpeedMax:number, ySpeedMax:number)
{
var a:number = this.angleBetweenPoint(source, target);
source.velocity.x = 0;
source.velocity.y = 0;
source.acceleration.x = Math.cos(a) * speed;
source.acceleration.y = Math.sin(a) * speed;
source.maxVelocity.x = xSpeedMax;
source.maxVelocity.y = ySpeedMax;
}
/**
* Find the distance (in pixels, rounded) between two Sprites, taking their origin into account
*
* @param a The first Sprite
* @param b The second Sprite
* @return int Distance (in pixels)
*/
public distanceBetween(a:GameObject, b:GameObject):number
{
var dx:number = (a.x + a.origin.x) - (b.x + b.origin.x);
var dy:number = (a.y + a.origin.y) - (b.y + b.origin.y);
return this._game.math.vectorLength(dx, dy);
}
/**
* Find the distance (in pixels, rounded) from an Sprite to the given Point, taking the source origin into account
*
* @param a The Sprite
* @param target The Point
* @return int Distance (in pixels)
*/
public distanceToPoint(a:GameObject, target:Point):number
{
var dx:number = (a.x + a.origin.x) - (target.x);
var dy:number = (a.y + a.origin.y) - (target.y);
return this._game.math.vectorLength(dx, dy);
}
/**
* Find the distance (in pixels, rounded) from the object x/y and the mouse x/y
*
* @param a The Sprite to test against
* @return int The distance between the given sprite and the mouse coordinates
*/
public distanceToMouse(a:GameObject):number
{
var dx: number = (a.x + a.origin.x) - this._game.input.x;
var dy: number = (a.y + a.origin.y) - this._game.input.y;
return this._game.math.vectorLength(dx, dy);
}
/**
* Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account.
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
*
* @param a The Sprite to test from
* @param target The Point to angle the Sprite towards
* @param asDegrees If you need the value in degrees instead of radians, set to true
*
* @return Number The angle (in radians unless asDegrees is true)
*/
public angleBetweenPoint(a:GameObject, target:Point, asDegrees:bool = false):number
{
var dx:number = (target.x) - (a.x + a.origin.x);
var dy:number = (target.y) - (a.y + a.origin.y);
if (asDegrees)
{
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
}
else
{
return Math.atan2(dy, dx);
}
}
/**
* Find the angle (in radians) between the two Sprite, taking their x/y and origin into account.
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
*
* @param a The Sprite to test from
* @param b The Sprite to test to
* @param asDegrees If you need the value in degrees instead of radians, set to true
*
* @return Number The angle (in radians unless asDegrees is true)
*/
public angleBetween(a:GameObject, b:GameObject, asDegrees:bool = false):number
{
var dx:number = (b.x + b.origin.x) - (a.x + a.origin.x);
var dy:number = (b.y + b.origin.y) - (a.y + a.origin.y);
if (asDegrees)
{
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
}
else
{
return Math.atan2(dy, dx);
}
}
/**
* Given the GameObject and speed calculate the velocity and return it as an Point based on the direction the sprite is facing
*
* @param parent The Sprite to get the facing value from
* @param speed The speed it will move, in pixels per second sq
*
* @return An Point where Point.x contains the velocity x value and Point.y contains the velocity y value
*/
public velocityFromFacing(parent:GameObject, speed:number):Point
{
var a:number;
if (parent.facing == Collision.LEFT)
{
a = this._game.math.degreesToRadians(180);
}
else if (parent.facing == Collision.RIGHT)
{
a = this._game.math.degreesToRadians(0);
}
else if (parent.facing == Collision.UP)
{
a = this._game.math.degreesToRadians(-90);
}
else if (parent.facing == Collision.DOWN)
{
a = this._game.math.degreesToRadians(90);
}
return new Point(Math.cos(a) * speed, Math.sin(a) * speed);
}
/**
* Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account.
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
*
* @param a The Object to test from
* @param asDegrees If you need the value in degrees instead of radians, set to true
*
* @return Number The angle (in radians unless asDegrees is true)
*/
public angleBetweenMouse(a:GameObject, asDegrees:bool = false):number
{
// In order to get the angle between the object and mouse, we need the objects screen coordinates (rather than world coordinates)
var p:Point = a.getScreenXY();
var dx:number = a._game.input.x - p.x;
var dy:number = a._game.input.y - p.y;
if (asDegrees)
{
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
}
else
{
return Math.atan2(dy, dx);
}
}
}
}

View file

@ -1,104 +0,0 @@
/// <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
*/
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 & GameObject.FLOOR)
{
this.drag.x = this.friction;
if (!(this.wasTouching & GameObject.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() {
}
}

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -46,31 +46,32 @@
<TypeScriptTarget>ES5</TypeScriptTarget>
<TypeScriptIncludeComments>true</TypeScriptIncludeComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
<TypeScriptOutFile>phaser.js</TypeScriptOutFile>
<TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TypeScriptTarget>ES5</TypeScriptTarget>
<TypeScriptIncludeComments>false</TypeScriptIncludeComments>
<TypeScriptSourceMap>true</TypeScriptSourceMap>
<TypeScriptOutFile>phaser.js</TypeScriptOutFile>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
<TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile>
</PropertyGroup>
<ItemGroup>
<TypeScriptCompile Include="Phaser.ts" />
<TypeScriptCompile Include="Animations.ts" />
<TypeScriptCompile Include="Basic.ts" />
<TypeScriptCompile Include="Cache.ts" />
<TypeScriptCompile Include="Cameras.ts" />
<TypeScriptCompile Include="Emitter.ts" />
<TypeScriptCompile Include="gameobjects\Emitter.ts" />
<TypeScriptCompile Include="Game.ts" />
<TypeScriptCompile Include="GameMath.ts" />
<TypeScriptCompile Include="GameObject.ts" />
<TypeScriptCompile Include="gameobjects\GameObject.ts" />
<TypeScriptCompile Include="Group.ts" />
<TypeScriptCompile Include="Loader.ts" />
<TypeScriptCompile Include="Particle.ts" />
<TypeScriptCompile Include="gameobjects\Particle.ts" />
<TypeScriptCompile Include="geom\Circle.ts" />
<TypeScriptCompile Include="geom\Point.ts" />
<TypeScriptCompile Include="geom\Rectangle.ts" />
<TypeScriptCompile Include="Sound.ts" />
<TypeScriptCompile Include="Sprite.ts" />
<TypeScriptCompile Include="gameobjects\Sprite.ts" />
<TypeScriptCompile Include="Stage.ts" />
<TypeScriptCompile Include="State.ts" />
<TypeScriptCompile Include="Signal.ts" />
@ -93,21 +94,35 @@
<TypeScriptCompile Include="system\StageScaleMode.ts" />
<TypeScriptCompile Include="system\Tile.ts" />
<TypeScriptCompile Include="system\TilemapBuffer.ts" />
<TypeScriptCompile Include="Tilemap.ts" />
<TypeScriptCompile Include="gameobjects\Tilemap.ts" />
<TypeScriptCompile Include="Time.ts" />
<TypeScriptCompile Include="World.ts" />
</ItemGroup>
<ItemGroup>
<TypeScriptCompile Include="DynamicTexture.ts" />
<TypeScriptCompile Include="Collision.ts" />
<TypeScriptCompile Include="system\Tween.ts" />
<TypeScriptCompile Include="geom\Line.ts" />
<TypeScriptCompile Include="gameobjects\GeomSprite.ts" />
<TypeScriptCompile Include="geom\IntersectResult.ts" />
<TypeScriptCompile Include="Motion.ts" />
<TypeScriptCompile Include="TweenManager.ts" />
<TypeScriptCompile Include="system\easing\Back.ts" />
<TypeScriptCompile Include="system\easing\Bounce.ts" />
<TypeScriptCompile Include="system\easing\Circular.ts" />
<TypeScriptCompile Include="system\easing\Cubic.ts" />
<TypeScriptCompile Include="system\easing\Elastic.ts" />
<TypeScriptCompile Include="system\easing\Exponential.ts" />
<TypeScriptCompile Include="system\easing\Linear.ts" />
<TypeScriptCompile Include="system\easing\Quadratic.ts" />
<TypeScriptCompile Include="system\easing\Quartic.ts" />
<TypeScriptCompile Include="system\easing\Quintic.ts" />
<TypeScriptCompile Include="system\easing\Sinusoidal.ts" />
</ItemGroup>
<ItemGroup>
<Content Include="DynamicTexture.js">
<DependentUpon>DynamicTexture.ts</DependentUpon>
</Content>
<Folder Include="plugins\" />
</ItemGroup>
<Import Project="$(VSToolsPath)\TypeScript\Microsoft.TypeScript.targets" />
<PropertyGroup>
<PostBuildEvent>cd $(ProjectDir)
copy $(ProjectDir)phaser.js ..\Tests\</PostBuildEvent>
<PostBuildEvent>cd $(ProjectDir)..\build
copy phaser.js ..\Tests\</PostBuildEvent>
</PropertyGroup>
</Project>

20
Phaser/Phaser.ts Normal file
View file

@ -0,0 +1,20 @@
/**
* Phaser
*
* v0.9 - April 18th 2013
*
* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi.
*
* Richard Davey (@photonstorm)
* Adam Saltsman (@ADAMATOMIC) (original Flixel code)
*
* "If you want your children to be intelligent, read them fairy tales."
* "If you want them to be more intelligent, read them more fairy tales."
* -- Albert Einstein
*/
module Phaser {
export var VERSION: string = 'Phaser version 0.9';
}

View file

@ -21,316 +21,324 @@
* @author Miller Medeiros
* @constructor
*/
class Signal {
/**
*
* @property _bindings
* @type Array
* @private
*/
private _bindings: SignalBinding[] = [];
/**
* Phaser
*/
/**
*
* @property _prevParams
* @type Any
* @private
*/
private _prevParams = null;
module Phaser {
/**
* Signals Version Number
* @property VERSION
* @type String
* @const
*/
public static VERSION: string = '1.0.0';
export class Signal {
/**
* If Signal should keep record of previously dispatched parameters and
* automatically execute listener during `add()`/`addOnce()` if Signal was
* already dispatched before.
* @type boolean
*/
public memorize: bool = false;
/**
*
* @property _bindings
* @type Array
* @private
*/
private _bindings: SignalBinding[] = [];
/**
* @type boolean
* @private
*/
private _shouldPropagate: bool = true;
/**
*
* @property _prevParams
* @type Any
* @private
*/
private _prevParams = null;
/**
* If Signal is active and should broadcast events.
* <p><strong>IMPORTANT:</strong> Setting this property during a dispatch will only affect the next dispatch, if you want to stop the propagation of a signal use `halt()` instead.</p>
* @type boolean
*/
public active: bool = true;
/**
* Signals Version Number
* @property VERSION
* @type String
* @const
*/
public static VERSION: string = '1.0.0';
/**
*
* @method validateListener
* @param {Any} listener
* @param {Any} fnName
*/
public validateListener(listener, fnName) {
/**
* If Signal should keep record of previously dispatched parameters and
* automatically execute listener during `add()`/`addOnce()` if Signal was
* already dispatched before.
* @type boolean
*/
public memorize: bool = false;
if (typeof listener !== 'function')
{
throw new Error('listener is a required param of {fn}() and should be a Function.'.replace('{fn}', fnName));
}
/**
* @type boolean
* @private
*/
private _shouldPropagate: bool = true;
}
/**
* If Signal is active and should broadcast events.
* <p><strong>IMPORTANT:</strong> Setting this property during a dispatch will only affect the next dispatch, if you want to stop the propagation of a signal use `halt()` instead.</p>
* @type boolean
*/
public active: bool = true;
/**
* @param {Function} listener
* @param {boolean} isOnce
* @param {Object} [listenerContext]
* @param {Number} [priority]
* @return {SignalBinding}
* @private
*/
private _registerListener(listener, isOnce: bool, listenerContext, priority: number): SignalBinding {
/**
*
* @method validateListener
* @param {Any} listener
* @param {Any} fnName
*/
public validateListener(listener, fnName) {
var prevIndex: number = this._indexOfListener(listener, listenerContext);
var binding: SignalBinding;
if (prevIndex !== -1)
{
binding = this._bindings[prevIndex];
if (binding.isOnce() !== isOnce)
if (typeof listener !== 'function')
{
throw new Error('You cannot add' + (isOnce ? '' : 'Once') + '() then add' + (!isOnce ? '' : 'Once') + '() the same listener without removing the relationship first.');
throw new Error('listener is a required param of {fn}() and should be a Function.'.replace('{fn}', fnName));
}
}
else
{
binding = new SignalBinding(this, listener, isOnce, listenerContext, priority);
this._addBinding(binding);
}
if (this.memorize && this._prevParams)
{
binding.execute(this._prevParams);
}
/**
* @param {Function} listener
* @param {boolean} isOnce
* @param {Object} [listenerContext]
* @param {Number} [priority]
* @return {SignalBinding}
* @private
*/
private _registerListener(listener, isOnce: bool, listenerContext, priority: number): SignalBinding {
return binding;
var prevIndex: number = this._indexOfListener(listener, listenerContext);
var binding: SignalBinding;
}
/**
*
* @method _addBinding
* @param {SignalBinding} binding
* @private
*/
private _addBinding(binding: SignalBinding) {
//simplified insertion sort
var n: number = this._bindings.length;
do { --n; } while (this._bindings[n] && binding.priority <= this._bindings[n].priority);
this._bindings.splice(n + 1, 0, binding);
}
/**
*
* @method _indexOfListener
* @param {Function} listener
* @return {number}
* @private
*/
private _indexOfListener(listener, context): number {
var n: number = this._bindings.length;
var cur: SignalBinding;
while (n--)
{
cur = this._bindings[n];
if (cur.getListener() === listener && cur.context === context)
if (prevIndex !== -1)
{
return n;
binding = this._bindings[prevIndex];
if (binding.isOnce() !== isOnce)
{
throw new Error('You cannot add' + (isOnce ? '' : 'Once') + '() then add' + (!isOnce ? '' : 'Once') + '() the same listener without removing the relationship first.');
}
}
else
{
binding = new SignalBinding(this, listener, isOnce, listenerContext, priority);
this._addBinding(binding);
}
if (this.memorize && this._prevParams)
{
binding.execute(this._prevParams);
}
return binding;
}
return -1;
/**
*
* @method _addBinding
* @param {SignalBinding} binding
* @private
*/
private _addBinding(binding: SignalBinding) {
}
//simplified insertion sort
/**
* Check if listener was attached to Signal.
* @param {Function} listener
* @param {Object} [context]
* @return {boolean} if Signal has the specified listener.
*/
public has(listener, context?: any = null): bool {
var n: number = this._bindings.length;
return this._indexOfListener(listener, context) !== -1;
do { --n; } while (this._bindings[n] && binding.priority <= this._bindings[n].priority);
}
this._bindings.splice(n + 1, 0, binding);
/**
* Add a listener to the signal.
* @param {Function} listener Signal handler function.
* @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function).
* @param {Number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0)
* @return {SignalBinding} An Object representing the binding between the Signal and listener.
*/
public add(listener, listenerContext?: any = null, priority?: number = 0): SignalBinding {
this.validateListener(listener, 'add');
return this._registerListener(listener, false, listenerContext, priority);
}
/**
* Add listener to the signal that should be removed after first execution (will be executed only once).
* @param {Function} listener Signal handler function.
* @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function).
* @param {Number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0)
* @return {SignalBinding} An Object representing the binding between the Signal and listener.
*/
public addOnce(listener, listenerContext?: any = null, priority?: number = 0): SignalBinding {
this.validateListener(listener, 'addOnce');
return this._registerListener(listener, true, listenerContext, priority);
}
/**
* Remove a single listener from the dispatch queue.
* @param {Function} listener Handler function that should be removed.
* @param {Object} [context] Execution context (since you can add the same handler multiple times if executing in a different context).
* @return {Function} Listener handler function.
*/
public remove(listener, context?: any = null) {
this.validateListener(listener, 'remove');
var i: number = this._indexOfListener(listener, context);
if (i !== -1)
{
this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal
this._bindings.splice(i, 1);
}
return listener;
/**
*
* @method _indexOfListener
* @param {Function} listener
* @return {number}
* @private
*/
private _indexOfListener(listener, context): number {
}
var n: number = this._bindings.length;
var cur: SignalBinding;
/**
* Remove all listeners from the Signal.
*/
public removeAll() {
while (n--)
{
cur = this._bindings[n];
var n: number = this._bindings.length;
if (cur.getListener() === listener && cur.context === context)
{
return n;
}
}
return -1;
while (n--)
{
this._bindings[n]._destroy();
}
this._bindings.length = 0;
/**
* Check if listener was attached to Signal.
* @param {Function} listener
* @param {Object} [context]
* @return {boolean} if Signal has the specified listener.
*/
public has(listener, context?: any = null): bool {
}
return this._indexOfListener(listener, context) !== -1;
/**
* @return {number} Number of listeners attached to the Signal.
*/
public getNumListeners(): number {
return this._bindings.length;
}
/**
* Stop propagation of the event, blocking the dispatch to next listeners on the queue.
* <p><strong>IMPORTANT:</strong> should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast.</p>
* @see Signal.prototype.disable
*/
public halt() {
this._shouldPropagate = false;
}
/**
* Dispatch/Broadcast Signal to all listeners added to the queue.
* @param {...*} [params] Parameters that should be passed to each handler.
*/
public dispatch(...paramsArr: any[]) {
if (!this.active)
{
return;
}
var n: number = this._bindings.length;
var bindings: SignalBinding[];
/**
* Add a listener to the signal.
* @param {Function} listener Signal handler function.
* @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function).
* @param {Number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0)
* @return {SignalBinding} An Object representing the binding between the Signal and listener.
*/
public add(listener, listenerContext?: any = null, priority?: number = 0): SignalBinding {
this.validateListener(listener, 'add');
return this._registerListener(listener, false, listenerContext, priority);
if (this.memorize)
{
this._prevParams = paramsArr;
}
if (!n)
{
//should come after memorize
return;
/**
* Add listener to the signal that should be removed after first execution (will be executed only once).
* @param {Function} listener Signal handler function.
* @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function).
* @param {Number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0)
* @return {SignalBinding} An Object representing the binding between the Signal and listener.
*/
public addOnce(listener, listenerContext?: any = null, priority?: number = 0): SignalBinding {
this.validateListener(listener, 'addOnce');
return this._registerListener(listener, true, listenerContext, priority);
}
bindings = this._bindings.slice(0); //clone array in case add/remove items during dispatch
/**
* Remove a single listener from the dispatch queue.
* @param {Function} listener Handler function that should be removed.
* @param {Object} [context] Execution context (since you can add the same handler multiple times if executing in a different context).
* @return {Function} Listener handler function.
*/
public remove(listener, context?: any = null) {
this._shouldPropagate = true; //in case `halt` was called before dispatch or during the previous dispatch.
this.validateListener(listener, 'remove');
//execute all callbacks until end of the list or until a callback returns `false` or stops propagation
//reverse loop since listeners with higher priority will be added at the end of the list
do { n--; } while (bindings[n] && this._shouldPropagate && bindings[n].execute(paramsArr) !== false);
var i: number = this._indexOfListener(listener, context);
if (i !== -1)
{
this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal
this._bindings.splice(i, 1);
}
return listener;
}
/**
* Remove all listeners from the Signal.
*/
public removeAll() {
var n: number = this._bindings.length;
while (n--)
{
this._bindings[n]._destroy();
}
this._bindings.length = 0;
}
/**
* @return {number} Number of listeners attached to the Signal.
*/
public getNumListeners(): number {
return this._bindings.length;
}
/**
* Stop propagation of the event, blocking the dispatch to next listeners on the queue.
* <p><strong>IMPORTANT:</strong> should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast.</p>
* @see Signal.prototype.disable
*/
public halt() {
this._shouldPropagate = false;
}
/**
* Dispatch/Broadcast Signal to all listeners added to the queue.
* @param {...*} [params] Parameters that should be passed to each handler.
*/
public dispatch(...paramsArr: any[]) {
if (!this.active)
{
return;
}
var n: number = this._bindings.length;
var bindings: SignalBinding[];
if (this.memorize)
{
this._prevParams = paramsArr;
}
if (!n)
{
//should come after memorize
return;
}
bindings = this._bindings.slice(0); //clone array in case add/remove items during dispatch
this._shouldPropagate = true; //in case `halt` was called before dispatch or during the previous dispatch.
//execute all callbacks until end of the list or until a callback returns `false` or stops propagation
//reverse loop since listeners with higher priority will be added at the end of the list
do { n--; } while (bindings[n] && this._shouldPropagate && bindings[n].execute(paramsArr) !== false);
}
/**
* Forget memorized arguments.
* @see Signal.memorize
*/
public forget() {
this._prevParams = null;
}
/**
* Remove all bindings from signal and destroy any reference to external objects (destroy Signal object).
* <p><strong>IMPORTANT:</strong> calling any method on the signal instance after calling dispose will throw errors.</p>
*/
public dispose() {
this.removeAll();
delete this._bindings;
delete this._prevParams;
}
/**
* @return {string} String representation of the object.
*/
public toString(): string {
return '[Signal active:' + this.active + ' numListeners:' + this.getNumListeners() + ']';
}
}
/**
* Forget memorized arguments.
* @see Signal.memorize
*/
public forget() {
this._prevParams = null;
}
/**
* Remove all bindings from signal and destroy any reference to external objects (destroy Signal object).
* <p><strong>IMPORTANT:</strong> calling any method on the signal instance after calling dispose will throw errors.</p>
*/
public dispose() {
this.removeAll();
delete this._bindings;
delete this._prevParams;
}
/**
* @return {string} String representation of the object.
*/
public toString(): string {
return '[Signal active:' + this.active + ' numListeners:' + this.getNumListeners() + ']';
}
}
}

View file

@ -14,7 +14,13 @@
*
*/
class SignalBinding {
/**
* Phaser
*/
module Phaser {
export class SignalBinding {
/**
* Object that represents a binding between a Signal and a listener function.
@ -184,3 +190,4 @@
}
}

View file

@ -1,219 +1,233 @@
class SoundManager {
/// <reference path="Game.ts" />
constructor(game:Game) {
/**
* Phaser
*/
this._game = game;
module Phaser {
if (game.device.webaudio == true)
{
if (!!window['AudioContext'])
{
this._context = new window['AudioContext']();
}
else if (!!window['webkitAudioContext'])
{
this._context = new window['webkitAudioContext']();
}
export class SoundManager {
constructor(game: Game) {
this._game = game;
if (game.device.webaudio == true)
{
if (!!window['AudioContext'])
{
this._context = new window['AudioContext']();
}
else if (!!window['webkitAudioContext'])
{
this._context = new window['webkitAudioContext']();
}
if (this._context !== null)
{
this._gainNode = this._context.createGainNode();
this._gainNode.connect(this._context.destination);
this._volume = 1;
}
}
if (this._context !== null)
{
this._gainNode = this._context.createGainNode();
this._gainNode.connect(this._context.destination);
this._volume = 1;
}
}
}
private _game: Game;
private _game: Game;
private _context = null;
private _gainNode;
private _volume: number;
private _context = null;
private _gainNode;
private _volume: number;
public mute() {
public mute() {
this._gainNode.gain.value = 0;
this._gainNode.gain.value = 0;
}
public unmute() {
this._gainNode.gain.value = this._volume;
}
public set volume(value: number) {
this._volume = value;
this._gainNode.gain.value = this._volume;
}
public get volume(): number {
return this._volume;
}
public decode(key: string, callback = null, sound?: Sound = null) {
var soundData = this._game.cache.getSound(key);
if (soundData)
{
if (this._game.cache.isSoundDecoded(key) === false)
{
var that = this;
this._context.decodeAudioData(soundData, function (buffer) {
that._game.cache.decodedSound(key, buffer);
if (sound)
{
sound.setDecodedBuffer(buffer);
}
callback();
});
}
}
}
public unmute() {
public play(key:string, volume?: number = 1, loop?: bool = false): Sound {
this._gainNode.gain.value = this._volume;
if (this._context === null)
{
return;
}
var soundData = this._game.cache.getSound(key);
public set volume(value: number) {
if (soundData)
{
// Does the sound need decoding?
if (this._game.cache.isSoundDecoded(key) === true)
this._volume = value;
this._gainNode.gain.value = this._volume;
}
public get volume(): number {
return this._volume;
}
public decode(key: string, callback = null, sound?: Sound = null) {
var soundData = this._game.cache.getSound(key);
if (soundData)
{
return new Sound(this._context, this._gainNode, soundData, volume, loop);
if (this._game.cache.isSoundDecoded(key) === false)
{
var that = this;
this._context.decodeAudioData(soundData, function (buffer) {
that._game.cache.decodedSound(key, buffer);
if (sound)
{
sound.setDecodedBuffer(buffer);
}
callback();
});
}
}
else
}
public play(key: string, volume?: number = 1, loop?: bool = false): Sound {
if (this._context === null)
{
var tempSound: Sound = new Sound(this._context, this._gainNode, null, volume, loop);
// this is an async process, so we can return the Sound object anyway, it just won't be playing yet
this.decode(key, () => this.play(key), tempSound);
return tempSound;
return;
}
var soundData = this._game.cache.getSound(key);
if (soundData)
{
// Does the sound need decoding?
if (this._game.cache.isSoundDecoded(key) === true)
{
return new Sound(this._context, this._gainNode, soundData, volume, loop);
}
else
{
var tempSound: Sound = new Sound(this._context, this._gainNode, null, volume, loop);
// this is an async process, so we can return the Sound object anyway, it just won't be playing yet
this.decode(key, () => this.play(key), tempSound);
return tempSound;
}
}
}
}
}
class Sound {
module Phaser {
constructor(context, gainNode, data, volume?: number = 1, loop?: bool = false) {
export class Sound {
this._context = context;
this._gainNode = gainNode;
this._buffer = data;
this._volume = volume;
this.loop = loop;
constructor(context, gainNode, data, volume?: number = 1, loop?: bool = false) {
this._context = context;
this._gainNode = gainNode;
this._buffer = data;
this._volume = volume;
this.loop = loop;
// Local volume control
if (this._context !== null)
{
this._localGainNode = this._context.createGainNode();
this._localGainNode.connect(this._gainNode);
this._localGainNode.gain.value = this._volume;
}
if (this._buffer === null)
{
this.isDecoding = true;
}
else
{
this.play();
}
// Local volume control
if (this._context !== null)
{
this._localGainNode = this._context.createGainNode();
this._localGainNode.connect(this._gainNode);
this._localGainNode.gain.value = this._volume;
}
if (this._buffer === null)
{
this.isDecoding = true;
}
else
{
private _context;
private _gainNode;
private _localGainNode;
private _buffer;
private _volume: number;
private _sound;
loop: bool = false;
duration: number;
isPlaying: bool = false;
isDecoding: bool = false;
public setDecodedBuffer(data) {
this._buffer = data;
this.isDecoding = false;
this.play();
}
}
public play() {
private _context;
private _gainNode;
private _localGainNode;
private _buffer;
private _volume: number;
private _sound;
if (this._buffer === null || this.isDecoding === true)
{
return;
}
loop: bool = false;
duration: number;
isPlaying: bool = false;
isDecoding: bool = false;
this._sound = this._context.createBufferSource();
this._sound.buffer = this._buffer;
this._sound.connect(this._localGainNode);
public setDecodedBuffer(data) {
if (this.loop)
{
this._sound.loop = true;
}
this._buffer = data;
this.isDecoding = false;
this.play();
this._sound.noteOn(0); // the zero is vitally important, crashes iOS6 without it
}
this.duration = this._sound.buffer.duration;
this.isPlaying = true;
public play() {
}
if (this._buffer === null || this.isDecoding === true)
{
return;
}
public stop() {
this._sound = this._context.createBufferSource();
this._sound.buffer = this._buffer;
this._sound.connect(this._localGainNode);
if (this.isPlaying === true)
{
this.isPlaying = false;
if (this.loop)
{
this._sound.loop = true;
}
this._sound.noteOff(0);
}
this._sound.noteOn(0); // the zero is vitally important, crashes iOS6 without it
}
this.duration = this._sound.buffer.duration;
this.isPlaying = true;
public mute() {
}
this._localGainNode.gain.value = 0;
public stop () {
}
if (this.isPlaying === true)
{
this.isPlaying = false;
public unmute() {
this._sound.noteOff(0);
}
this._localGainNode.gain.value = this._volume;
}
}
public mute() {
public set volume(value: number) {
this._localGainNode.gain.value = 0;
this._volume = value;
this._localGainNode.gain.value = this._volume;
}
}
public unmute() {
public get volume(): number {
return this._volume;
}
this._localGainNode.gain.value = this._volume;
}
public set volume(value: number) {
this._volume = value;
this._localGainNode.gain.value = this._volume;
}
public get volume(): number {
return this._volume;
}
}

View file

@ -1,273 +0,0 @@
/// <reference path="Animations.ts" />
/// <reference path="DynamicTexture.ts" />
/// <reference path="GameObject.ts" />
/// <reference path="Game.ts" />
/// <reference path="GameMath.ts" />
/// <reference path="geom/Rectangle.ts" />
/// <reference path="geom/Point.ts" />
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._dy + (this._dh / 2));
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);
}
}

View file

@ -1,203 +1,233 @@
/// <reference path="Phaser.ts" />
/// <reference path="Game.ts" />
/// <reference path="geom/Point.ts" />
/// <reference path="geom/Rectangle.ts" />
/// <reference path="system/StageScaleMode.ts" />
class Stage {
/**
* Phaser
*/
constructor(game:Game, parent:string, width: number, height: number) {
module Phaser {
this._game = game;
export class Stage {
this.canvas = <HTMLCanvasElement> document.createElement('canvas');
this.canvas.width = width;
this.canvas.height = height;
constructor(game: Game, parent: string, width: number, height: number) {
this._game = game;
this.canvas = <HTMLCanvasElement> document.createElement('canvas');
this.canvas.width = width;
this.canvas.height = height;
if (document.getElementById(parent))
{
document.getElementById(parent).appendChild(this.canvas);
document.getElementById(parent).style.overflow = 'hidden';
}
else
{
document.body.appendChild(this.canvas);
}
this.context = this.canvas.getContext('2d');
this.offset = this.getOffset(this.canvas);
this.bounds = new Rectangle(this.offset.x, this.offset.y, width, height);
this.aspectRatio = width / height;
this.scaleMode = StageScaleMode.NO_SCALE;
this.scale = new StageScaleMode(this._game);
//document.addEventListener('visibilitychange', (event) => this.visibilityChange(event), false);
//document.addEventListener('webkitvisibilitychange', (event) => this.visibilityChange(event), false);
window.onblur = (event) => this.visibilityChange(event);
window.onfocus = (event) => this.visibilityChange(event);
if (document.getElementById(parent))
{
document.getElementById(parent).appendChild(this.canvas);
document.getElementById(parent).style.overflow = 'hidden';
}
else
{
document.body.appendChild(this.canvas);
}
this.context = this.canvas.getContext('2d');
this.offset = this.getOffset(this.canvas);
this.bounds = new Rectangle(this.offset.x, this.offset.y, width, height);
this.aspectRatio = width / height;
this.scaleMode = StageScaleMode.NO_SCALE;
this.scale = new StageScaleMode(this._game);
//document.addEventListener('visibilitychange', (event) => this.visibilityChange(event), false);
//document.addEventListener('webkitvisibilitychange', (event) => this.visibilityChange(event), false);
window.onblur = (event) => this.visibilityChange(event);
window.onfocus = (event) => this.visibilityChange(event);
}
private _game: Game;
private _bgColor: string;
private _game: Game;
private _bgColor: string;
public static ORIENTATION_LANDSCAPE:number = 0;
public static ORIENTATION_PORTRAIT:number = 1;
public static ORIENTATION_LANDSCAPE: number = 0;
public static ORIENTATION_PORTRAIT: number = 1;
public bounds: Rectangle;
public aspectRatio: number;
public clear: bool = true;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
public offset: Point;
public scale: StageScaleMode;
public scaleMode: number;
public minScaleX: number = null;
public maxScaleX: number = null;
public minScaleY: number = null;
public maxScaleY: number = null;
public update() {
public bounds: Rectangle;
public aspectRatio: number;
public clear: bool = true;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
public offset: Point;
public scale: StageScaleMode;
public scaleMode: number;
this.scale.update();
public minScaleX: number = null;
public maxScaleX: number = null;
public minScaleY: number = null;
public maxScaleY: number = null;
public update() {
this.scale.update();
if (this.clear)
{
// implement dirty rect? could take up more cpu time than it saves. needs benching.
this.context.clearRect(0, 0, this.width, this.height);
}
if (this.clear)
{
// implement dirty rect? could take up more cpu time than it saves. needs benching.
this.context.clearRect(0, 0, this.width, this.height);
}
}
public renderDebugInfo() {
public renderDebugInfo() {
this.context.fillStyle = 'rgb(255,255,255)';
this.context.fillText(Phaser.VERSION, 10, 20);
this.context.fillText('Game Size: ' + this.width + ' x ' + this.height, 10, 40);
this.context.fillText('x: ' + this.x + ' y: ' + this.y, 10, 60);
this.context.fillStyle = 'rgb(255,255,255)';
this.context.fillText(Game.VERSION, 10, 20);
this.context.fillText('Game Size: ' + this.width + ' x ' + this.height, 10, 40);
this.context.fillText('x: ' + this.x + ' y: ' + this.y, 10, 60);
}
private visibilityChange(event) {
if (event.type == 'blur' && this._game.pause == false && this._game.isBooted == true)
{
this._game.pause = true;
this.drawPauseScreen();
}
else if (event.type == 'focus')
{
this._game.pause = false;
}
//if (document['hidden'] === true || document['webkitHidden'] === true)
private visibilityChange(event) {
if (event.type == 'blur' && this._game.paused == false && this._game.isBooted == true)
{
this._game.paused = true;
this.drawPauseScreen();
}
else if (event.type == 'focus')
{
this._game.paused = false;
}
//if (document['hidden'] === true || document['webkitHidden'] === true)
}
public drawInitScreen() {
this.context.fillStyle = 'rgb(40, 40, 40)';
this.context.fillRect(0, 0, this.width, this.height);
this.context.fillStyle = 'rgb(255,255,255)';
this.context.font = 'bold 18px Arial';
this.context.textBaseline = 'top';
this.context.fillText(Phaser.VERSION, 54, 32);
this.context.fillText('Game Size: ' + this.width + ' x ' + this.height, 32, 64);
this.context.fillText('www.photonstorm.com', 32, 96);
this.context.font = '16px Arial';
this.context.fillText('You are seeing this screen because you didn\'t specify any default', 32, 160);
this.context.fillText('functions in the Game constructor, or use Game.loadState()', 32, 184);
var image = new Image();
var that = this;
image.onload = function () {
that.context.drawImage(image, 32, 32);
};
image.src = this._logo;
}
private drawPauseScreen() {
this.saveCanvasValues();
this.context.fillStyle = 'rgba(0, 0, 0, 0.4)';
this.context.fillRect(0, 0, this.width, this.height);
// Draw a 'play' arrow
var arrowWidth = Math.round(this.width / 2);
var arrowHeight = Math.round(this.height / 2);
var sx = this.centerX - arrowWidth / 2;
var sy = this.centerY - arrowHeight / 2;
this.context.beginPath();
this.context.moveTo(sx, sy);
this.context.lineTo(sx, sy + arrowHeight);
this.context.lineTo(sx + arrowWidth, this.centerY);
this.context.fillStyle = 'rgba(255, 255, 255, 0.8)';
this.context.fill();
this.context.closePath();
this.restoreCanvasValues();
}
private getOffset(element): Point {
var box = element.getBoundingClientRect();
var clientTop = element.clientTop || document.body.clientTop || 0;
var clientLeft = element.clientLeft || document.body.clientLeft || 0;
var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop;
var scrollLeft = window.pageXOffset || element.scrollLeft || document.body.scrollLeft;
return new Point(box.left + scrollLeft - clientLeft, box.top + scrollTop - clientTop);
}
public strokeStyle: string;
public lineWidth: number;
public fillStyle: string;
public saveCanvasValues() {
this.strokeStyle = this.context.strokeStyle;
this.lineWidth = this.context.lineWidth;
this.fillStyle = this.context.fillStyle;
}
public restoreCanvasValues() {
this.context.strokeStyle = this.strokeStyle;
this.context.lineWidth = this.lineWidth;
this.context.fillStyle = this.fillStyle;
}
public set backgroundColor(color: string) {
this.canvas.style.backgroundColor = color;
}
public get backgroundColor(): string {
return this._bgColor;
}
public get x(): number {
return this.bounds.x;
}
public get y(): number {
return this.bounds.y;
}
public get width(): number {
return this.bounds.width;
}
public get height(): number {
return this.bounds.height;
}
public get centerX(): number {
return this.bounds.halfWidth;
}
public get centerY(): number {
return this.bounds.halfHeight;
}
public get randomX(): number {
return Math.round(Math.random() * this.bounds.width);
}
public get randomY(): number {
return Math.round(Math.random() * this.bounds.height);
}
private _logo: string = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAO1JREFUeNpi/P//PwM6YGRkxBQEAqBaRnQxFmwa10d6MAjrMqMofHv5L1we2SBGmAtAktg0ogOQQYHLd8ANYYFpPtTmzUAMAFmwnsEDrAdkCAvMZlIAsiFMMAEYsKvaSrQhIMCELkGsV2AAbIC8gCQYgwKIUABiNYBf9yoYH7n7n6CzN274g2IYEyFbsNmKLIaSkHpP7WSwUfbA0ASzFQRslBlxp0RcAF0TRhggA3zhAJIDpUKU5A9KyshpHDkjFZu5g2nJMFcwXVJSgqIGnBKx5bKenh4w/XzVbgbPtlIUcVgSxuoCUgHIIIAAAwArtXwJBABO6QAAAABJRU5ErkJggg==";
}
public drawInitScreen() {
this.context.fillStyle = 'rgb(40, 40, 40)';
this.context.fillRect(0, 0, this.width, this.height);
this.context.fillStyle = 'rgb(255,255,255)';
this.context.font = 'bold 18px Arial';
this.context.textBaseline = 'top';
this.context.fillText(Game.VERSION, 54, 32);
this.context.fillText('Game Size: ' + this.width + ' x ' + this.height, 32, 64);
this.context.fillText('www.photonstorm.com', 32, 96);
this.context.font = '16px Arial';
this.context.fillText('You are seeing this screen because you didn\'t specify any default', 32, 160);
this.context.fillText('functions in the Game constructor, or use Game.loadState()', 32, 184);
var image = new Image();
var that = this;
image.onload = function() {
that.context.drawImage(image, 32, 32);
};
image.src = this._logo;
}
private drawPauseScreen() {
this.context.fillStyle = 'rgba(0, 0, 0, 0.4)';
this.context.fillRect(0, 0, this.width, this.height);
// Draw a 'play' arrow
var arrowWidth = Math.round(this.width / 2);
var arrowHeight = Math.round(this.height / 2);
var sx = this.centerX - arrowWidth / 2;
var sy = this.centerY - arrowHeight / 2;
this.context.beginPath();
this.context.moveTo(sx, sy);
this.context.lineTo(sx, sy + arrowHeight);
this.context.lineTo(sx + arrowWidth, this.centerY);
this.context.closePath();
this.context.fillStyle = 'rgba(255, 255, 255, 0.8)';
this.context.fill();
}
private getOffset(element):Point {
var box = element.getBoundingClientRect();
var clientTop = element.clientTop || document.body.clientTop || 0;
var clientLeft = element.clientLeft || document.body.clientLeft || 0;
var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop;
var scrollLeft = window.pageXOffset || element.scrollLeft || document.body.scrollLeft;
return new Point(box.left + scrollLeft - clientLeft, box.top + scrollTop - clientTop);
}
public set backgroundColor(color: string) {
this.canvas.style.backgroundColor = color;
}
public get backgroundColor():string {
return this._bgColor;
}
public get x(): number {
return this.bounds.x;
}
public get y(): number {
return this.bounds.y;
}
public get width(): number {
return this.bounds.width;
}
public get height(): number {
return this.bounds.height;
}
public get centerX(): number {
return this.bounds.halfWidth;
}
public get centerY(): number {
return this.bounds.halfHeight;
}
public get randomX(): number {
return Math.round(Math.random() * this.bounds.width);
}
public get randomY(): number {
return Math.round(Math.random() * this.bounds.height);
}
private _logo:string = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAO1JREFUeNpi/P//PwM6YGRkxBQEAqBaRnQxFmwa10d6MAjrMqMofHv5L1we2SBGmAtAktg0ogOQQYHLd8ANYYFpPtTmzUAMAFmwnsEDrAdkCAvMZlIAsiFMMAEYsKvaSrQhIMCELkGsV2AAbIC8gCQYgwKIUABiNYBf9yoYH7n7n6CzN274g2IYEyFbsNmKLIaSkHpP7WSwUfbA0ASzFQRslBlxp0RcAF0TRhggA3zhAJIDpUKU5A9KyshpHDkjFZu5g2nJMFcwXVJSgqIGnBKx5bKenh4w/XzVbgbPtlIUcVgSxuoCUgHIIIAAAwArtXwJBABO6QAAAABJRU5ErkJggg==";
}

View file

@ -1,71 +1,97 @@
/// <reference path="Game.ts" />
class State {
/**
* Phaser
*/
constructor(game: Game) {
module Phaser {
this.game = game;
export class State {
this.camera = game.camera;
this.cache = game.cache;
this.input = game.input;
this.loader = game.loader;
this.sound = game.sound;
this.stage = game.stage;
this.time = game.time;
this.math = game.math;
this.world = game.world;
constructor(game: Game) {
}
this.game = game;
public game: Game;
this.camera = game.camera;
this.cache = game.cache;
this.collision = game.collision;
this.input = game.input;
this.loader = game.loader;
this.math = game.math;
this.motion = game.motion;
this.sound = game.sound;
this.stage = game.stage;
this.time = game.time;
this.tweens = game.tweens;
this.world = game.world;
public camera: Camera;
public cache: Cache;
public input: Input;
public loader: Loader;
public sound: SoundManager;
public stage: Stage;
public time: Time;
public math: GameMath;
public world: World;
}
public game: Game;
public camera: Camera;
public cache: Cache;
public collision: Collision;
public input: Input;
public loader: Loader;
public math: GameMath;
public motion: Motion;
public sound: SoundManager;
public stage: Stage;
public time: Time;
public tweens: TweenManager;
public world: World;
// Overload these in your own States
public init() {}
public create() {}
public update() {}
public render() {}
public paused() {}
// Overload these in your own States
public init() { }
public create() { }
public update() { }
public render() { }
public paused() { }
// Handy Proxy methods
// Handy Proxy methods
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this.game.world.createCamera(x, y, width, height);
}
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this.game.world.createCamera(x, y, width, height);
}
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return this.game.world.createSprite(x, y, key);
}
public createGeomSprite(x: number, y: number): GeomSprite {
return this.world.createGeomSprite(x, y);
}
public createGroup(MaxSize?: number = 0): Group {
return this.game.world.createGroup(MaxSize);
}
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return this.game.world.createSprite(x, y, key);
}
public createParticle(): Particle {
return this.game.world.createParticle();
}
public createDynamicTexture(key: string, width: number, height: number): DynamicTexture {
return this.game.world.createDynamicTexture(key, width, height);
}
public createEmitter(x?: number = 0, y?: number = 0, size?:number = 0): Emitter {
return this.game.world.createEmitter(x, y, size);
}
public createGroup(MaxSize?: number = 0): Group {
return this.game.world.createGroup(MaxSize);
}
public createTilemap(key:string, mapData:string, format:number, tileWidth?:number,tileHeight?:number): Tilemap {
return this.game.world.createTilemap(key, mapData, format, tileWidth, tileHeight);
}
public createParticle(): Particle {
return this.game.world.createParticle();
}
public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return this.game.world.createEmitter(x, y, size);
}
public createTilemap(key: string, mapData: string, format: number, tileWidth?: number, tileHeight?: number): Tilemap {
return this.game.world.createTilemap(key, mapData, format, tileWidth, tileHeight);
}
public createTween(obj): Tween {
return this.game.tweens.create(obj);
}
public collide(ObjectOrGroup1: Basic = null, ObjectOrGroup2: Basic = null, NotifyCallback = null): bool {
return this.collision.overlap(ObjectOrGroup1, ObjectOrGroup2, NotifyCallback, Collision.separate);
}
public collide(ObjectOrGroup1: Basic = null, ObjectOrGroup2: Basic = null, NotifyCallback = null): bool {
return this.game.world.overlap(ObjectOrGroup1, ObjectOrGroup2, NotifyCallback, World.separate);
}
}

View file

@ -1,261 +0,0 @@
/// <reference path="Game.ts" />
/// <reference path="GameObject.ts" />
/// <reference path="geom/Point.ts" />
/// <reference path="geom/Rectangle.ts" />
/// <reference path="system/TilemapBuffer.ts" />
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;
}
}

View file

@ -1,129 +1,137 @@
/// <reference path="Game.ts" />
class Time {
/**
* Phaser
*/
constructor(game: Game) {
module Phaser {
this._started = Date.now();
this._timeLastSecond = this._started;
this.time = this._started;
export class Time {
}
constructor(game: Game) {
private _game: Game;
private _started: number;
this._started = Date.now();
this._timeLastSecond = this._started;
this.time = this._started;
public timeScale: number = 1.0;
public elapsed: number = 0;
/**
*
* @property time
* @type Number
*/
public time: number = 0;
/**
*
* @property now
* @type Number
*/
public now: number = 0;
/**
*
* @property delta
* @type Number
*/
public delta: number = 0;
/**
*
* @method totalElapsedSeconds
* @return {Number}
*/
public get totalElapsedSeconds(): number {
return (this.now - this._started) * 0.001;
}
public fps: number = 0;
public fpsMin: number = 1000;
public fpsMax: number = 0;
public msMin: number = 1000;
public msMax: number = 0;
public frames: number = 0;
private _timeLastSecond: number = 0;
/**
*
* @method update
*/
public update() {
// Can we use performance.now() ?
this.now = Date.now(); // mark
this.delta = this.now - this.time; // elapsedMS
this.msMin = Math.min(this.msMin, this.delta);
this.msMax = Math.max(this.msMax, this.delta);
this.frames++;
if (this.now > this._timeLastSecond + 1000)
{
this.fps = Math.round((this.frames * 1000) / (this.now - this._timeLastSecond));
this.fpsMin = Math.min(this.fpsMin, this.fps);
this.fpsMax = Math.max(this.fpsMax, this.fps);
this._timeLastSecond = this.now;
this.frames = 0;
}
this.time = this.now; // _total
private _game: Game;
private _started: number;
//// Lock the delta at 0.1 to minimise fps tunneling
//if (this.delta > 0.1)
//{
// this.delta = 0.1;
//}
}
public timeScale: number = 1.0;
public elapsed: number = 0;
/**
*
* @method elapsedSince
* @param {Number} since
* @return {Number}
*/
public elapsedSince(since: number): number {
/**
*
* @property time
* @type Number
*/
public time: number = 0;
return this.now - since;
/**
*
* @property now
* @type Number
*/
public now: number = 0;
}
/**
*
* @property delta
* @type Number
*/
public delta: number = 0;
/**
*
* @method elapsedSecondsSince
* @param {Number} since
* @return {Number}
*/
public elapsedSecondsSince(since: number): number {
/**
*
* @method totalElapsedSeconds
* @return {Number}
*/
public get totalElapsedSeconds(): number {
return (this.now - since) * 0.001;
return (this.now - this._started) * 0.001;
}
}
/**
*
* @method reset
*/
public reset() {
public fps: number = 0;
public fpsMin: number = 1000;
public fpsMax: number = 0;
public msMin: number = 1000;
public msMax: number = 0;
public frames: number = 0;
this._started = this.now;
private _timeLastSecond: number = 0;
/**
*
* @method update
*/
public update() {
// Can we use performance.now() ?
this.now = Date.now(); // mark
this.delta = this.now - this.time; // elapsedMS
this.msMin = Math.min(this.msMin, this.delta);
this.msMax = Math.max(this.msMax, this.delta);
this.frames++;
if (this.now > this._timeLastSecond + 1000)
{
this.fps = Math.round((this.frames * 1000) / (this.now - this._timeLastSecond));
this.fpsMin = Math.min(this.fpsMin, this.fps);
this.fpsMax = Math.max(this.fpsMax, this.fps);
this._timeLastSecond = this.now;
this.frames = 0;
}
this.time = this.now; // _total
//// Lock the delta at 0.1 to minimise fps tunneling
//if (this.delta > 0.1)
//{
// this.delta = 0.1;
//}
}
/**
*
* @method elapsedSince
* @param {Number} since
* @return {Number}
*/
public elapsedSince(since: number): number {
return this.now - since;
}
/**
*
* @method elapsedSecondsSince
* @param {Number} since
* @return {Number}
*/
public elapsedSecondsSince(since: number): number {
return (this.now - since) * 0.001;
}
/**
*
* @method reset
*/
public reset() {
this._started = this.now;
}
}

108
Phaser/TweenManager.ts Normal file
View file

@ -0,0 +1,108 @@
/// <reference path="Game.ts" />
/// <reference path="system/Tween.ts" />
/**
* Phaser - Tween Manager
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js) converted to TypeScript, patched and integrated into Phaser
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration
* @author sole / http://soledadpenades.com
* @author mrdoob / http://mrdoob.com
* @author Robert Eisele / http://www.xarg.org
* @author Philippe / http://philippe.elsass.me
* @author Robert Penner / http://www.robertpenner.com/easing_terms_of_use.html
* @author Paul Lewis / http://www.aerotwist.com/
* @author lechecacharro
* @author Josh Faul / http://jocafa.com/
* @author egraether / http://egraether.com/
*
* @todo
* 1) Allow for tweening direct numeric values, not just object properties
* 2) YoYo support
*/
module Phaser {
export class TweenManager {
constructor(game: Phaser.Game) {
this._game = game;
this._tweens = [];
}
private _game: Phaser.Game;
private _tweens: Phaser.Tween[];
public getAll() {
return this._tweens;
}
public removeAll() {
this._tweens.length = 0;
}
public create(object): Phaser.Tween {
return new Phaser.Tween(object, this._game);
}
public add(tween: Phaser.Tween) {
tween.parent = this._game;
this._tweens.push(tween);
return tween;
}
public remove(tween: Phaser.Tween) {
var i = this._tweens.indexOf(tween);
if (i !== -1)
{
this._tweens.splice(i, 1);
}
}
public update() {
if (this._tweens.length === 0)
{
return false;
}
var i = 0;
var numTweens = this._tweens.length;
while (i < numTweens)
{
if (this._tweens[i].update(this._game.time.now))
{
i++;
}
else
{
this._tweens.splice(i, 1);
numTweens--;
}
}
return true;
}
}
}

View file

@ -1,475 +1,165 @@
/// <reference path="Cameras.ts" />
/// <reference path="Game.ts" />
/// <reference path="GameMath.ts" />
/// <reference path="Group.ts" />
/// <reference path="geom/Rectangle.ts" />
/// <reference path="geom/Point.ts" />
/// <reference path="Sprite.ts" />
/// <reference path="Tilemap.ts" />
/// <reference path="system/Camera.ts" />
/// <reference path="system/QuadTree.ts" />
class World {
/**
* Phaser
*/
constructor(game: Game, width: number, height: number) {
module Phaser {
this._game = game;
export class World {
this._cameras = new Cameras(this._game, 0, 0, width, height);
constructor(game: Game, width: number, height: number) {
this._game.camera = this._cameras.current;
this._game = game;
this.group = new Group(this._game, 0);
this._cameras = new Cameras(this._game, 0, 0, width, height);
this.bounds = new Rectangle(0, 0, width, height);
this._game.camera = this._cameras.current;
this.worldDivisions = 6;
this.group = new Group(this._game, 0);
}
this.bounds = new Rectangle(0, 0, width, height);
private _game: Game;
private _cameras: Cameras;
this.worldDivisions = 6;
public group: Group;
public bounds: Rectangle;
public worldDivisions: number;
public update() {
this.group.preUpdate();
this.group.update();
this.group.postUpdate();
this._cameras.update();
}
public render() {
// Unlike in flixel our render process is camera driven, not group driven
this._cameras.render();
}
public destroy() {
this.group.destroy();
this._cameras.destroy();
}
// World methods
public setSize(width: number, height: number, updateCameraBounds: bool = true) {
this.bounds.width = width;
this.bounds.height = height;
if (updateCameraBounds == true)
{
this._game.camera.setBounds(0, 0, width, height);
}
}
private _game: Game;
private _cameras: Cameras;
public get width(): number {
return this.bounds.width;
}
public group: Group;
public bounds: Rectangle;
public worldDivisions: number;
public set width(value: number) {
this.bounds.width = value;
}
public update() {
public get height(): number {
return this.bounds.height;
}
this.group.preUpdate();
this.group.update();
this.group.postUpdate();
public set height(value: number) {
this.bounds.height = value;
}
this._cameras.update();
public get centerX(): number {
return this.bounds.halfWidth;
}
public get centerY(): number {
return this.bounds.halfHeight;
}
public get randomX(): number {
return Math.round(Math.random() * this.bounds.width);
}
public get randomY(): number {
return Math.round(Math.random() * this.bounds.height);
}
// Cameras
public addExistingCamera(cam: Camera): Camera {
//return this._cameras.addCamera(x, y, width, height);
return cam;
}
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this._cameras.addCamera(x, y, width, height);
}
public removeCamera(id: number): bool {
return this._cameras.removeCamera(id);
}
public getAllCameras(): Camera[] {
return this._cameras.getAll();
}
// Sprites
public addExistingSprite(sprite: Sprite): Sprite {
return <Sprite> this.group.add(sprite);
}
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return <Sprite> this.group.add(new Sprite(this._game, x, y, key));
}
public createDynamicTexture(key:string, width: number, height: number): DynamicTexture {
return new DynamicTexture(this._game, key, width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return <Group> this.group.add(new Group(this._game, MaxSize));
}
// Tilemaps
public createTilemap(key:string, mapData:string, format:number, tileWidth?:number,tileHeight?:number): Tilemap {
return <Tilemap> this.group.add(new Tilemap(this._game, key, mapData, format, tileWidth, tileHeight));
}
// Emitters
public createParticle(): Particle {
return new Particle(this._game);
}
public createEmitter(x?: number = 0, y?: number = 0, size?:number = 0): Emitter {
return <Emitter> this.group.add(new Emitter(this._game, x, y, size));
}
// Collision
/**
* Call this function to see if one <code>GameObject</code> overlaps another.
* Can be called with one object and one group, or two groups, or two objects,
* whatever floats your boat! For maximum performance try bundling a lot of objects
* together using a <code>FlxGroup</code> (or even bundling groups together!).
*
* <p>NOTE: does NOT take objects' scrollfactor into account, all overlaps are checked in world space.</p>
*
* @param ObjectOrGroup1 The first object or group you want to check.
* @param ObjectOrGroup2 The second object or group you want to check. If it is the same as the first, flixel knows to just do a comparison within that group.
* @param NotifyCallback A function with two <code>GameObject</code> parameters - e.g. <code>myOverlapFunction(Object1:GameObject,Object2:GameObject)</code> - that is called if those two objects overlap.
* @param ProcessCallback A function with two <code>GameObject</code> parameters - e.g. <code>myOverlapFunction(Object1:GameObject,Object2:GameObject)</code> - that is called if those two objects overlap. If a ProcessCallback is provided, then NotifyCallback will only be called if ProcessCallback returns true for those objects!
*
* @return Whether any overlaps were detected.
*/
public overlap(ObjectOrGroup1: Basic = null, ObjectOrGroup2: Basic = null, NotifyCallback = null, ProcessCallback = null): bool {
if (ObjectOrGroup1 == null)
{
ObjectOrGroup1 = this.group;
}
if (ObjectOrGroup2 == ObjectOrGroup1)
{
ObjectOrGroup2 = null;
public render() {
// Unlike in flixel our render process is camera driven, not group driven
this._cameras.render();
}
QuadTree.divisions = this.worldDivisions;
public destroy() {
var quadTree: QuadTree = new QuadTree(this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height);
this.group.destroy();
quadTree.load(ObjectOrGroup1, ObjectOrGroup2, NotifyCallback, ProcessCallback);
this._cameras.destroy();
var result: bool = quadTree.execute();
quadTree.destroy();
quadTree = null;
return result;
}
/**
* The main collision resolution in flixel.
*
* @param Object1 Any <code>Sprite</code>.
* @param Object2 Any other <code>Sprite</code>.
*
* @return Whether the objects in fact touched and were separated.
*/
public static separate(Object1, Object2): bool {
var separatedX: bool = World.separateX(Object1, Object2);
var separatedY: bool = World.separateY(Object1, Object2);
return separatedX || separatedY;
}
/**
* The X-axis component of the object separation process.
*
* @param Object1 Any <code>Sprite</code>.
* @param Object2 Any other <code>Sprite</code>.
*
* @return Whether the objects in fact touched and were separated along the X axis.
*/
public static separateX(Object1, Object2): bool {
//can't separate two immovable objects
var obj1immovable: bool = Object1.immovable;
var obj2immovable: bool = Object2.immovable;
if (obj1immovable && obj2immovable)
{
return false;
}
//If one of the objects is a tilemap, just pass it off.
/*
if (typeof Object1 === 'FlxTilemap')
{
return Object1.overlapsWithCallback(Object2, separateX);
}
// World methods
if (typeof Object2 === 'FlxTilemap')
{
return Object2.overlapsWithCallback(Object1, separateX, true);
}
*/
public setSize(width: number, height: number, updateCameraBounds: bool = true) {
//First, get the two object deltas
var overlap: number = 0;
var obj1delta: number = Object1.x - Object1.last.x;
var obj2delta: number = Object2.x - Object2.last.x;
this.bounds.width = width;
this.bounds.height = height;
if (obj1delta != obj2delta)
{
//Check if the X hulls actually overlap
var obj1deltaAbs: number = (obj1delta > 0) ? obj1delta : -obj1delta;
var obj2deltaAbs: number = (obj2delta > 0) ? obj2delta : -obj2delta;
var obj1rect: Rectangle = new Rectangle(Object1.x - ((obj1delta > 0) ? obj1delta : 0), Object1.last.y, Object1.width + ((obj1delta > 0) ? obj1delta : -obj1delta), Object1.height);
var obj2rect: Rectangle = new Rectangle(Object2.x - ((obj2delta > 0) ? obj2delta : 0), Object2.last.y, Object2.width + ((obj2delta > 0) ? obj2delta : -obj2delta), Object2.height);
if ((obj1rect.x + obj1rect.width > obj2rect.x) && (obj1rect.x < obj2rect.x + obj2rect.width) && (obj1rect.y + obj1rect.height > obj2rect.y) && (obj1rect.y < obj2rect.y + obj2rect.height))
if (updateCameraBounds == true)
{
var maxOverlap: number = obj1deltaAbs + obj2deltaAbs + GameObject.OVERLAP_BIAS;
//If they did overlap (and can), figure out by how much and flip the corresponding flags
if (obj1delta > obj2delta)
{
overlap = Object1.x + Object1.width - Object2.x;
if ((overlap > maxOverlap) || !(Object1.allowCollisions & GameObject.RIGHT) || !(Object2.allowCollisions & GameObject.LEFT))
{
overlap = 0;
}
else
{
Object1.touching |= GameObject.RIGHT;
Object2.touching |= GameObject.LEFT;
}
}
else if (obj1delta < obj2delta)
{
overlap = Object1.x - Object2.width - Object2.x;
if ((-overlap > maxOverlap) || !(Object1.allowCollisions & GameObject.LEFT) || !(Object2.allowCollisions & GameObject.RIGHT))
{
overlap = 0;
}
else
{
Object1.touching |= GameObject.LEFT;
Object2.touching |= GameObject.RIGHT;
}
}
}
}
//Then adjust their positions and velocities accordingly (if there was any overlap)
if (overlap != 0)
{
var obj1v: number = Object1.velocity.x;
var obj2v: number = Object2.velocity.x;
if (!obj1immovable && !obj2immovable)
{
overlap *= 0.5;
Object1.x = Object1.x - overlap;
Object2.x += overlap;
var obj1velocity: number = Math.sqrt((obj2v * obj2v * Object2.mass) / Object1.mass) * ((obj2v > 0) ? 1 : -1);
var obj2velocity: number = Math.sqrt((obj1v * obj1v * Object1.mass) / Object2.mass) * ((obj1v > 0) ? 1 : -1);
var average: number = (obj1velocity + obj2velocity) * 0.5;
obj1velocity -= average;
obj2velocity -= average;
Object1.velocity.x = average + obj1velocity * Object1.elasticity;
Object2.velocity.x = average + obj2velocity * Object2.elasticity;
}
else if (!obj1immovable)
{
Object1.x = Object1.x - overlap;
Object1.velocity.x = obj2v - obj1v * Object1.elasticity;
}
else if (!obj2immovable)
{
Object2.x += overlap;
Object2.velocity.x = obj1v - obj2v * Object2.elasticity;
this._game.camera.setBounds(0, 0, width, height);
}
return true;
}
else
{
return false;
}
}
/**
* The Y-axis component of the object separation process.
*
* @param Object1 Any <code>Sprite</code>.
* @param Object2 Any other <code>Sprite</code>.
*
* @return Whether the objects in fact touched and were separated along the Y axis.
*/
public static separateY(Object1, Object2): bool {
//can't separate two immovable objects
var obj1immovable: bool = Object1.immovable;
var obj2immovable: bool = Object2.immovable;
if (obj1immovable && obj2immovable)
return false;
//If one of the objects is a tilemap, just pass it off.
/*
if (typeof Object1 === 'FlxTilemap')
{
return Object1.overlapsWithCallback(Object2, separateY);
public get width(): number {
return this.bounds.width;
}
if (typeof Object2 === 'FlxTilemap')
{
return Object2.overlapsWithCallback(Object1, separateY, true);
}
*/
//First, get the two object deltas
var overlap: number = 0;
var obj1delta: number = Object1.y - Object1.last.y;
var obj2delta: number = Object2.y - Object2.last.y;
if (obj1delta != obj2delta)
{
//Check if the Y hulls actually overlap
var obj1deltaAbs: number = (obj1delta > 0) ? obj1delta : -obj1delta;
var obj2deltaAbs: number = (obj2delta > 0) ? obj2delta : -obj2delta;
var obj1rect: Rectangle = new Rectangle(Object1.x, Object1.y - ((obj1delta > 0) ? obj1delta : 0), Object1.width, Object1.height + obj1deltaAbs);
var obj2rect: Rectangle = new Rectangle(Object2.x, Object2.y - ((obj2delta > 0) ? obj2delta : 0), Object2.width, Object2.height + obj2deltaAbs);
if ((obj1rect.x + obj1rect.width > obj2rect.x) && (obj1rect.x < obj2rect.x + obj2rect.width) && (obj1rect.y + obj1rect.height > obj2rect.y) && (obj1rect.y < obj2rect.y + obj2rect.height))
{
var maxOverlap: number = obj1deltaAbs + obj2deltaAbs + GameObject.OVERLAP_BIAS;
//If they did overlap (and can), figure out by how much and flip the corresponding flags
if (obj1delta > obj2delta)
{
overlap = Object1.y + Object1.height - Object2.y;
if ((overlap > maxOverlap) || !(Object1.allowCollisions & GameObject.DOWN) || !(Object2.allowCollisions & GameObject.UP))
{
overlap = 0;
}
else
{
Object1.touching |= GameObject.DOWN;
Object2.touching |= GameObject.UP;
}
}
else if (obj1delta < obj2delta)
{
overlap = Object1.y - Object2.height - Object2.y;
if ((-overlap > maxOverlap) || !(Object1.allowCollisions & GameObject.UP) || !(Object2.allowCollisions & GameObject.DOWN))
{
overlap = 0;
}
else
{
Object1.touching |= GameObject.UP;
Object2.touching |= GameObject.DOWN;
}
}
}
public set width(value: number) {
this.bounds.width = value;
}
//Then adjust their positions and velocities accordingly (if there was any overlap)
if (overlap != 0)
{
var obj1v: number = Object1.velocity.y;
var obj2v: number = Object2.velocity.y;
if (!obj1immovable && !obj2immovable)
{
overlap *= 0.5;
Object1.y = Object1.y - overlap;
Object2.y += overlap;
var obj1velocity: number = Math.sqrt((obj2v * obj2v * Object2.mass) / Object1.mass) * ((obj2v > 0) ? 1 : -1);
var obj2velocity: number = Math.sqrt((obj1v * obj1v * Object1.mass) / Object2.mass) * ((obj1v > 0) ? 1 : -1);
var average: number = (obj1velocity + obj2velocity) * 0.5;
obj1velocity -= average;
obj2velocity -= average;
Object1.velocity.y = average + obj1velocity * Object1.elasticity;
Object2.velocity.y = average + obj2velocity * Object2.elasticity;
}
else if (!obj1immovable)
{
Object1.y = Object1.y - overlap;
Object1.velocity.y = obj2v - obj1v * Object1.elasticity;
//This is special case code that handles cases like horizontal moving platforms you can ride
if (Object2.active && Object2.moves && (obj1delta > obj2delta))
{
Object1.x += Object2.x - Object2.last.x;
}
}
else if (!obj2immovable)
{
Object2.y += overlap;
Object2.velocity.y = obj1v - obj2v * Object2.elasticity;
//This is special case code that handles cases like horizontal moving platforms you can ride
if (Object1.active && Object1.moves && (obj1delta < obj2delta))
{
Object2.x += Object1.x - Object1.last.x;
}
}
return true;
public get height(): number {
return this.bounds.height;
}
else
{
return false;
public set height(value: number) {
this.bounds.height = value;
}
public get centerX(): number {
return this.bounds.halfWidth;
}
public get centerY(): number {
return this.bounds.halfHeight;
}
public get randomX(): number {
return Math.round(Math.random() * this.bounds.width);
}
public get randomY(): number {
return Math.round(Math.random() * this.bounds.height);
}
// Cameras
public addExistingCamera(cam: Camera): Camera {
//return this._cameras.addCamera(x, y, width, height);
return cam;
}
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this._cameras.addCamera(x, y, width, height);
}
public removeCamera(id: number): bool {
return this._cameras.removeCamera(id);
}
public getAllCameras(): Camera[] {
return this._cameras.getAll();
}
// Sprites
// Drop this?
public addExistingSprite(sprite: Sprite): Sprite {
return <Sprite> this.group.add(sprite);
}
public createSprite(x: number, y: number, key?: string = ''): Sprite {
return <Sprite> this.group.add(new Sprite(this._game, x, y, key));
}
public createGeomSprite(x: number, y: number): GeomSprite {
return <GeomSprite> this.group.add(new GeomSprite(this._game, x, y));
}
public createDynamicTexture(key: string, width: number, height: number): DynamicTexture {
return new DynamicTexture(this._game, key, width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return <Group> this.group.add(new Group(this._game, MaxSize));
}
// Tilemaps
public createTilemap(key: string, mapData: string, format: number, tileWidth?: number, tileHeight?: number): Tilemap {
return <Tilemap> this.group.add(new Tilemap(this._game, key, mapData, format, tileWidth, tileHeight));
}
// Emitters
public createParticle(): Particle {
return new Particle(this._game);
}
public createEmitter(x?: number = 0, y?: number = 0, size?: number = 0): Emitter {
return <Emitter> this.group.add(new Emitter(this._game, x, y, size));
}
}
}

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);
}
}
}

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;
}
}
}

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;
}
}
}

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() {
}
}
}

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);
}
}
}

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;
}
}
}

View file

@ -1,474 +1,506 @@
/// <reference path="Point.ts" />
/// <reference path="../Game.ts" />
/**
* Geom - Circle
* Phaser - Geom - Circle
*
* @desc A Circle object is an area defined by its position, as indicated by its center point (x,y) and diameter.
*
* @version 1.2 - 27th February 2013
* @version 1.1 - 11th October 2012
* @author Richard Davey
* @author Ross Kettle
*
* @todo Intersections
*/
class Circle {
module Phaser {
/**
* Creates a new Circle object with the center coordinate specified by the x and y parameters and the diameter specified by the diameter parameter. If you call this function without parameters, a circle with x, y, diameter and radius properties set to 0 is created.
* @class Circle
* @constructor
* @param {Number} x The x coordinate of the center of the circle.
* @param {Number} y The y coordinate of the center of the circle.
* @return {Circle} This circle object
**/
constructor(x: number = 0, y: number = 0, diameter: number = 0) {
export class Circle {
this.setTo(x, y, diameter);
/**
* Creates a new Circle object with the center coordinate specified by the x and y parameters and the diameter specified by the diameter parameter. If you call this function without parameters, a circle with x, y, diameter and radius properties set to 0 is created.
* @class Circle
* @constructor
* @param {Number} x The x coordinate of the center of the circle.
* @param {Number} y The y coordinate of the center of the circle.
* @return {Circle} This circle object
**/
constructor(x: number = 0, y: number = 0, diameter: number = 0) {
}
this.setTo(x, y, diameter);
/**
* The diameter of the circle
* @property _diameter
* @type Number
**/
private _diameter: number = 0;
/**
* The radius of the circle
* @property _radius
* @type Number
**/
private _radius: number = 0;
/**
* The x coordinate of the center of the circle
* @property x
* @type Number
**/
public x: number = 0;
/**
* The y coordinate of the center of the circle
* @property y
* @type Number
**/
public y: number = 0;
/**
* The diameter of the circle. The largest distance between any two points on the circle. The same as the radius * 2.
* @method diameter
* @param {Number} The diameter of the circle.
* @return {Number}
**/
public diameter(value?: number): number {
if (value && value > 0)
{
this._diameter = value;
this._radius = value * 0.5;
}
return this._diameter;
private _diameter: number = 0;
private _radius: number = 0;
}
/**
* The x coordinate of the center of the circle
* @property x
* @type Number
**/
public x: number = 0;
/**
* The radius of the circle. The length of a line extending from the center of the circle to any point on the circle itself. The same as half the diameter.
* @method radius
* @param {Number} The radius of the circle.
**/
public radius(value?: number) {
/**
* The y coordinate of the center of the circle
* @property y
* @type Number
**/
public y: number = 0;
/**
* The diameter of the circle. The largest distance between any two points on the circle. The same as the radius * 2.
* @method diameter
* @return {Number}
**/
get diameter(): number {
return this._diameter;
if (value && value > 0)
{
this._radius = value;
this._diameter = value * 2;
}
return this._radius;
/**
* The diameter of the circle. The largest distance between any two points on the circle. The same as the radius * 2.
* @method diameter
* @param {Number} The diameter of the circle.
**/
set diameter(value: number) {
}
/**
* The circumference of the circle.
* @method circumference
* @return {Number}
**/
public circumference(): number {
return 2 * (Math.PI * this._radius);
}
/**
* The sum of the y and radius properties. Changing the bottom property of a Circle object has no effect on the x and y properties, but does change the diameter.
* @method bottom
* @param {Number} The value to adjust the height of the circle by.
**/
public bottom(value?: number) {
if (value && !isNaN(value))
{
if (value < this.y)
if (value > 0)
{
this._radius = 0;
this._diameter = 0;
this._diameter = value;
this._radius = value * 0.5;
}
}
/**
* The radius of the circle. The length of a line extending from the center of the circle to any point on the circle itself. The same as half the diameter.
* @method radius
* @return {Number}
**/
get radius(): number {
return this._radius;
}
/**
* The radius of the circle. The length of a line extending from the center of the circle to any point on the circle itself. The same as half the diameter.
* @method radius
* @param {Number} The radius of the circle.
**/
set radius(value: number) {
if (value > 0)
{
this._radius = value;
this._diameter = value * 2;
}
}
/**
* The circumference of the circle.
* @method circumference
* @return {Number}
**/
public circumference(): number {
return 2 * (Math.PI * this._radius);
}
/**
* The sum of the y and radius properties. Changing the bottom property of a Circle object has no effect on the x and y properties, but does change the diameter.
* @method bottom
* @return {Number}
**/
get bottom(): number {
return this.y + this._radius;
}
/**
* The sum of the y and radius properties. Changing the bottom property of a Circle object has no effect on the x and y properties, but does change the diameter.
* @method bottom
* @param {Number} The value to adjust the height of the circle by.
**/
set bottom(value: number) {
if (!isNaN(value))
{
if (value < this.y)
{
this._radius = 0;
this._diameter = 0;
}
else
{
this.radius = value - this.y;
}
}
}
/**
* The x coordinate of the leftmost point of the circle. Changing the left property of a Circle object has no effect on the x and y properties. However it does affect the diameter, whereas changing the x value does not affect the diameter property.
* @method left
* @return {Number} The x coordinate of the leftmost point of the circle.
**/
get left(): number {
return this.x - this._radius;
}
/**
* The x coordinate of the leftmost point of the circle. Changing the left property of a Circle object has no effect on the x and y properties. However it does affect the diameter, whereas changing the x value does not affect the diameter property.
* @method left
* @param {Number} The value to adjust the position of the leftmost point of the circle by.
**/
set left(value: number) {
if (!isNaN(value))
{
if (value < this.x)
{
this.radius = this.x - value;
}
else
{
this._radius = 0;
this._diameter = 0;
}
}
}
/**
* The x coordinate of the rightmost point of the circle. Changing the right property of a Circle object has no effect on the x and y properties. However it does affect the diameter, whereas changing the x value does not affect the diameter property.
* @method right
* @return {Number}
**/
get right(): number {
return this.x + this._radius;
}
/**
* The x coordinate of the rightmost point of the circle. Changing the right property of a Circle object has no effect on the x and y properties. However it does affect the diameter, whereas changing the x value does not affect the diameter property.
* @method right
* @param {Number} The amount to adjust the diameter of the circle by.
**/
set right(value: number) {
if (!isNaN(value))
{
if (value > this.x)
{
this.radius = value - this.x;
}
else
{
this._radius = 0;
this._diameter = 0;
}
}
}
/**
* The sum of the y minus the radius property. Changing the top property of a Circle object has no effect on the x and y properties, but does change the diameter.
* @method bottom
* @return {Number}
**/
get top(): number {
return this.y - this._radius;
}
/**
* The sum of the y minus the radius property. Changing the top property of a Circle object has no effect on the x and y properties, but does change the diameter.
* @method bottom
* @param {Number} The amount to adjust the height of the circle by.
**/
set top(value: number) {
if (!isNaN(value))
{
if (value > this.y)
{
this._radius = 0;
this._diameter = 0;
}
else
{
this.radius = this.y - value;
}
}
}
/**
* Gets the area of this Circle.
* @method area
* @return {Number} This area of this circle.
**/
get area(): number {
if (this._radius > 0)
{
return Math.PI * this._radius * this._radius;
}
else
{
this.radius(value - this.y);
return 0;
}
}
return this.y + this._radius;
/**
* Determines whether or not this Circle object is empty.
* @method isEmpty
* @return {Boolean} A value of true if the Circle objects diameter is less than or equal to 0; otherwise false.
**/
get isEmpty(): bool {
}
/**
* The x coordinate of the leftmost point of the circle. Changing the left property of a Circle object has no effect on the x and y properties. However it does affect the diameter, whereas changing the x value does not affect the diameter property.
* @method left
* @param {Number} The value to adjust the position of the leftmost point of the circle by.
**/
public left(value?: number) {
if (value && !isNaN(value))
{
if (value < this.x)
if (this._diameter < 1)
{
this.radius(this.x - value);
return true;
}
return false;
}
/**
* Whether the circle intersects with a line. Checks against infinite line defined by the two points on the line, not the line segment.
* If you need details about the intersection then use Collision.lineToCircle instead.
* @method intersectCircleLine
* @param {Object} the line object to check.
* @return {Boolean}
**/
public intersectCircleLine(line: Line): bool {
return Collision.lineToCircle(line, this).result;
}
/**
* Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object.
* @method clone
* @param {Circle} output Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned.
* @return {Phaser.Circle}
**/
public clone(output?: Circle = new Circle): Circle {
return output.setTo(this.x, this.y, this._diameter);
}
/**
* Return true if the given x/y coordinates are within this Circle object.
* If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead.
* @method contains
* @param {Number} The X value of the coordinate to test.
* @param {Number} The Y value of the coordinate to test.
* @return {Boolean} True if the coordinates are within this circle, otherwise false.
**/
public contains(x: number, y: number): bool {
return Collision.circleContainsPoint(this, <Point> { x: x, y: y }).result;
}
/**
* Return true if the coordinates of the given Point object are within this Circle object.
* If you need details about the intersection then use Phaser.Intersect.circleContainsPoint instead.
* @method containsPoint
* @param {Phaser.Point} The Point object to test.
* @return {Boolean} True if the coordinates are within this circle, otherwise false.
**/
public containsPoint(point:Point): bool {
return Collision.circleContainsPoint(this, point).result;
}
/**
* Return true if the given Circle is contained entirely within this Circle object.
* If you need details about the intersection then use Phaser.Intersect.circleToCircle instead.
* @method containsCircle
* @param {Phaser.Circle} The Circle object to test.
* @return {Boolean} True if the coordinates are within this circle, otherwise false.
**/
public containsCircle(circle:Circle): bool {
return Collision.circleToCircle(this, circle).result;
}
/**
* Copies all of circle data from the source Circle object into the calling Circle object.
* @method copyFrom
* @param {Circle} rect The source circle object to copy from
* @return {Circle} This circle object
**/
public copyFrom(source: Circle): Circle {
return this.setTo(source.x, source.y, source.diameter);
}
/**
* Copies all of circle data from this Circle object into the destination Circle object.
* @method copyTo
* @param {Circle} circle The destination circle object to copy in to
* @return {Circle} The destination circle object
**/
public copyTo(target: Circle) {
return target.copyFrom(this);
}
/**
* Returns the distance from the center of this Circle object to the given object (can be Circle, Point or anything with x/y values)
* @method distanceFrom
* @param {Circle/Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
public distanceTo(target: any, round?: bool = false): number {
var dx = this.x - target.x;
var dy = this.y - target.y;
if (round === true)
{
return Math.round(Math.sqrt(dx * dx + dy * dy));
}
else
{
this._radius = 0;
this._diameter = 0;
return Math.sqrt(dx * dx + dy * dy);
}
}
return this.x - this._radius;
/**
* Determines whether the object specified in the toCompare parameter is equal to this Circle object. This method compares the x, y and diameter properties of an object against the same properties of this Circle object.
* @method equals
* @param {Circle} toCompare The circle to compare to this Circle object.
* @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false.
**/
public equals(toCompare: Circle): bool {
}
/**
* The x coordinate of the rightmost point of the circle. Changing the right property of a Circle object has no effect on the x and y properties. However it does affect the diameter, whereas changing the x value does not affect the diameter property.
* @method right
* @param {Number} The amount to adjust the diameter of the circle by.
**/
public right(value?: number) {
if (value && !isNaN(value))
{
if (value > this.x)
if (this.x === toCompare.x && this.y === toCompare.y && this.diameter === toCompare.diameter)
{
this.radius(value - this.x);
return true;
}
else
return false;
}
/**
* Determines whether the Circle object specified in the toIntersect parameter intersects with this Circle object. This method checks the radius distances between the two Circle objects to see if they intersect.
* @method intersects
* @param {Circle} toIntersect The Circle object to compare against to see if it intersects with this Circle object.
* @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false.
**/
public intersects(toIntersect: Circle): bool {
if (this.distanceTo(toIntersect, false) < (this._radius + toIntersect._radius)) {
return true;
}
return false;
}
/**
* Returns a Point object containing the coordinates of a point on the circumference of this Circle based on the given angle.
* @method circumferencePoint
* @param {Number} The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} Is the given angle in radians (false) or degrees (true)?
* @param {Phaser.Point} An optional Point object to put the result in to. If none specified a new Point object will be created.
* @return {Phaser.Point} The Point object holding the result.
**/
public circumferencePoint(angle: number, asDegrees: bool = false, output?: Point = new Point): Point {
if (asDegrees === true)
{
this._radius = 0;
this._diameter = 0;
angle = angle * GameMath.DEG_TO_RAD;
}
output.x = this.x + this._radius * Math.cos(angle);
output.y = this.y + this._radius * Math.sin(angle);
return output;
}
return this.x + this._radius;
/**
* Adjusts the location of the Circle object, as determined by its center coordinate, by the specified amounts.
* @method offset
* @param {Number} dx Moves the x value of the Circle object by this amount.
* @param {Number} dy Moves the y value of the Circle object by this amount.
* @return {Circle} This Circle object.
**/
public offset(dx: number, dy: number): Circle {
}
/**
* The sum of the y minus the radius property. Changing the top property of a Circle object has no effect on the x and y properties, but does change the diameter.
* @method bottom
* @param {Number} The amount to adjust the height of the circle by.
**/
public top(value?: number) {
if (value && !isNaN(value))
{
if (value > this.y)
if (!isNaN(dx) && !isNaN(dy))
{
this._radius = 0;
this._diameter = 0;
}
else
{
this.radius(this.y - value);
this.x += dx;
this.y += dy;
}
return this;
}
return this.y - this._radius;
/**
* Adjusts the location of the Circle object using a Point object as a parameter. This method is similar to the Circle.offset() method, except that it takes a Point object as a parameter.
* @method offsetPoint
* @param {Point} point A Point object to use to offset this Circle object.
* @return {Circle} This Circle object.
**/
public offsetPoint(point: Point): Circle {
}
return this.offset(point.x, point.y);
/**
* Gets the area of this Circle.
* @method area
* @return {Number} This area of this circle.
**/
public area(): number {
if (this._radius > 0)
{
return Math.PI * this._radius * this._radius;
}
else
{
return 0;
/**
* Sets the members of Circle to the specified values.
* @method setTo
* @param {Number} x The x coordinate of the center of the circle.
* @param {Number} y The y coordinate of the center of the circle.
* @param {Number} diameter The diameter of the circle in pixels.
* @return {Circle} This circle object
**/
public setTo(x: number, y: number, diameter: number): Circle {
this.x = x;
this.y = y;
this._diameter = diameter;
this._radius = diameter * 0.5;
return this;
}
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the instance.
**/
public toString(): string {
return "[{Circle (x=" + this.x + " y=" + this.y + " diameter=" + this.diameter + " radius=" + this.radius + ")}]";
}
}
/**
* Determines whether or not this Circle object is empty.
* @method isEmpty
* @return {Boolean} A value of true if the Circle objects diameter is less than or equal to 0; otherwise false.
**/
public isEmpty(): bool {
if (this._diameter < 1)
{
return true;
}
return false;
}
/**
* Whether the circle intersects with a line. Checks against infinite line defined by the two points on the line, not the line segment.
* If you need details about the intersection then use Kiwi.Geom.Intersect.lineToCircle instead.
* @method intersectCircleLine
* @param {Object} the line object to check.
* @return {Boolean}
**/
/*
public intersectCircleLine(line: Line): bool {
return Intersect.lineToCircle(line, this).result;
}
*/
/**
* Returns a new Circle object with the same values for the x, y, width, and height properties as the original Circle object.
* @method clone
* @param {Circle} output Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned.
* @return {Kiwi.Geom.Circle}
**/
public clone(output?: Circle = new Circle): Circle {
return output.setTo(this.x, this.y, this._diameter);
}
/**
* Return true if the given x/y coordinates are within this Circle object.
* If you need details about the intersection then use Kiwi.Geom.Intersect.circleContainsPoint instead.
* @method contains
* @param {Number} The X value of the coordinate to test.
* @param {Number} The Y value of the coordinate to test.
* @return {Boolean} True if the coordinates are within this circle, otherwise false.
**/
/*
public contains(x: number, y: number): bool {
return Intersect.circleContainsPoint(this, <Point> { x: x, y: y }).result;
}
*/
/**
* Return true if the coordinates of the given Point object are within this Circle object.
* If you need details about the intersection then use Kiwi.Geom.Intersect.circleContainsPoint instead.
* @method containsPoint
* @param {Kiwi.Geom.Point} The Point object to test.
* @return {Boolean} True if the coordinates are within this circle, otherwise false.
**/
/*
public containsPoint(point:Point): bool {
return Intersect.circleContainsPoint(this, point).result;
}
*/
/**
* Return true if the given Circle is contained entirely within this Circle object.
* If you need details about the intersection then use Kiwi.Geom.Intersect.circleToCircle instead.
* @method containsCircle
* @param {Kiwi.Geom.Circle} The Circle object to test.
* @return {Boolean} True if the coordinates are within this circle, otherwise false.
**/
/*
public containsCircle(circle:Circle): bool {
return Intersect.circleToCircle(this, circle).result;
}
*/
/**
* Copies all of circle data from the source Circle object into the calling Circle object.
* @method copyFrom
* @param {Circle} rect The source circle object to copy from
* @return {Circle} This circle object
**/
public copyFrom(source: Circle): Circle {
return this.setTo(source.x, source.y, source.diameter());
}
/**
* Copies all of circle data from this Circle object into the destination Circle object.
* @method copyTo
* @param {Circle} circle The destination circle object to copy in to
* @return {Circle} The destination circle object
**/
public copyTo(target: Circle) {
return target.copyFrom(this);
}
/**
* Returns the distance from the center of this Circle object to the given object (can be Circle, Point or anything with x/y values)
* @method distanceFrom
* @param {Circle/Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
public distanceTo(target: any, round?: bool = false): number {
var dx = this.x - target.x;
var dy = this.y - target.y;
if (round === true)
{
return Math.round(Math.sqrt(dx * dx + dy * dy));
}
else
{
return Math.sqrt(dx * dx + dy * dy);
}
}
/**
* Determines whether the object specified in the toCompare parameter is equal to this Circle object. This method compares the x, y and diameter properties of an object against the same properties of this Circle object.
* @method equals
* @param {Circle} toCompare The circle to compare to this Circle object.
* @return {Boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false.
**/
public equals(toCompare: Circle): bool {
if (this.x === toCompare.x && this.y === toCompare.y && this.diameter() === toCompare.diameter())
{
return true;
}
return false;
}
/**
* Determines whether the Circle object specified in the toIntersect parameter intersects with this Circle object. This method checks the radius distances between the two Circle objects to see if they intersect.
* @method intersects
* @param {Circle} toIntersect The Circle object to compare against to see if it intersects with this Circle object.
* @return {Boolean} A value of true if the specified object intersects with this Circle object; otherwise false.
**/
public intersects(toIntersect: Circle): bool {
if (this.distanceTo(toIntersect, false) < (this._radius + toIntersect._radius))
{
return true;
}
return false;
}
/**
* Returns a Point object containing the coordinates of a point on the circumference of this Circle based on the given angle.
* @method circumferencePoint
* @param {Number} The angle in radians (unless asDegrees is true) to return the point from.
* @param {Boolean} Is the given angle in radians (false) or degrees (true)?
* @param {Kiwi.Geom.Point} An optional Point object to put the result in to. If none specified a new Point object will be created.
* @return {Kiwi.Geom.Point} The Point object holding the result.
**/
public circumferencePoint(angle: number, asDegrees: bool = false, output?: Point = new Point): Point {
if (asDegrees === true)
{
//angle = angle * (Math.PI / 180); // Degrees to Radians
angle = angle * (180 / Math.PI); // Radians to Degrees
}
output.x = this.x + this._radius * Math.cos(angle);
output.y = this.y + this._radius * Math.sin(angle);
return output;
}
/**
* Adjusts the location of the Circle object, as determined by its center coordinate, by the specified amounts.
* @method offset
* @param {Number} dx Moves the x value of the Circle object by this amount.
* @param {Number} dy Moves the y value of the Circle object by this amount.
* @return {Circle} This Circle object.
**/
public offset(dx: number, dy: number): Circle {
if (!isNaN(dx) && !isNaN(dy))
{
this.x += dx;
this.y += dy;
}
return this;
}
/**
* Adjusts the location of the Circle object using a Point object as a parameter. This method is similar to the Circle.offset() method, except that it takes a Point object as a parameter.
* @method offsetPoint
* @param {Point} point A Point object to use to offset this Circle object.
* @return {Circle} This Circle object.
**/
public offsetPoint(point: Point): Circle {
return this.offset(point.x, point.y);
}
/**
* Sets the members of Circle to the specified values.
* @method setTo
* @param {Number} x The x coordinate of the center of the circle.
* @param {Number} y The y coordinate of the center of the circle.
* @param {Number} diameter The diameter of the circle in pixels.
* @return {Circle} This circle object
**/
public setTo(x: number, y: number, diameter: number): Circle {
this.x = x;
this.y = y;
this._diameter = diameter;
this._radius = diameter * 0.5;
return this;
}
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the instance.
**/
public toString(): string {
return "[{Circle (x=" + this.x + " y=" + this.y + " diameter=" + this.diameter() + " radius=" + this.radius() + ")}]";
}
}
}

View file

@ -0,0 +1,99 @@
/// <reference path="../Game.ts" />
/**
* Phaser - Geom - IntersectResult
*
* @desc A light-weight result object to hold the results of an intersection
*
* @version 1.0 - 15th October 2012
* @author Richard Davey
*/
module Phaser {
export class IntersectResult {
/**
* Did they intersect or not?
* @property result
* @type Boolean
*/
result: bool = false;
/**
* @property x
* @type Number
*/
x: number;
/**
* @property y
* @type Number
*/
y: number;
/**
* @property x1
* @type Number
*/
x1: number;
/**
* @property y1
* @type Number
*/
y1: number;
/**
* @property x2
* @type Number
*/
x2: number;
/**
* @property y2
* @type Number
*/
y2: number;
/**
* @property width
* @type Number
*/
width: number;
/**
* @property height
* @type Number
*/
height: number;
/**
*
* @method setTo
* @param {Number} x1
* @param {Number} y1
* @param {Number} [x2]
* @param {Number} [y2]
* @param {Number} [width]
* @param {Number} [height]
*/
setTo(x1: number, y1: number, x2?: number = 0, y2?: number = 0, width?: number = 0, height?: number = 0) {
this.x = x1;
this.y = y1;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.width = width;
this.height = height;
}
}
}

309
Phaser/geom/Line.ts Normal file
View file

@ -0,0 +1,309 @@
/// <reference path="../Game.ts" />
/**
* Phaser - Geom - Line
*
* @desc A Line object is an infinte line through space. The two sets of x/y coordinates define the Line Segment.
*
* @version 1.0 - 11th October 2012
* @author Ross Kettle
* @author Richard Davey
*/
module Phaser {
export class Line {
/**
*
* @constructor
* @param {Number} x1
* @param {Number} y1
* @param {Number} x2
* @param {Number} y2
* @return {Phaser.Line} This Object
*/
constructor(x1: number = 0, y1: number = 0, x2: number = 0, y2: number = 0) {
this.setTo(x1, y1, x2, y2);
}
/**
*
* @property x1
* @type Number
*/
public x1: number = 0;
/**
*
* @property y1
* @type Number
*/
public y1: number = 0;
/**
*
* @property x2
* @type Number
*/
public x2: number = 0;
/**
*
* @property y2
* @type Number
*/
public y2: number = 0;
/**
*
* @method clone
* @param {Phaser.Line} [output]
* @return {Phaser.Line}
*/
public clone(output?: Line = new Line): Line {
return output.setTo(this.x1, this.y1, this.x2, this.y2);
}
/**
*
* @method copyFrom
* @param {Phaser.Line} source
* @return {Phaser.Line}
*/
public copyFrom(source: Line): Line {
return this.setTo(source.x1, source.y1, source.x2, source.y2);
}
/**
*
* @method copyTo
* @param {Phaser.Line} target
* @return {Phaser.Line}
*/
public copyTo(target: Line): Line {
return target.copyFrom(this);
}
/**
*
* @method setTo
* @param {Number} x1
* @param {Number} y1
* @param {Number} x2
* @param {Number} y2
* @return {Phaser.Line}
*/
public setTo(x1: number = 0, y1: number = 0, x2: number = 0, y2: number = 0): Line {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
return this;
}
public get width(): number {
return Math.max(this.x1, this.x2) - Math.min(this.x1, this.x2);
}
public get height(): number {
return Math.max(this.y1, this.y2) - Math.min(this.y1, this.y2);
}
/**
*
* @method length
* @return {Number}
*/
public get length(): number {
return Math.sqrt((this.x2 - this.x1) * (this.x2 - this.x1) + (this.y2 - this.y1) * (this.y2 - this.y1));
}
/**
*
* @method getY
* @param {Number} x
* @return {Number}
*/
public getY(x: number): number {
return this.slope * x + this.yIntercept;
}
/**
*
* @method angle
* @return {Number}
*/
public get angle(): number {
return Math.atan2(this.x2 - this.x1, this.y2 - this.y1);
}
/**
*
* @method slope
* @return {Number}
*/
public get slope(): number {
return (this.y2 - this.y1) / (this.x2 - this.x1);
}
/**
*
* @method perpSlope
* @return {Number}
*/
public get perpSlope(): number {
return -((this.x2 - this.x1) / (this.y2 - this.y1));
}
/**
*
* @method yIntercept
* @return {Number}
*/
public get yIntercept(): number {
return (this.y1 - this.slope * this.x1);
}
/**
*
* @method isPointOnLine
* @param {Number} x
* @param {Number} y
* @return {Boolean}
*/
public isPointOnLine(x: number, y: number): bool {
if ((x - this.x1) * (this.y2 - this.y1) === (this.x2 - this.x1) * (y - this.y1))
{
return true;
}
else
{
return false;
}
}
/**
*
* @method isPointOnLineSegment
* @param {Number} x
* @param {Number} y
* @return {Boolean}
*/
public isPointOnLineSegment(x: number, y: number): bool {
var xMin = Math.min(this.x1, this.x2);
var xMax = Math.max(this.x1, this.x2);
var yMin = Math.min(this.y1, this.y2);
var yMax = Math.max(this.y1, this.y2);
if (this.isPointOnLine(x, y) && (x >= xMin && x <= xMax) && (y >= yMin && y <= yMax))
{
return true;
}
else
{
return false;
}
}
/**
*
* @method intersectLineLine
* @param {Any} line
* @return {Any}
*/
public intersectLineLine(line): any {
//return Phaser.intersectLineLine(this,line);
}
/**
*
* @method perp
* @param {Number} x
* @param {Number} y
* @param {Phaser.Line} [output]
* @return {Phaser.Line}
*/
public perp(x: number, y: number, output?: Line): Line {
if (this.y1 === this.y2)
{
if (output)
{
output.setTo(x, y, x, this.y1);
}
else
{
return new Line(x, y, x, this.y1);
}
}
var yInt: number = (y - this.perpSlope * x);
var pt: any = this.intersectLineLine({ x1: x, y1: y, x2: 0, y2: yInt });
if (output)
{
output.setTo(x, y, pt.x, pt.y);
}
else
{
return new Line(x, y, pt.x, pt.y);
}
}
/*
intersectLineCircle (circle:Circle)
{
var perp = this.perp()
return Phaser.intersectLineCircle(this,circle);
}
*/
/**
*
* @method toString
* @return {String}
*/
public toString(): string {
return "[{Line (x1=" + this.x1 + " y1=" + this.y1 + " x2=" + this.x2 + " y2=" + this.y2 + ")}]";
}
}
}

View file

@ -1,3 +1,5 @@
/// <reference path="../Game.ts" />
/**
* Point
*
@ -8,332 +10,340 @@
* @todo polar, interpolate
*/
class Point {
/**
* Phaser
*/
/**
* Creates a new point. If you pass no parameters to this method, a point is created at (0,0).
* @class Point
* @constructor
* @param {Number} x One-liner. Default is ?.
* @param {Number} y One-liner. Default is ?.
**/
constructor(x: number = 0, y: number = 0) {
module Phaser {
this.setTo(x, y);
export class Point {
}
/**
* Creates a new point. If you pass no parameters to this method, a point is created at (0,0).
* @class Point
* @constructor
* @param {Number} x One-liner. Default is ?.
* @param {Number} y One-liner. Default is ?.
**/
constructor(x: number = 0, y: number = 0) {
/**
* The horizontal position of this point (default 0)
* @property x
* @type Number
**/
public x: number;
this.setTo(x, y);
/**
* The vertical position of this point (default 0)
* @property y
* @type Number
**/
public y: number;
/**
* Adds the coordinates of another point to the coordinates of this point to create a new point.
* @method add
* @param {Point} point - The point to be added.
* @return {Point} The new Point object.
**/
public add(toAdd: Point, output?: Point = new Point): Point {
return output.setTo(this.x + toAdd.x, this.y + toAdd.y);
}
/**
* Adds the given values to the coordinates of this point and returns it
* @method addTo
* @param {Number} x - The amount to add to the x value of the point
* @param {Number} y - The amount to add to the x value of the point
* @return {Point} This Point object.
**/
public addTo(x?: number = 0, y?: number = 0): Point {
return this.setTo(this.x + x, this.y + y);
}
/**
* Adds the given values to the coordinates of this point and returns it
* @method addTo
* @param {Number} x - The amount to add to the x value of the point
* @param {Number} y - The amount to add to the x value of the point
* @return {Point} This Point object.
**/
public subtractFrom(x?: number = 0, y?: number = 0): Point {
return this.setTo(this.x - x, this.y - y);
}
/**
* Inverts the x and y values of this point
* @method invert
* @return {Point} This Point object.
**/
public invert(): Point {
return this.setTo(this.y, this.x);
}
/**
* Clamps this Point object to be between the given min and max
* @method clamp
* @param {number} The minimum value to clamp this Point to
* @param {number} The maximum value to clamp this Point to
* @return {Point} This Point object.
**/
public clamp(min: number, max: number): Point {
this.clampX(min, max);
this.clampY(min, max);
return this;
}
/**
* Clamps the x value of this Point object to be between the given min and max
* @method clampX
* @param {number} The minimum value to clamp this Point to
* @param {number} The maximum value to clamp this Point to
* @return {Point} This Point object.
**/
public clampX(min: number, max: number): Point {
this.x = Math.max(Math.min(this.x, max), min);
return this;
}
/**
* Clamps the y value of this Point object to be between the given min and max
* @method clampY
* @param {number} The minimum value to clamp this Point to
* @param {number} The maximum value to clamp this Point to
* @return {Point} This Point object.
**/
public clampY(min: number, max: number): Point {
this.x = Math.max(Math.min(this.x, max), min);
this.y = Math.max(Math.min(this.y, max), min);
return this;
}
/**
* Creates a copy of this Point.
* @method clone
* @param {Point} output Optional Point object. If given the values will be set into this object, otherwise a brand new Point object will be created and returned.
* @return {Point} The new Point object.
**/
public clone(output?: Point = new Point): Point {
return output.setTo(this.x, this.y);
}
/**
* Copies the point data from the source Point object into this Point object.
* @method copyFrom
* @param {Point} source - The point to copy from.
* @return {Point} This Point object. Useful for chaining method calls.
**/
public copyFrom(source: Point): Point {
return this.setTo(source.x, source.y);
}
/**
* Copies the point data from this Point object to the given target Point object.
* @method copyTo
* @param {Point} target - The point to copy to.
* @return {Point} The target Point object.
**/
public copyTo(target: Point): Point {
return target.setTo(this.x, this.y);
}
/**
* Returns the distance from this Point object to the given Point object.
* @method distanceFrom
* @param {Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
public distanceTo(target: Point, round?: bool = false): number {
var dx = this.x - target.x;
var dy = this.y - target.y;
if (round === true)
{
return Math.round(Math.sqrt(dx * dx + dy * dy));
}
else
{
return Math.sqrt(dx * dx + dy * dy);
/**
* The horizontal position of this point (default 0)
* @property x
* @type Number
**/
public x: number;
/**
* The vertical position of this point (default 0)
* @property y
* @type Number
**/
public y: number;
/**
* Adds the coordinates of another point to the coordinates of this point to create a new point.
* @method add
* @param {Point} point - The point to be added.
* @return {Point} The new Point object.
**/
public add(toAdd: Point, output?: Point = new Point): Point {
return output.setTo(this.x + toAdd.x, this.y + toAdd.y);
}
/**
* Adds the given values to the coordinates of this point and returns it
* @method addTo
* @param {Number} x - The amount to add to the x value of the point
* @param {Number} y - The amount to add to the x value of the point
* @return {Point} This Point object.
**/
public addTo(x?: number = 0, y?: number = 0): Point {
return this.setTo(this.x + x, this.y + y);
}
/**
* Adds the given values to the coordinates of this point and returns it
* @method addTo
* @param {Number} x - The amount to add to the x value of the point
* @param {Number} y - The amount to add to the x value of the point
* @return {Point} This Point object.
**/
public subtractFrom(x?: number = 0, y?: number = 0): Point {
return this.setTo(this.x - x, this.y - y);
}
/**
* Inverts the x and y values of this point
* @method invert
* @return {Point} This Point object.
**/
public invert(): Point {
return this.setTo(this.y, this.x);
}
/**
* Clamps this Point object to be between the given min and max
* @method clamp
* @param {number} The minimum value to clamp this Point to
* @param {number} The maximum value to clamp this Point to
* @return {Point} This Point object.
**/
public clamp(min: number, max: number): Point {
this.clampX(min, max);
this.clampY(min, max);
return this;
}
/**
* Clamps the x value of this Point object to be between the given min and max
* @method clampX
* @param {number} The minimum value to clamp this Point to
* @param {number} The maximum value to clamp this Point to
* @return {Point} This Point object.
**/
public clampX(min: number, max: number): Point {
this.x = Math.max(Math.min(this.x, max), min);
return this;
}
/**
* Clamps the y value of this Point object to be between the given min and max
* @method clampY
* @param {number} The minimum value to clamp this Point to
* @param {number} The maximum value to clamp this Point to
* @return {Point} This Point object.
**/
public clampY(min: number, max: number): Point {
this.x = Math.max(Math.min(this.x, max), min);
this.y = Math.max(Math.min(this.y, max), min);
return this;
}
/**
* Creates a copy of this Point.
* @method clone
* @param {Point} output Optional Point object. If given the values will be set into this object, otherwise a brand new Point object will be created and returned.
* @return {Point} The new Point object.
**/
public clone(output?: Point = new Point): Point {
return output.setTo(this.x, this.y);
}
/**
* Copies the point data from the source Point object into this Point object.
* @method copyFrom
* @param {Point} source - The point to copy from.
* @return {Point} This Point object. Useful for chaining method calls.
**/
public copyFrom(source: Point): Point {
return this.setTo(source.x, source.y);
}
/**
* Copies the point data from this Point object to the given target Point object.
* @method copyTo
* @param {Point} target - The point to copy to.
* @return {Point} The target Point object.
**/
public copyTo(target: Point): Point {
return target.setTo(this.x, this.y);
}
/**
* Returns the distance from this Point object to the given Point object.
* @method distanceFrom
* @param {Point} target - The destination Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
public distanceTo(target: Point, round?: bool = false): number {
var dx = this.x - target.x;
var dy = this.y - target.y;
if (round === true)
{
return Math.round(Math.sqrt(dx * dx + dy * dy));
}
else
{
return Math.sqrt(dx * dx + dy * dy);
}
}
/**
* Returns the distance between the two Point objects.
* @method distanceBetween
* @param {Point} pointA - The first Point object.
* @param {Point} pointB - The second Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between the two Point objects.
**/
public static distanceBetween(pointA: Point, pointB: Point, round?: bool = false): number {
var dx: number = pointA.x - pointB.x;
var dy: number = pointA.y - pointB.y;
if (round === true)
{
return Math.round(Math.sqrt(dx * dx + dy * dy));
}
else
{
return Math.sqrt(dx * dx + dy * dy);
}
}
/**
* Returns true if the distance between this point and a target point is greater than or equal a specified distance.
* This avoids using a costly square root operation
* @method distanceCompare
* @param {Point} target - The Point object to use for comparison.
* @param {Number} distance - The distance to use for comparison.
* @return {Boolena} True if distance is >= specified distance.
**/
public distanceCompare(target: Point, distance: number): bool {
if (this.distanceTo(target) >= distance)
{
return true;
}
else
{
return false;
}
}
/**
* Determines whether this Point object and the given point object are equal. They are equal if they have the same x and y values.
* @method equals
* @param {Point} point - The point to compare against.
* @return {Boolean} A value of true if the object is equal to this Point object; false if it is not equal.
**/
public equals(toCompare: Point): bool {
if (this.x === toCompare.x && this.y === toCompare.y)
{
return true;
}
else
{
return false;
}
}
/**
* Determines a point between two specified points. The parameter f determines where the new interpolated point is located relative to the two end points specified by parameters pt1 and pt2.
* The closer the value of the parameter f is to 1.0, the closer the interpolated point is to the first point (parameter pt1). The closer the value of the parameter f is to 0, the closer the interpolated point is to the second point (parameter pt2).
* @method interpolate
* @param {Point} pointA - The first Point object.
* @param {Point} pointB - The second Point object.
* @param {Number} f - The level of interpolation between the two points. Indicates where the new point will be, along the line between pt1 and pt2. If f=1, pt1 is returned; if f=0, pt2 is returned.
* @return {Point} The new interpolated Point object.
**/
public interpolate(pointA, pointB, f) {
}
/**
* Offsets the Point object by the specified amount. The value of dx is added to the original value of x to create the new x value.
* The value of dy is added to the original value of y to create the new y value.
* @method offset
* @param {Number} dx - The amount by which to offset the horizontal coordinate, x.
* @param {Number} dy - The amount by which to offset the vertical coordinate, y.
* @return {Point} This Point object. Useful for chaining method calls.
**/
public offset(dx: number, dy: number): Point {
this.x += dx;
this.y += dy;
return this;
}
/**
* Converts a pair of polar coordinates to a Cartesian point coordinate.
* @method polar
* @param {Number} length - The length coordinate of the polar pair.
* @param {Number} angle - The angle, in radians, of the polar pair.
* @return {Point} The new Cartesian Point object.
**/
public polar(length, angle) {
}
/**
* Sets the x and y values of this Point object to the given coordinates.
* @method set
* @param {Number} x - The horizontal position of this point.
* @param {Number} y - The vertical position of this point.
* @return {Point} This Point object. Useful for chaining method calls.
**/
public setTo(x: number, y: number): Point {
this.x = x;
this.y = y;
return this;
}
/**
* Subtracts the coordinates of another point from the coordinates of this point to create a new point.
* @method subtract
* @param {Point} point - The point to be subtracted.
* @param {Point} output Optional Point object. If given the values will be set into this object, otherwise a brand new Point object will be created and returned.
* @return {Point} The new Point object.
**/
public subtract(point: Point, output?: Point = new Point): Point {
return output.setTo(this.x - point.x, this.y - point.y);
}
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the instance.
**/
public toString(): string {
return '[{Point (x=' + this.x + ' y=' + this.y + ')}]';
}
}
/**
* Returns the distance between the two Point objects.
* @method distanceBetween
* @param {Point} pointA - The first Point object.
* @param {Point} pointB - The second Point object.
* @param {Boolean} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between the two Point objects.
**/
public static distanceBetween(pointA: Point, pointB: Point, round?: bool = false): number {
var dx: number = pointA.x - pointB.x;
var dy: number = pointA.y - pointB.y;
if (round === true)
{
return Math.round(Math.sqrt(dx * dx + dy * dy));
}
else
{
return Math.sqrt(dx * dx + dy * dy);
}
}
/**
* Returns true if the distance between this point and a target point is greater than or equal a specified distance.
* This avoids using a costly square root operation
* @method distanceCompare
* @param {Point} target - The Point object to use for comparison.
* @param {Number} distance - The distance to use for comparison.
* @return {Boolena} True if distance is >= specified distance.
**/
public distanceCompare(target: Point, distance: number): bool {
if (this.distanceTo(target) >= distance)
{
return true;
}
else
{
return false;
}
}
/**
* Determines whether this Point object and the given point object are equal. They are equal if they have the same x and y values.
* @method equals
* @param {Point} point - The point to compare against.
* @return {Boolean} A value of true if the object is equal to this Point object; false if it is not equal.
**/
public equals(toCompare: Point): bool {
if (this.x === toCompare.x && this.y === toCompare.y)
{
return true;
}
else
{
return false;
}
}
/**
* Determines a point between two specified points. The parameter f determines where the new interpolated point is located relative to the two end points specified by parameters pt1 and pt2.
* The closer the value of the parameter f is to 1.0, the closer the interpolated point is to the first point (parameter pt1). The closer the value of the parameter f is to 0, the closer the interpolated point is to the second point (parameter pt2).
* @method interpolate
* @param {Point} pointA - The first Point object.
* @param {Point} pointB - The second Point object.
* @param {Number} f - The level of interpolation between the two points. Indicates where the new point will be, along the line between pt1 and pt2. If f=1, pt1 is returned; if f=0, pt2 is returned.
* @return {Point} The new interpolated Point object.
**/
public interpolate(pointA, pointB, f) {
}
/**
* Offsets the Point object by the specified amount. The value of dx is added to the original value of x to create the new x value.
* The value of dy is added to the original value of y to create the new y value.
* @method offset
* @param {Number} dx - The amount by which to offset the horizontal coordinate, x.
* @param {Number} dy - The amount by which to offset the vertical coordinate, y.
* @return {Point} This Point object. Useful for chaining method calls.
**/
public offset(dx: number, dy: number): Point {
this.x += dx;
this.y += dy;
return this;
}
/**
* Converts a pair of polar coordinates to a Cartesian point coordinate.
* @method polar
* @param {Number} length - The length coordinate of the polar pair.
* @param {Number} angle - The angle, in radians, of the polar pair.
* @return {Point} The new Cartesian Point object.
**/
public polar(length, angle) {
}
/**
* Sets the x and y values of this Point object to the given coordinates.
* @method set
* @param {Number} x - The horizontal position of this point.
* @param {Number} y - The vertical position of this point.
* @return {Point} This Point object. Useful for chaining method calls.
**/
public setTo(x: number, y: number): Point {
this.x = x;
this.y = y;
return this;
}
/**
* Subtracts the coordinates of another point from the coordinates of this point to create a new point.
* @method subtract
* @param {Point} point - The point to be subtracted.
* @param {Point} output Optional Point object. If given the values will be set into this object, otherwise a brand new Point object will be created and returned.
* @return {Point} The new Point object.
**/
public subtract(point: Point, output?: Point = new Point): Point {
return output.setTo(this.x - point.x, this.y - point.y);
}
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the instance.
**/
public toString(): string {
return '[{Point (x=' + this.x + ' y=' + this.y + ')}]';
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,45 +1,54 @@
/// <reference path="../Basic.ts" />
/// <reference path="../Game.ts" />
/**
* A miniature linked list class.
* Useful for optimizing time-critical or highly repetitive tasks!
* See <code>QuadTree</code> for how to use it, IF YOU DARE.
*/
class LinkedList {
/**
* Creates a new link, and sets <code>object</code> and <code>next</code> to <code>null</code>.
*/
constructor() {
/**
* Phaser
*/
this.object = null;
this.next = null;
module Phaser {
}
export class LinkedList {
/**
* Stores a reference to an <code>Basic</code>.
*/
public object: Basic;
/**
* Creates a new link, and sets <code>object</code> and <code>next</code> to <code>null</code>.
*/
constructor() {
/**
* Stores a reference to the next link in the list.
*/
public next: LinkedList;
this.object = null;
this.next = null;
/**
* Clean up memory.
*/
public destroy() {
this.object = null;
if (this.next != null)
{
this.next.destroy();
}
this.next = null;
/**
* Stores a reference to an <code>Basic</code>.
*/
public object: Basic;
/**
* Stores a reference to the next link in the list.
*/
public next: LinkedList;
/**
* Clean up memory.
*/
public destroy() {
this.object = null;
if (this.next != null)
{
this.next.destroy();
}
this.next = null;
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,5 @@
/// <reference path="../Game.ts" />
/**
* Repeatable Random Data Generator
*
@ -10,273 +12,281 @@
* @author Richard Davey, TypeScript conversion and additional methods
*/
class RandomDataGenerator {
/**
* Phaser
*/
/**
* @constructor
* @param {Array} seeds
* @return {Kiwi.Utils.RandomDataGenerator}
*/
constructor(seeds?: string[] = []) {
module Phaser {
this.sow(seeds);
export class RandomDataGenerator {
}
/**
* @constructor
* @param {Array} seeds
* @return {Phaser.RandomDataGenerator}
*/
constructor(seeds?: string[] = []) {
/**
* @property s0
* @type Any
* @private
*/
private s0;
this.sow(seeds);
/**
* @property s1
* @type Any
* @private
*/
private s1;
/**
* @property s2
* @type Any
* @private
*/
private s2;
/**
* @property c
* @type Number
* @private
*/
private c: number = 1;
/**
* @method uint32
* @private
*/
private uint32() {
return this.rnd.apply(this) * 0x100000000; // 2^32
}
/**
* @method fract32
* @private
*/
private fract32() {
return this.rnd.apply(this) + (this.rnd.apply(this) * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
}
// private random helper
/**
* @method rnd
* @private
*/
private rnd() {
var t = 2091639 * this.s0 + this.c * 2.3283064365386963e-10; // 2^-32
this.c = t | 0;
this.s0 = this.s1;
this.s1 = this.s2;
this.s2 = t - this.c;
return this.s2;
}
/**
* @method hash
* @param {Any} data
* @private
*/
private hash(data) {
var h, i, n;
n = 0xefc8249d;
data = data.toString();
for (i = 0; i < data.length; i++)
{
n += data.charCodeAt(i);
h = 0.02519603282416938 * n;
n = h >>> 0;
h -= n;
h *= n;
n = h >>> 0;
h -= n;
n += h * 0x100000000; // 2^32
}
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
/**
* @property s0
* @type Any
* @private
*/
private s0;
}
/**
* @property s1
* @type Any
* @private
*/
private s1;
/**
* Reset the seed of the random data generator
* @method sow
* @param {Array} seeds
*/
public sow(seeds?: string[] = []) {
/**
* @property s2
* @type Any
* @private
*/
private s2;
this.s0 = this.hash(' ');
this.s1 = this.hash(this.s0);
this.s2 = this.hash(this.s1);
/**
* @property c
* @type Number
* @private
*/
private c: number = 1;
var seed;
/**
* @method uint32
* @private
*/
private uint32() {
for (var i = 0; seed = seeds[i++];)
{
this.s0 -= this.hash(seed);
this.s0 += ~~(this.s0 < 0);
return this.rnd.apply(this) * 0x100000000; // 2^32
this.s1 -= this.hash(seed);
this.s1 += ~~(this.s1 < 0);
}
/**
* @method fract32
* @private
*/
private fract32() {
return this.rnd.apply(this) + (this.rnd.apply(this) * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
}
// private random helper
/**
* @method rnd
* @private
*/
private rnd() {
var t = 2091639 * this.s0 + this.c * 2.3283064365386963e-10; // 2^-32
this.c = t | 0;
this.s0 = this.s1;
this.s1 = this.s2;
this.s2 = t - this.c;
return this.s2;
}
/**
* @method hash
* @param {Any} data
* @private
*/
private hash(data) {
var h, i, n;
n = 0xefc8249d;
data = data.toString();
for (i = 0; i < data.length; i++)
{
n += data.charCodeAt(i);
h = 0.02519603282416938 * n;
n = h >>> 0;
h -= n;
h *= n;
n = h >>> 0;
h -= n;
n += h * 0x100000000; // 2^32
}
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
}
/**
* Reset the seed of the random data generator
* @method sow
* @param {Array} seeds
*/
public sow(seeds?: string[] = []) {
this.s0 = this.hash(' ');
this.s1 = this.hash(this.s0);
this.s2 = this.hash(this.s1);
var seed;
for (var i = 0; seed = seeds[i++];)
{
this.s0 -= this.hash(seed);
this.s0 += ~~(this.s0 < 0);
this.s1 -= this.hash(seed);
this.s1 += ~~(this.s1 < 0);
this.s2 -= this.hash(seed);
this.s2 += ~~(this.s2 < 0);
}
}
/**
* Returns a random integer between 0 and 2^32
* @method integer
* @return {Number}
*/
public get integer(): number {
return this.uint32();
}
/**
* Returns a random real number between 0 and 1
* @method frac
* @return {Number}
*/
public get frac(): number {
return this.fract32();
}
/**
* Returns a random real number between 0 and 2^32
* @method real
* @return {Number}
*/
public get real(): number {
return this.uint32() + this.fract32();
}
/**
* Returns a random integer between min and max
* @method integerInRange
* @param {Number} min
* @param {Number} max
* @return {Number}
*/
public integerInRange(min: number, max: number): number {
return Math.floor(this.realInRange(min, max));
}
/**
* Returns a random real number between min and max
* @method realInRange
* @param {Number} min
* @param {Number} max
* @return {Number}
*/
public realInRange(min: number, max: number): number {
min = min || 0;
max = max || 0;
return this.frac * (max - min) + min;
}
/**
* Returns a random real number between -1 and 1
* @method normal
* @return {Number}
*/
public get normal(): number {
return 1 - 2 * this.frac;
}
/**
* Returns a valid v4 UUID hex string (from https://gist.github.com/1308368)
* @method uuid
* @return {String}
*/
public get uuid(): string {
var a, b;
for (
b = a = '';
a++ < 36;
b += ~a % 5 | a * 3 & 4 ? (a ^ 15 ? 8 ^ this.frac * (a ^ 20 ? 16 : 4) : 4).toString(16) : '-'
);
return b;
}
/**
* Returns a random member of `array`
* @method pick
* @param {Any} array
*/
public pick(array) {
return array[this.integerInRange(0, array.length)];
}
/**
* Returns a random member of `array`, favoring the earlier entries
* @method weightedPick
* @param {Any} array
*/
public weightedPick(array) {
return array[~~(Math.pow(this.frac, 2) * array.length)];
}
/**
* Returns a random timestamp between min and max, or between the beginning of 2000 and the end of 2020 if min and max aren't specified
* @method timestamp
* @param {Number} min
* @param {Number} max
*/
public timestamp(min?: number = 946684800000, max?: number = 1577862000000): number {
return this.realInRange(min, max);
}
/**
* Returns a random angle between -180 and 180
* @method angle
*/
public get angle(): number {
return this.integerInRange(-180, 180);
this.s2 -= this.hash(seed);
this.s2 += ~~(this.s2 < 0);
}
}
/**
* Returns a random integer between 0 and 2^32
* @method integer
* @return {Number}
*/
public get integer(): number {
return this.uint32();
}
/**
* Returns a random real number between 0 and 1
* @method frac
* @return {Number}
*/
public get frac(): number {
return this.fract32();
}
/**
* Returns a random real number between 0 and 2^32
* @method real
* @return {Number}
*/
public get real(): number {
return this.uint32() + this.fract32();
}
/**
* Returns a random integer between min and max
* @method integerInRange
* @param {Number} min
* @param {Number} max
* @return {Number}
*/
public integerInRange(min: number, max: number): number {
return Math.floor(this.realInRange(min, max));
}
/**
* Returns a random real number between min and max
* @method realInRange
* @param {Number} min
* @param {Number} max
* @return {Number}
*/
public realInRange(min: number, max: number): number {
min = min || 0;
max = max || 0;
return this.frac * (max - min) + min;
}
/**
* Returns a random real number between -1 and 1
* @method normal
* @return {Number}
*/
public get normal(): number {
return 1 - 2 * this.frac;
}
/**
* Returns a valid v4 UUID hex string (from https://gist.github.com/1308368)
* @method uuid
* @return {String}
*/
public get uuid(): string {
var a, b;
for (
b = a = '';
a++ < 36;
b += ~a % 5 | a * 3 & 4 ? (a ^ 15 ? 8 ^ this.frac * (a ^ 20 ? 16 : 4) : 4).toString(16) : '-'
);
return b;
}
/**
* Returns a random member of `array`
* @method pick
* @param {Any} array
*/
public pick(array) {
return array[this.integerInRange(0, array.length)];
}
/**
* Returns a random member of `array`, favoring the earlier entries
* @method weightedPick
* @param {Any} array
*/
public weightedPick(array) {
return array[~~(Math.pow(this.frac, 2) * array.length)];
}
/**
* Returns a random timestamp between min and max, or between the beginning of 2000 and the end of 2020 if min and max aren't specified
* @method timestamp
* @param {Number} min
* @param {Number} max
*/
public timestamp(min?: number = 946684800000, max?: number = 1577862000000):number {
return this.realInRange(min, max);
}
/**
* Returns a random angle between -180 and 180
* @method angle
*/
public get angle():number {
return this.integerInRange(-180, 180);
}
}
}

View file

@ -1,3 +1,5 @@
/// <reference path="../Game.ts" />
/**
* RequestAnimationFrame
*
@ -7,199 +9,207 @@
* @author Richard Davey
*/
class RequestAnimationFrame {
/**
* Phaser
*/
/**
* Constructor
* @param {Any} callback
* @return {RequestAnimationFrame} This object.
*/
constructor(callback, callbackContext) {
module Phaser {
this._callback = callback;
this._callbackContext = callbackContext;
export class RequestAnimationFrame {
var vendors = ['ms', 'moz', 'webkit', 'o'];
/**
* Constructor
* @param {Any} callback
* @return {RequestAnimationFrame} This object.
*/
constructor(callback, callbackContext) {
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; x++)
{
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'];
}
this.start();
}
/**
*
* @property _callback
* @type Any
* @private
**/
private _callback;
private _callbackContext;
/**
*
* @method callback
* @param {Any} callback
**/
public setCallback(callback) {
this._callback = callback;
}
/**
*
* @property _timeOutID
* @type Any
* @private
**/
private _timeOutID;
/**
*
* @property _isSetTimeOut
* @type Boolean
* @private
**/
private _isSetTimeOut: bool = false;
/**
*
* @method usingSetTimeOut
* @return Boolean
**/
public isUsingSetTimeOut(): bool {
return this._isSetTimeOut;
}
/**
*
* @method usingRAF
* @return Boolean
**/
public isUsingRAF(): bool {
if (this._isSetTimeOut === true)
{
return false;
}
else
{
return true;
}
}
/**
*
* @property lastTime
* @type Number
**/
public lastTime: number = 0;
/**
*
* @property currentTime
* @type Number
**/
public currentTime: number = 0;
/**
*
* @property isRunning
* @type Boolean
**/
public isRunning: bool = false;
/**
*
* @method start
* @param {Any} [callback]
**/
public start(callback? = null) {
if (callback)
{
this._callback = callback;
this._callbackContext = callbackContext;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; x++)
{
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'];
}
this.start();
}
if (!window.requestAnimationFrame)
{
this._isSetTimeOut = true;
this._timeOutID = window.setTimeout(() => this.SetTimeoutUpdate(), 0);
/**
*
* @property _callback
* @type Any
* @private
**/
private _callback;
private _callbackContext;
/**
*
* @method callback
* @param {Any} callback
**/
public setCallback(callback) {
this._callback = callback;
}
else
{
this._isSetTimeOut = false;
/**
*
* @property _timeOutID
* @type Any
* @private
**/
private _timeOutID;
/**
*
* @property _isSetTimeOut
* @type Boolean
* @private
**/
private _isSetTimeOut: bool = false;
/**
*
* @method usingSetTimeOut
* @return Boolean
**/
public isUsingSetTimeOut(): bool {
return this._isSetTimeOut;
}
/**
*
* @method usingRAF
* @return Boolean
**/
public isUsingRAF(): bool {
if (this._isSetTimeOut === true)
{
return false;
}
else
{
return true;
}
}
/**
*
* @property lastTime
* @type Number
**/
public lastTime: number = 0;
/**
*
* @property currentTime
* @type Number
**/
public currentTime: number = 0;
/**
*
* @property isRunning
* @type Boolean
**/
public isRunning: bool = false;
/**
*
* @method start
* @param {Any} [callback]
**/
public start(callback? = null) {
if (callback)
{
this._callback = callback;
}
if (!window.requestAnimationFrame)
{
this._isSetTimeOut = true;
this._timeOutID = window.setTimeout(() => this.SetTimeoutUpdate(), 0);
}
else
{
this._isSetTimeOut = false;
window.requestAnimationFrame(() => this.RAFUpdate());
}
this.isRunning = true;
}
/**
*
* @method stop
**/
public stop() {
if (this._isSetTimeOut)
{
clearTimeout(this._timeOutID);
}
else
{
window.cancelAnimationFrame;
}
this.isRunning = false;
}
public RAFUpdate() {
// Not in IE8 (but neither is RAF) also doesn't use a high performance timer (window.performance.now)
this.currentTime = Date.now();
if (this._callback)
{
this._callback.call(this._callbackContext);
}
var timeToCall: number = Math.max(0, 16 - (this.currentTime - this.lastTime));
window.requestAnimationFrame(() => this.RAFUpdate());
this.lastTime = this.currentTime + timeToCall;
}
this.isRunning = true;
/**
*
* @method SetTimeoutUpdate
**/
public SetTimeoutUpdate() {
// Not in IE8
this.currentTime = Date.now();
if (this._callback)
{
this._callback.call(this._callbackContext);
}
var timeToCall: number = Math.max(0, 16 - (this.currentTime - this.lastTime));
this._timeOutID = window.setTimeout(() => this.SetTimeoutUpdate(), timeToCall);
this.lastTime = this.currentTime + timeToCall;
}
}
/**
*
* @method stop
**/
public stop() {
if (this._isSetTimeOut)
{
clearTimeout(this._timeOutID);
}
else
{
window.cancelAnimationFrame;
}
this.isRunning = false;
}
public RAFUpdate() {
// Not in IE8 (but neither is RAF) also doesn't use a high performance timer (window.performance.now)
this.currentTime = Date.now();
if (this._callback)
{
this._callback.call(this._callbackContext);
}
var timeToCall: number = Math.max(0, 16 - (this.currentTime - this.lastTime));
window.requestAnimationFrame(() => this.RAFUpdate());
this.lastTime = this.currentTime + timeToCall;
}
/**
*
* @method SetTimeoutUpdate
**/
public SetTimeoutUpdate() {
// Not in IE8
this.currentTime = Date.now();
if (this._callback)
{
this._callback.call(this._callbackContext);
}
var timeToCall: number = Math.max(0, 16 - (this.currentTime - this.lastTime));
this._timeOutID = window.setTimeout(() => this.SetTimeoutUpdate(), timeToCall);
this.lastTime = this.currentTime + timeToCall;
}
}
}

View file

@ -9,157 +9,165 @@
* https://raw.github.com/zynga/viewporter/master/MIT-LICENSE.txt
*/
class StageScaleMode {
/**
* Phaser
*/
constructor(game: Game) {
module Phaser {
this._game = game;
export class StageScaleMode {
this.orientation = window['orientation'];
constructor(game: Game) {
window.addEventListener('orientationchange', (event) => this.checkOrientation(event), false);
this._game = game;
}
private _game: Game;
private _startHeight: number = 0;
private _iterations: number;
private _check;
// Specifies that the game be visible in the specified area without trying to preserve the original aspect ratio.
public static EXACT_FIT:number = 0;
// Specifies that the size of the game be fixed, so that it remains unchanged even if the size of the window changes.
public static NO_SCALE:number = 1;
// Specifies that the entire game be visible in the specified area without distortion while maintaining the original aspect ratio.
public static SHOW_ALL:number = 2;
public width: number = 0;
public height: number = 0;
public orientation;
public update() {
if (this._game.stage.scaleMode !== StageScaleMode.NO_SCALE && (window.innerWidth !== this.width || window.innerHeight !== this.height))
{
this.refresh();
}
}
public get isLandscape(): bool {
return window['orientation'] === 90 || window['orientation'] === -90;
}
private checkOrientation(event) {
if (window['orientation'] !== this.orientation)
{
this.refresh();
this.orientation = window['orientation'];
window.addEventListener('orientationchange', (event) => this.checkOrientation(event), false);
}
}
private _game: Game;
private _startHeight: number = 0;
private _iterations: number;
private _check;
private refresh() {
// Specifies that the game be visible in the specified area without trying to preserve the original aspect ratio.
public static EXACT_FIT: number = 0;
// We can't do anything about the status bars in iPads, web apps or desktops
if (this._game.device.iPad == false && this._game.device.webApp == false && this._game.device.desktop == false)
{
document.documentElement.style.minHeight = '5000px';
// Specifies that the size of the game be fixed, so that it remains unchanged even if the size of the window changes.
public static NO_SCALE: number = 1;
this._startHeight = window.innerHeight;
// Specifies that the entire game be visible in the specified area without distortion while maintaining the original aspect ratio.
public static SHOW_ALL: number = 2;
if (this._game.device.android && this._game.device.chrome == false)
{
window.scrollTo(0, 1);
}
else
{
window.scrollTo(0, 0);
}
}
public width: number = 0;
public height: number = 0;
if (this._check == null)
{
this._iterations = 40;
this._check = window.setInterval(() => this.setScreenSize(), 10);
}
public orientation;
}
public update() {
private setScreenSize() {
if (this._game.device.iPad == false && this._game.device.webApp == false && this._game.device.desktop == false)
{
if (this._game.device.android && this._game.device.chrome == false)
if (this._game.stage.scaleMode !== StageScaleMode.NO_SCALE && (window.innerWidth !== this.width || window.innerHeight !== this.height))
{
window.scrollTo(0, 1);
}
else
{
window.scrollTo(0, 0);
this.refresh();
}
}
this._iterations--;
public get isLandscape(): bool {
return window['orientation'] === 90 || window['orientation'] === -90;
}
if (window.innerHeight > this._startHeight || this._iterations < 0)
{
// Set minimum height of content to new window height
document.documentElement.style.minHeight = window.innerHeight + 'px';
private checkOrientation(event) {
if (this._game.stage.scaleMode == StageScaleMode.EXACT_FIT)
if (window['orientation'] !== this.orientation)
{
if (this._game.stage.maxScaleX && window.innerWidth > this._game.stage.maxScaleX)
this.refresh();
this.orientation = window['orientation'];
}
}
private refresh() {
// We can't do anything about the status bars in iPads, web apps or desktops
if (this._game.device.iPad == false && this._game.device.webApp == false && this._game.device.desktop == false)
{
document.documentElement.style.minHeight = '5000px';
this._startHeight = window.innerHeight;
if (this._game.device.android && this._game.device.chrome == false)
{
this.width = this._game.stage.maxScaleX;
window.scrollTo(0, 1);
}
else
{
this.width = window.innerWidth;
window.scrollTo(0, 0);
}
}
if (this._game.stage.maxScaleY && window.innerHeight > this._game.stage.maxScaleY)
if (this._check == null)
{
this._iterations = 40;
this._check = window.setInterval(() => this.setScreenSize(), 10);
}
}
private setScreenSize() {
if (this._game.device.iPad == false && this._game.device.webApp == false && this._game.device.desktop == false)
{
if (this._game.device.android && this._game.device.chrome == false)
{
this.height = this._game.stage.maxScaleY;
window.scrollTo(0, 1);
}
else
{
this.height = window.innerHeight;
window.scrollTo(0, 0);
}
}
else if (this._game.stage.scaleMode == StageScaleMode.SHOW_ALL)
this._iterations--;
if (window.innerHeight > this._startHeight || this._iterations < 0)
{
var multiplier = Math.min((window.innerHeight / this._game.stage.height), (window.innerWidth / this._game.stage.width));
// Set minimum height of content to new window height
document.documentElement.style.minHeight = window.innerHeight + 'px';
this.width = Math.round(this._game.stage.width * multiplier);
this.height = Math.round(this._game.stage.height * multiplier);
if (this._game.stage.scaleMode == StageScaleMode.EXACT_FIT)
{
if (this._game.stage.maxScaleX && window.innerWidth > this._game.stage.maxScaleX)
{
this.width = this._game.stage.maxScaleX;
}
else
{
this.width = window.innerWidth;
}
if (this._game.stage.maxScaleX && this.width > this._game.stage.maxScaleX)
{
this.width = this._game.stage.maxScaleX;
}
if (this._game.stage.maxScaleY && this.height > this._game.stage.maxScaleY)
{
this.height = this._game.stage.maxScaleY;
if (this._game.stage.maxScaleY && window.innerHeight > this._game.stage.maxScaleY)
{
this.height = this._game.stage.maxScaleY;
}
else
{
this.height = window.innerHeight;
}
}
else if (this._game.stage.scaleMode == StageScaleMode.SHOW_ALL)
{
var multiplier = Math.min((window.innerHeight / this._game.stage.height), (window.innerWidth / this._game.stage.width));
this.width = Math.round(this._game.stage.width * multiplier);
this.height = Math.round(this._game.stage.height * multiplier);
if (this._game.stage.maxScaleX && this.width > this._game.stage.maxScaleX)
{
this.width = this._game.stage.maxScaleX;
}
if (this._game.stage.maxScaleY && this.height > this._game.stage.maxScaleY)
{
this.height = this._game.stage.maxScaleY;
}
}
this._game.stage.canvas.style.width = this.width + 'px';
this._game.stage.canvas.style.height = this.height + 'px';
this._game.input.scaleX = this._game.stage.width / this.width;
this._game.input.scaleY = this._game.stage.height / this.height;
clearInterval(this._check);
this._check = null;
}
this._game.stage.canvas.style.width = this.width + 'px';
this._game.stage.canvas.style.height = this.height + 'px';
this._game.input.scaleX = this._game.stage.width / this.width;
this._game.input.scaleY = this._game.stage.height / this.height;
clearInterval(this._check);
this._check = null;
}
}
}

View file

@ -1,5 +1,4 @@
/// <reference path="../GameObject.ts" />
/// <reference path="../Tilemap.ts" />
/// <reference path="../Game.ts" />
/**
* A simple helper object for <code>Tilemap</code> that helps expand collision opportunities and control.
@ -9,79 +8,88 @@
* @author Adam Atomic
* @author Richard Davey
*/
class Tile extends GameObject {
/**
* Instantiate this new tile object. This is usually called from <code>FlxTilemap.loadMap()</code>.
*
* @param Tilemap A reference to the tilemap object creating the tile.
* @param Index The actual core map data index for this tile type.
* @param Width The width of the tile.
* @param Height The height of the tile.
* @param Visible Whether the tile is visible or not.
* @param AllowCollisions The collision flags for the object. By default this value is ANY or NONE depending on the parameters sent to loadMap().
*/
constructor(game: Game, Tilemap: Tilemap, Index: number, Width: number, Height: number, Visible: bool, AllowCollisions: number) {
/**
* Phaser
*/
super(game, 0, 0, Width, Height);
module Phaser {
this.immovable = true;
this.moves = false;
this.callback = null;
this.filter = null;
export class Tile extends GameObject {
this.tilemap = Tilemap;
this.index = Index;
this.visible = Visible;
this.allowCollisions = AllowCollisions;
/**
* Instantiate this new tile object. This is usually called from <code>FlxTilemap.loadMap()</code>.
*
* @param Tilemap A reference to the tilemap object creating the tile.
* @param Index The actual core map data index for this tile type.
* @param Width The width of the tile.
* @param Height The height of the tile.
* @param Visible Whether the tile is visible or not.
* @param AllowCollisions The collision flags for the object. By default this value is ANY or NONE depending on the parameters sent to loadMap().
*/
constructor(game: Game, Tilemap: Tilemap, Index: number, Width: number, Height: number, Visible: bool, AllowCollisions: number) {
this.mapIndex = 0;
super(game, 0, 0, Width, Height);
this.immovable = true;
this.moves = false;
this.callback = null;
this.filter = null;
this.tilemap = Tilemap;
this.index = Index;
this.visible = Visible;
this.allowCollisions = AllowCollisions;
this.mapIndex = 0;
}
/**
* This function is called whenever an object hits a tile of this type.
* This function should take the form <code>myFunction(Tile:FlxTile,Object:FlxObject)</code>.
* Defaults to null, set through <code>FlxTilemap.setTileProperties()</code>.
*/
public callback;
/**
* Each tile can store its own filter class for their callback functions.
* That is, the callback will only be triggered if an object with a class
* type matching the filter touched it.
* Defaults to null, set through <code>FlxTilemap.setTileProperties()</code>.
*/
public filter;
/**
* A reference to the tilemap this tile object belongs to.
*/
public tilemap: Tilemap;
/**
* The index of this tile type in the core map data.
* For example, if your map only has 16 kinds of tiles in it,
* this number is usually between 0 and 15.
*/
public index: number;
/**
* The current map index of this tile object at this moment.
* You can think of tile objects as moving around the tilemap helping with collisions.
* This value is only reliable and useful if used from the callback function.
*/
public mapIndex: number;
/**
* Clean up memory.
*/
public destroy() {
super.destroy();
this.callback = null;
this.tilemap = null;
}
}
/**
* This function is called whenever an object hits a tile of this type.
* This function should take the form <code>myFunction(Tile:FlxTile,Object:FlxObject)</code>.
* Defaults to null, set through <code>FlxTilemap.setTileProperties()</code>.
*/
public callback;
/**
* Each tile can store its own filter class for their callback functions.
* That is, the callback will only be triggered if an object with a class
* type matching the filter touched it.
* Defaults to null, set through <code>FlxTilemap.setTileProperties()</code>.
*/
public filter;
/**
* A reference to the tilemap this tile object belongs to.
*/
public tilemap: Tilemap;
/**
* The index of this tile type in the core map data.
* For example, if your map only has 16 kinds of tiles in it,
* this number is usually between 0 and 15.
*/
public index: number;
/**
* The current map index of this tile object at this moment.
* You can think of tile objects as moving around the tilemap helping with collisions.
* This value is only reliable and useful if used from the callback function.
*/
public mapIndex: number;
/**
* Clean up memory.
*/
public destroy() {
super.destroy();
this.callback = null;
this.tilemap = null;
}
}
}

View file

@ -1,172 +1,173 @@
/// <reference path="../Game.ts" />
/// <reference path="../GameObject.ts" />
/// <reference path="../Tilemap.ts" />
/// <reference path="../geom/Rectangle.ts" />
/// <reference path="Camera.ts" />
/**
* A Tilemap Buffer
*
* @author Richard Davey
*/
class TilemapBuffer {
constructor(game: Game, camera:Camera, tilemap:Tilemap, texture, tileOffsets) {
module Phaser {
//console.log('New TilemapBuffer created for Camera ' + camera.ID);
export class TilemapBuffer {
this._game = game;
this.camera = camera;
this._tilemap = tilemap;
this._texture = texture;
this._tileOffsets = tileOffsets;
constructor(game: Game, camera: Camera, tilemap: Tilemap, texture, tileOffsets) {
//this.createCanvas();
//console.log('New TilemapBuffer created for Camera ' + camera.ID);
}
this._game = game;
this.camera = camera;
this._tilemap = tilemap;
this._texture = texture;
this._tileOffsets = tileOffsets;
private _game: Game;
private _tilemap: Tilemap;
private _texture;
private _tileOffsets;
//this.createCanvas();
private _startX: number = 0;
private _maxX: number = 0;
private _startY: number = 0;
private _maxY: number = 0;
private _tx: number = 0;
private _ty: number = 0;
private _dx: number = 0;
private _dy: number = 0;
private _oldCameraX: number = 0;
private _oldCameraY: number = 0;
private _dirty: bool = true;
private _columnData;
public camera: Camera;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
private createCanvas() {
this.canvas = <HTMLCanvasElement> document.createElement('canvas');
this.canvas.width = this._game.stage.width;
this.canvas.height = this._game.stage.height;
this.context = this.canvas.getContext('2d');
}
public update() {
/*
if (this.camera.worldView.x !== this._oldCameraX || this.camera.worldView.y !== this._oldCameraY)
{
this._dirty = true;
}
this._oldCameraX = this.camera.worldView.x;
this._oldCameraY = this.camera.worldView.y;
*/
private _game: Game;
private _tilemap: Tilemap;
private _texture;
private _tileOffsets;
}
private _startX: number = 0;
private _maxX: number = 0;
private _startY: number = 0;
private _maxY: number = 0;
private _tx: number = 0;
private _ty: number = 0;
private _dx: number = 0;
private _dy: number = 0;
private _oldCameraX: number = 0;
private _oldCameraY: number = 0;
private _dirty: bool = true;
private _columnData;
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
public camera: Camera;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
this._game.stage.context.fillStyle = color;
this._game.stage.context.fillText('TilemapBuffer', x, y);
this._game.stage.context.fillText('startX: ' + this._startX + ' endX: ' + this._maxX, x, y + 14);
this._game.stage.context.fillText('startY: ' + this._startY + ' endY: ' + this._maxY, x, y + 28);
this._game.stage.context.fillText('dx: ' + this._dx + ' dy: ' + this._dy, x, y + 42);
this._game.stage.context.fillText('Dirty: ' + this._dirty, x, y + 56);
}
private createCanvas() {
public render(dx, dy): bool {
this.canvas = <HTMLCanvasElement> document.createElement('canvas');
this.canvas.width = this._game.stage.width;
this.canvas.height = this._game.stage.height;
this.context = this.canvas.getContext('2d');
/*
if (this._dirty == false)
{
this._game.stage.context.drawImage(this.canvas, 0, 0);
return true;
}
*/
// Work out how many tiles we can fit into our camera and round it up for the edges
this._maxX = this._game.math.ceil(this.camera.width / this._tilemap.tileWidth) + 1;
this._maxY = this._game.math.ceil(this.camera.height / this._tilemap.tileHeight) + 1;
// And now work out where in the tilemap the camera actually is
this._startX = this._game.math.floor(this.camera.worldView.x / this._tilemap.tileWidth);
this._startY = this._game.math.floor(this.camera.worldView.y / this._tilemap.tileHeight);
// Tilemap bounds check
if (this._startX < 0)
{
this._startX = 0;
}
if (this._startY < 0)
{
this._startY = 0;
}
public update() {
if (this._startX + this._maxX > this._tilemap.widthInTiles)
{
this._startX = this._tilemap.widthInTiles - this._maxX;
}
if (this._startY + this._maxY > this._tilemap.heightInTiles)
{
this._startY = this._tilemap.heightInTiles - this._maxY;
}
// Finally get the offset to avoid the blocky movement
this._dx = dx;
this._dy = dy;
this._dx += -(this.camera.worldView.x - (this._startX * this._tilemap.tileWidth));
this._dy += -(this.camera.worldView.y - (this._startY * this._tilemap.tileHeight));
this._tx = this._dx;
this._ty = this._dy;
for (var row = this._startY; row < this._startY + this._maxY; row++)
{
this._columnData = this._tilemap.mapData[row];
for (var tile = this._startX; tile < this._startX + this._maxX; tile++)
/*
if (this.camera.worldView.x !== this._oldCameraX || this.camera.worldView.y !== this._oldCameraY)
{
if (this._tileOffsets[this._columnData[tile]])
{
//this.context.drawImage(
this._game.stage.context.drawImage(
this._texture, // Source Image
this._tileOffsets[this._columnData[tile]].x, // Source X (location within the source image)
this._tileOffsets[this._columnData[tile]].y, // Source Y
this._tilemap.tileWidth, // Source Width
this._tilemap.tileHeight, // Source Height
this._tx, // Destination X (where on the canvas it'll be drawn)
this._ty, // Destination Y
this._tilemap.tileWidth, // Destination Width (always same as Source Width unless scaled)
this._tilemap.tileHeight // Destination Height (always same as Source Height unless scaled)
);
this._dirty = true;
}
this._oldCameraX = this.camera.worldView.x;
this._oldCameraY = this.camera.worldView.y;
*/
this._tx += this._tilemap.tileWidth;
}
}
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
this._game.stage.context.fillStyle = color;
this._game.stage.context.fillText('TilemapBuffer', x, y);
this._game.stage.context.fillText('startX: ' + this._startX + ' endX: ' + this._maxX, x, y + 14);
this._game.stage.context.fillText('startY: ' + this._startY + ' endY: ' + this._maxY, x, y + 28);
this._game.stage.context.fillText('dx: ' + this._dx + ' dy: ' + this._dy, x, y + 42);
this._game.stage.context.fillText('Dirty: ' + this._dirty, x, y + 56);
}
public render(dx, dy): bool {
/*
if (this._dirty == false)
{
this._game.stage.context.drawImage(this.canvas, 0, 0);
return true;
}
*/
// Work out how many tiles we can fit into our camera and round it up for the edges
this._maxX = this._game.math.ceil(this.camera.width / this._tilemap.tileWidth) + 1;
this._maxY = this._game.math.ceil(this.camera.height / this._tilemap.tileHeight) + 1;
// And now work out where in the tilemap the camera actually is
this._startX = this._game.math.floor(this.camera.worldView.x / this._tilemap.tileWidth);
this._startY = this._game.math.floor(this.camera.worldView.y / this._tilemap.tileHeight);
// Tilemap bounds check
if (this._startX < 0)
{
this._startX = 0;
}
if (this._startY < 0)
{
this._startY = 0;
}
if (this._startX + this._maxX > this._tilemap.widthInTiles)
{
this._startX = this._tilemap.widthInTiles - this._maxX;
}
if (this._startY + this._maxY > this._tilemap.heightInTiles)
{
this._startY = this._tilemap.heightInTiles - this._maxY;
}
// Finally get the offset to avoid the blocky movement
this._dx = dx;
this._dy = dy;
this._dx += -(this.camera.worldView.x - (this._startX * this._tilemap.tileWidth));
this._dy += -(this.camera.worldView.y - (this._startY * this._tilemap.tileHeight));
this._tx = this._dx;
this._ty += this._tilemap.tileHeight;
this._ty = this._dy;
for (var row = this._startY; row < this._startY + this._maxY; row++)
{
this._columnData = this._tilemap.mapData[row];
for (var tile = this._startX; tile < this._startX + this._maxX; tile++)
{
if (this._tileOffsets[this._columnData[tile]])
{
//this.context.drawImage(
this._game.stage.context.drawImage(
this._texture, // Source Image
this._tileOffsets[this._columnData[tile]].x, // Source X (location within the source image)
this._tileOffsets[this._columnData[tile]].y, // Source Y
this._tilemap.tileWidth, // Source Width
this._tilemap.tileHeight, // Source Height
this._tx, // Destination X (where on the canvas it'll be drawn)
this._ty, // Destination Y
this._tilemap.tileWidth, // Destination Width (always same as Source Width unless scaled)
this._tilemap.tileHeight // Destination Height (always same as Source Height unless scaled)
);
this._tx += this._tilemap.tileWidth;
}
}
this._tx = this._dx;
this._ty += this._tilemap.tileHeight;
}
//this._game.stage.context.drawImage(this.canvas, 0, 0);
//console.log('dirty cleaned');
//this._dirty = false;
return true;
}
//this._game.stage.context.drawImage(this.canvas, 0, 0);
//console.log('dirty cleaned');
//this._dirty = false;
return true;
}
}
}

240
Phaser/system/Tween.ts Normal file
View file

@ -0,0 +1,240 @@
/// <reference path="../Game.ts" />
/// <reference path="easing/Back.ts" />
/// <reference path="easing/Bounce.ts" />
/// <reference path="easing/Circular.ts" />
/// <reference path="easing/Cubic.ts" />
/// <reference path="easing/Elastic.ts" />
/// <reference path="easing/Exponential.ts" />
/// <reference path="easing/Linear.ts" />
/// <reference path="easing/Quadratic.ts" />
/// <reference path="easing/Quartic.ts" />
/// <reference path="easing/Quintic.ts" />
/// <reference path="easing/Sinusoidal.ts" />
/**
* Phaser - Tween
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js) converted to TypeScript and integrated into Phaser
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser {
export class Tween {
constructor(object, game:Phaser.Game) {
this._object = object;
this._game = game;
this._manager = this._game.tweens;
this._interpolationFunction = this._game.math.linearInterpolation;
this._easingFunction = Phaser.Easing.Linear.None;
this.onStart = new Phaser.Signal();
this.onUpdate = new Phaser.Signal();
this.onComplete = new Phaser.Signal();
}
private _game: Phaser.Game;
private _manager: Phaser.TweenManager;
private _object = null;
private _pausedTime: number = 0;
private _valuesStart = {};
private _valuesEnd = {};
private _duration = 1000;
private _delayTime = 0;
private _startTime = null;
private _easingFunction;
private _interpolationFunction;
private _chainedTweens = [];
public onStart: Phaser.Signal;
public onUpdate: Phaser.Signal;
public onComplete: Phaser.Signal;
public to(properties, duration?: number = 1000, ease?: any = null, autoStart?: bool = false) {
this._duration = duration;
// If properties isn't an object this will fail, sanity check it here somehow?
this._valuesEnd = properties;
if (ease !== null)
{
this._easingFunction = ease;
}
if (autoStart === true)
{
return this.start();
}
else
{
return this;
}
}
public start() {
if (this._game === null || this._object === null)
{
return;
}
this._manager.add(this);
this.onStart.dispatch(this._object);
this._startTime = this._game.time.now + this._delayTime;
for (var property in this._valuesEnd)
{
// This prevents the interpolation of null values or of non-existing properties
if (this._object[property] === null || !(property in this._object))
{
throw Error('Phaser.Tween interpolation of null value of non-existing property');
continue;
}
// check if an Array was provided as property value
if (this._valuesEnd[property] instanceof Array)
{
if (this._valuesEnd[property].length === 0)
{
continue;
}
// create a local copy of the Array with the start value at the front
this._valuesEnd[property] = [this._object[property]].concat(this._valuesEnd[property]);
}
this._valuesStart[property] = this._object[property];
}
return this;
}
public stop() {
if (this._manager !== null)
{
this._manager.remove(this);
}
return this;
}
public set parent(value:Phaser.Game) {
this._game = value;
this._manager = this._game.tweens;
}
public set delay(amount:number) {
this._delayTime = amount;
}
public get delay(): number {
return this._delayTime;
}
public set easing(easing) {
this._easingFunction = easing;
}
public get easing():any {
return this._easingFunction;
}
public set interpolation(interpolation) {
this._interpolationFunction = interpolation;
}
public get interpolation():any {
return this._interpolationFunction;
}
public chain(tween:Phaser.Tween) {
this._chainedTweens.push(tween);
return this;
}
public debugValue;
public update(time) {
if (this._game.paused == true)
{
if (this._pausedTime == 0)
{
this._pausedTime = time;
}
}
else
{
// Ok we aren't paused, but was there some time gained?
if (this._pausedTime > 0)
{
this._startTime += (time - this._pausedTime);
this._pausedTime = 0;
}
}
if (time < this._startTime)
{
return true;
}
var elapsed = (time - this._startTime) / this._duration;
elapsed = elapsed > 1 ? 1 : elapsed;
var value = this._easingFunction(elapsed);
for (var property in this._valuesStart)
{
// Add checks for object, array, numeric up front
if (this._valuesEnd[property] instanceof Array)
{
this._object[property] = this._interpolationFunction(this._valuesEnd[property], value);
}
else
{
this._object[property] = this._valuesStart[property] + (this._valuesEnd[property] - this._valuesStart[property]) * value;
}
}
this.onUpdate.dispatch(this._object, value);
if (elapsed == 1)
{
this.onComplete.dispatch(this._object);
for (var i = 0; i < this._chainedTweens.length; i++)
{
this._chainedTweens[i].start();
}
return false;
}
return true;
}
}
}

View file

@ -1,8 +1,4 @@
/// <reference path="../../Game.ts" />
/// <reference path="../../Sprite.ts" />
/// <reference path="AnimationLoader.ts" />
/// <reference path="Frame.ts" />
/// <reference path="FrameData.ts" />
/**
* Animation
@ -13,142 +9,150 @@
* @author Richard Davey
*/
class Animation {
/**
* Phaser
*/
constructor(game: Game, parent: Sprite, frameData: FrameData, name, frames, delay, looped) {
module Phaser {
this._game = game;
this._parent = parent;
this._frames = frames;
this._frameData = frameData;
export class Animation {
this.name = name;
this.delay = 1000 / delay;
this.looped = looped;
constructor(game: Game, parent: Sprite, frameData: FrameData, name: string, frames, delay: number, looped: bool) {
this.isFinished = false;
this.isPlaying = false;
this._game = game;
this._parent = parent;
this._frames = frames;
this._frameData = frameData;
}
this.name = name;
this.delay = 1000 / delay;
this.looped = looped;
private _game: Game;
private _parent: Sprite;
private _frames: number[];
private _frameData: FrameData;
private _frameIndex: number;
this.isFinished = false;
this.isPlaying = false;
private _timeLastFrame: number;
private _timeNextFrame: number;
public name: string;
public currentFrame: Frame;
public isFinished: bool;
public isPlaying: bool;
public looped: bool;
public delay: number;
public get frameTotal(): number {
return this._frames.length;
}
public get frame(): number {
return this._frameIndex;
}
public set frame(value: number) {
this.currentFrame = this._frameData.getFrame(value);
if (this.currentFrame !== null)
{
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._frameIndex = value;
}
}
private _game: Game;
private _parent: Sprite;
private _frames: number[];
private _frameData: FrameData;
private _frameIndex: number;
public play(frameRate?: number = null, loop?: bool) {
private _timeLastFrame: number;
private _timeNextFrame: number;
if (frameRate !== null)
{
this.delay = 1000 / frameRate;
public name: string;
public currentFrame: Frame;
public isFinished: bool;
public isPlaying: bool;
public looped: bool;
public delay: number;
public get frameTotal(): number {
return this._frames.length;
}
if (loop !== undefined)
{
this.looped = loop;
public get frame(): number {
return this._frameIndex;
}
this.isPlaying = true;
this.isFinished = false;
public set frame(value: number) {
this._timeLastFrame = this._game.time.now;
this._timeNextFrame = this._game.time.now + this.delay;
this.currentFrame = this._frameData.getFrame(value);
this._frameIndex = 0;
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
}
private onComplete() {
this.isPlaying = false;
this.isFinished = true;
// callback
}
public stop() {
this.isPlaying = false;
this.isFinished = true;
}
public update():bool {
if (this.isPlaying == true && this._game.time.now >= this._timeNextFrame)
{
this._frameIndex++;
if (this._frameIndex == this._frames.length)
if (this.currentFrame !== null)
{
if (this.looped)
{
this._frameIndex = 0;
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
}
else
{
this.onComplete();
}
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._frameIndex = value;
}
else
}
public play(frameRate?: number = null, loop?: bool) {
if (frameRate !== null)
{
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
this.delay = 1000 / frameRate;
}
if (loop !== undefined)
{
this.looped = loop;
}
this.isPlaying = true;
this.isFinished = false;
this._timeLastFrame = this._game.time.now;
this._timeNextFrame = this._game.time.now + this.delay;
return true;
this._frameIndex = 0;
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
}
return false;
private onComplete() {
this.isPlaying = false;
this.isFinished = true;
// callback
}
public stop() {
this.isPlaying = false;
this.isFinished = true;
}
public update(): bool {
if (this.isPlaying == true && this._game.time.now >= this._timeNextFrame)
{
this._frameIndex++;
if (this._frameIndex == this._frames.length)
{
if (this.looped)
{
this._frameIndex = 0;
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
}
else
{
this.onComplete();
}
}
else
{
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
}
this._timeLastFrame = this._game.time.now;
this._timeNextFrame = this._game.time.now + this.delay;
return true;
}
return false;
}
public destroy() {
this._game = null;
this._parent = null;
this._frames = null;
this._frameData = null;
this.currentFrame = null;
this.isPlaying = false;
}
}
public destroy() {
this._game = null;
this._parent = null;
this._frames = null;
this._frameData = null;
this.currentFrame = null;
this.isPlaying = false;
}
}
}

View file

@ -1,83 +1,86 @@
/// <reference path="../../Game.ts" />
/// <reference path="../../Sprite.ts" />
/// <reference path="Animation.ts" />
/// <reference path="Frame.ts" />
/// <reference path="FrameData.ts" />
class AnimationLoader {
/**
* Phaser
*/
public static parseSpriteSheet(game: Game, key: string, frameWidth: number, frameHeight: number, frameMax:number): FrameData {
module Phaser {
// How big is our image?
export class AnimationLoader {
var img = game.cache.getImage(key);
public static parseSpriteSheet(game: Game, key: string, frameWidth: number, frameHeight: number, frameMax: number): FrameData {
if (img == null)
{
return null;
}
// How big is our image?
var width = img.width;
var height = img.height;
var img = game.cache.getImage(key);
var row = Math.round(width / frameWidth);
var column = Math.round(height / frameHeight);
var total = row * column;
if (frameMax !== -1)
{
total = frameMax;
}
// Zero or smaller than frame sizes?
if (width == 0 || height == 0 || width < frameWidth || height < frameHeight || total === 0)
{
return null;
}
// Let's create some frames then
var data: FrameData = new FrameData();
var x = 0;
var y = 0;
for (var i = 0; i < total; i++)
{
data.addFrame(new Frame(x, y, frameWidth, frameHeight, ''));
x += frameWidth;
if (x === width)
if (img == null)
{
x = 0;
y += frameHeight;
return null;
}
var width = img.width;
var height = img.height;
var row = Math.round(width / frameWidth);
var column = Math.round(height / frameHeight);
var total = row * column;
if (frameMax !== -1)
{
total = frameMax;
}
// Zero or smaller than frame sizes?
if (width == 0 || height == 0 || width < frameWidth || height < frameHeight || total === 0)
{
return null;
}
// Let's create some frames then
var data: FrameData = new FrameData();
var x = 0;
var y = 0;
for (var i = 0; i < total; i++)
{
data.addFrame(new Frame(x, y, frameWidth, frameHeight, ''));
x += frameWidth;
if (x === width)
{
x = 0;
y += frameHeight;
}
}
return data;
}
return data;
public static parseJSONData(game: Game, json): FrameData {
// Let's create some frames then
var data: FrameData = new FrameData();
// By this stage frames is a fully parsed array
var frames = json;
var newFrame: Frame;
for (var i = 0; i < frames.length; i++)
{
newFrame = data.addFrame(new Frame(frames[i].frame.x, frames[i].frame.y, frames[i].frame.w, frames[i].frame.h, frames[i].filename));
newFrame.setTrim(frames[i].trimmed, frames[i].sourceSize.w, frames[i].sourceSize.h, frames[i].spriteSourceSize.x, frames[i].spriteSourceSize.y, frames[i].spriteSourceSize.w, frames[i].spriteSourceSize.h);
}
return data;
}
}
public static parseJSONData(game: Game, json): FrameData {
// Let's create some frames then
var data: FrameData = new FrameData();
// By this stage frames is a fully parsed array
var frames = json;
var newFrame:Frame;
for (var i = 0; i < frames.length; i++)
{
newFrame = data.addFrame(new Frame(frames[i].frame.x, frames[i].frame.y, frames[i].frame.w, frames[i].frame.h, frames[i].filename));
newFrame.setTrim(frames[i].trimmed, frames[i].sourceSize.w, frames[i].sourceSize.h, frames[i].spriteSourceSize.x, frames[i].spriteSourceSize.y, frames[i].spriteSourceSize.w, frames[i].spriteSourceSize.h);
}
return data;
}
}
}

View file

@ -1,68 +1,72 @@
/// <reference path="../../Game.ts" />
/// <reference path="../../Sprite.ts" />
/// <reference path="Animation.ts" />
/// <reference path="AnimationLoader.ts" />
/// <reference path="FrameData.ts" />
class Frame {
/**
* Phaser
*/
constructor(x: number, y: number, width: number, height: number, name: string) {
module Phaser {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.name = name;
export class Frame {
this.rotated = false;
this.trimmed = false;
constructor(x: number, y: number, width: number, height: number, name: string) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.name = name;
this.rotated = false;
this.trimmed = false;
}
// Position within the image to cut from
public x: number;
public y: number;
public width: number;
public height: number;
// Useful for Sprite Sheets
public index: number;
// Useful for Texture Atlas files (is set to the filename value)
public name: string = '';
// Rotated? (not yet implemented)
public rotated: bool = false;
// Either cw or ccw, rotation is always 90 degrees
public rotationDirection: string = 'cw';
// Was it trimmed when packed?
public trimmed: bool;
// The coordinates of the trimmed sprite inside the original sprite
public sourceSizeW: number;
public sourceSizeH: number;
public spriteSourceSizeX: number;
public spriteSourceSizeY: number;
public spriteSourceSizeW: number;
public spriteSourceSizeH: number;
public setRotation(rotated: bool, rotationDirection: string) {
// Not yet supported
}
public setTrim(trimmed: bool, actualWidth, actualHeight, destX, destY, destWidth, destHeight, ) {
this.trimmed = trimmed;
this.sourceSizeW = actualWidth;
this.sourceSizeH = actualHeight;
this.spriteSourceSizeX = destX;
this.spriteSourceSizeY = destY;
this.spriteSourceSizeW = destWidth;
this.spriteSourceSizeH = destHeight;
}
}
// Position within the image to cut from
public x: number;
public y: number;
public width: number;
public height: number;
// Useful for Sprite Sheets
public index: number;
// Useful for Texture Atlas files (is set to the filename value)
public name: string = '';
// Rotated? (not yet implemented)
public rotated: bool = false;
// Either cw or ccw, rotation is always 90 degrees
public rotationDirection: string = 'cw';
// Was it trimmed when packed?
public trimmed: bool;
// The coordinates of the trimmed sprite inside the original sprite
public sourceSizeW: number;
public sourceSizeH: number;
public spriteSourceSizeX: number;
public spriteSourceSizeY: number;
public spriteSourceSizeW: number;
public spriteSourceSizeH: number;
public setRotation(rotated: bool, rotationDirection: string) {
// Not yet supported
}
public setTrim(trimmed: bool, actualWidth, actualHeight, destX, destY, destWidth, destHeight, ) {
this.trimmed = trimmed;
this.sourceSizeW = actualWidth;
this.sourceSizeH = actualHeight;
this.spriteSourceSizeX = destX;
this.spriteSourceSizeY = destY;
this.spriteSourceSizeW = destWidth;
this.spriteSourceSizeH = destHeight;
}
}
}

View file

@ -1,100 +1,131 @@
/// <reference path="../../Game.ts" />
/// <reference path="../../Sprite.ts" />
/// <reference path="Animation.ts" />
/// <reference path="AnimationLoader.ts" />
/// <reference path="Frame.ts" />
class FrameData {
/**
* Phaser
*/
constructor() {
module Phaser {
this._frames = [];
this._frameNames = [];
export class FrameData {
}
constructor() {
private _frames: Frame[];
private _frameNames;
this._frames = [];
this._frameNames = [];
public get total(): number {
return this._frames.length;
}
public addFrame(frame: Frame):Frame {
frame.index = this._frames.length;
this._frames.push(frame);
if (frame.name !== '')
{
this._frameNames[frame.name] = frame.index;
}
return frame;
private _frames: Frame[];
private _frameNames;
}
public getFrame(index: number):Frame {
if (this._frames[index])
{
return this._frames[index];
public get total(): number {
return this._frames.length;
}
return null;
public addFrame(frame: Frame): Frame {
}
frame.index = this._frames.length;
public getFrameByName(name: string):Frame {
this._frames.push(frame);
if (frame.name !== '')
{
this._frameNames[frame.name] = frame.index;
}
return frame;
if (this._frameNames[name] >= 0)
{
return this._frames[this._frameNames[name]];
}
return null;
public getFrame(index: number): Frame {
}
if (this._frames[index])
{
return this._frames[index];
}
public getFrameRange(start: number, end: number, output?:Frame[] = []):Frame[] {
return null;
for (var i = start; i <= end; i++)
{
output.push(this._frames[i]);
}
return output;
public getFrameByName(name: string): Frame {
}
if (this._frameNames[name] >= 0)
{
return this._frames[this._frameNames[name]];
}
public getFrameIndexes(output?:number[] = []):number[] {
return null;
output.length = 0;
for (var i = 0; i < this._frames.length; i++)
{
output.push(i);
}
return output;
public checkFrameName(name: string): bool {
}
if (this._frameNames[name] >= 0)
{
return true;
}
public getAllFrames():Frame[] {
return this._frames;
}
return false;
public getFrames(range: number[]) {
var output: Frame[] = [];
for (var i = 0; i < range.length; i++)
{
output.push(this._frames[i]);
}
return output;
public getFrameRange(start: number, end: number, output?: Frame[] = []): Frame[] {
for (var i = start; i <= end; i++)
{
output.push(this._frames[i]);
}
return output;
}
public getFrameIndexes(output?: number[] = []): number[] {
output.length = 0;
for (var i = 0; i < this._frames.length; i++)
{
output.push(i);
}
return output;
}
public getFrameIndexesByName(input: string[]): number[] {
var output: number[] = [];
for (var i = 0; i < input.length; i++)
{
if (this.getFrameByName(input[i]))
{
output.push(this.getFrameByName(input[i]).index);
}
}
return output;
}
public getAllFrames(): Frame[] {
return this._frames;
}
public getFrames(range: number[]) {
var output: Frame[] = [];
for (var i = 0; i < range.length; i++)
{
output.push(this._frames[i]);
}
return output;
}
}

View file

@ -0,0 +1,41 @@
/// <reference path="../../Game.ts" />
/**
* Phaser - Easing
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js)
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser.Easing {
export class Back {
public static In(k) {
var s = 1.70158;
return k * k * ((s + 1) * k - s);
}
public static Out(k) {
var s = 1.70158;
return --k * k * ((s + 1) * k + s) + 1;
}
public static InOut(k) {
var s = 1.70158 * 1.525;
if ((k *= 2) < 1) return 0.5 * (k * k * ((s + 1) * k - s));
return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);
}
}
}

View file

@ -0,0 +1,53 @@
/// <reference path="../../Game.ts" />
/**
* Phaser - Easing
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js)
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser.Easing {
export class Bounce {
public static In(k) {
return 1 - Phaser.Easing.Bounce.Out(1 - k);
}
public static Out(k) {
if (k < (1 / 2.75))
{
return 7.5625 * k * k;
}
else if (k < (2 / 2.75))
{
return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;
}
else if (k < (2.5 / 2.75))
{
return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;
}
else
{
return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;
}
}
public static InOut(k) {
if (k < 0.5) return Phaser.Easing.Bounce.In(k * 2) * 0.5;
return Phaser.Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5;
}
}
}

View file

@ -0,0 +1,38 @@
/// <reference path="../../Game.ts" />
/**
* Phaser - Easing
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js)
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser.Easing {
export class Circular {
public static In(k) {
return 1 - Math.sqrt(1 - k * k);
}
public static Out(k) {
return Math.sqrt(1 - (--k * k));
}
public static InOut(k) {
if ((k *= 2) < 1) return -0.5 * (Math.sqrt(1 - k * k) - 1);
return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1);
}
}
}

View file

@ -0,0 +1,38 @@
/// <reference path="../../Game.ts" />
/**
* Phaser - Easing
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js)
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser.Easing {
export class Cubic {
public static In(k) {
return k * k * k;
}
public static Out(k) {
return --k * k * k + 1;
}
public static InOut(k) {
if ((k *= 2) < 1) return 0.5 * k * k * k;
return 0.5 * ((k -= 2) * k * k + 2);
}
}
}

View file

@ -0,0 +1,53 @@
/// <reference path="../../Game.ts" />
/**
* Phaser - Easing
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js)
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser.Easing {
export class Elastic {
public static In(k) {
var s, a = 0.1, p = 0.4;
if (k === 0) return 0;
if (k === 1) return 1;
if (!a || a < 1) { a = 1; s = p / 4; }
else s = p * Math.asin(1 / a) / (2 * Math.PI);
return -(a * Math.pow(2, 10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p));
}
public static Out(k) {
var s, a = 0.1, p = 0.4;
if (k === 0) return 0;
if (k === 1) return 1;
if (!a || a < 1) { a = 1; s = p / 4; }
else s = p * Math.asin(1 / a) / (2 * Math.PI);
return (a * Math.pow(2, -10 * k) * Math.sin((k - s) * (2 * Math.PI) / p) + 1);
}
public static InOut(k) {
var s, a = 0.1, p = 0.4;
if (k === 0) return 0;
if (k === 1) return 1;
if (!a || a < 1) { a = 1; s = p / 4; }
else s = p * Math.asin(1 / a) / (2 * Math.PI);
if ((k *= 2) < 1) return -0.5 * (a * Math.pow(2, 10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p));
return a * Math.pow(2, -10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1;
}
}
}

View file

@ -0,0 +1,40 @@
/// <reference path="../../Game.ts" />
/**
* Phaser - Easing
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js)
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser.Easing {
export class Exponential {
public static In(k) {
return k === 0 ? 0 : Math.pow(1024, k - 1);
}
public static Out(k) {
return k === 1 ? 1 : 1 - Math.pow(2, -10 * k);
}
public static InOut(k) {
if (k === 0) return 0;
if (k === 1) return 1;
if ((k *= 2) < 1) return 0.5 * Math.pow(1024, k - 1);
return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2);
}
}
}

View file

@ -0,0 +1,25 @@
/// <reference path="../../Game.ts" />
/**
* Phaser - Easing
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js)
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser.Easing {
export class Linear {
public static None(k) {
return k;
}
}
}

View file

@ -0,0 +1,38 @@
/// <reference path="../../Game.ts" />
/**
* Phaser - Easing
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js)
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser.Easing {
export class Quadratic {
public static In(k) {
return k * k;
}
public static Out(k) {
return k * (2 - k);
}
public static InOut(k) {
if ((k *= 2) < 1) return 0.5 * k * k;
return -0.5 * (--k * (k - 2) - 1);
}
}
}

View file

@ -0,0 +1,38 @@
/// <reference path="../../Game.ts" />
/**
* Phaser - Easing
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js)
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser.Easing {
export class Quartic {
public static In(k) {
return k * k * k * k;
}
public static Out(k) {
return 1 - (--k * k * k * k);
}
public static InOut(k) {
if ((k *= 2) < 1) return 0.5 * k * k * k * k;
return -0.5 * ((k -= 2) * k * k * k - 2);
}
}
}

View file

@ -0,0 +1,38 @@
/// <reference path="../../Game.ts" />
/**
* Phaser - Easing
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js)
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser.Easing {
export class Quintic {
public static In(k) {
return k * k * k * k * k;
}
public static Out(k) {
return --k * k * k * k * k + 1;
}
public static InOut(k) {
if ((k *= 2) < 1) return 0.5 * k * k * k * k * k;
return 0.5 * ((k -= 2) * k * k * k * k + 2);
}
}
}

View file

@ -0,0 +1,37 @@
/// <reference path="../../Game.ts" />
/**
* Phaser - Easing
*
* @desc Based heavily on tween.js by sole (https://github.com/sole/tween.js)
*
* @version 1.0 - 11th January 2013
*
* @author Richard Davey, TypeScript conversion and Phaser integration. See Phaser.TweenManager for the full tween.js author list
*/
module Phaser.Easing {
export class Sinusoidal {
public static In(k) {
return 1 - Math.cos(k * Math.PI / 2);
}
public static Out(k) {
return Math.sin(k * Math.PI / 2);
}
public static InOut(k) {
return 0.5 * (1 - Math.cos(Math.PI * k));
}
}
}

View file

@ -1,6 +1,4 @@
/// <reference path="../../Game.ts" />
/// <reference path="../../geom/Point.ts" />
/// <reference path="../../geom/Circle.ts" />
/**
* Input - Finger
@ -13,311 +11,318 @@
* @todo Lots
*/
class Finger {
/**
* Phaser
*/
/**
* Constructor
* @param {Kiwi.Game} game.
* @return {Kiwi.Input.Finger} This object.
*/
constructor(game: Game) {
module Phaser {
this._game = game;
this.active = false;
export class Finger {
}
/**
* Constructor
* @param {Phaser.Game} game.
* @return {Phaser.Finger} This object.
*/
constructor(game: Game) {
/**
*
* @property _game
* @type Kiwi.Game
* @private
**/
private _game: Game;
this._game = game;
this.active = false;
/**
* An identification number for each touch point. When a touch point becomes active, it must be assigned an identifier that is distinct from any other active touch point. While the touch point remains active, all events that refer to it must assign it the same identifier.
* @property identifier
* @type Number
*/
public identifier: number;
/**
*
* @property active
* @type Boolean
*/
public active: bool;
/**
*
* @property point
* @type Point
**/
public point: Point = null;
/**
*
* @property circle
* @type Circle
**/
public circle: Circle = null;
/**
*
* @property withinGame
* @type Boolean
*/
public withinGame: bool = false;
/**
* The horizontal coordinate of point relative to the viewport in pixels, excluding any scroll offset
* @property clientX
* @type Number
*/
public clientX: number = -1;
//
/**
* The vertical coordinate of point relative to the viewport in pixels, excluding any scroll offset
* @property clientY
* @type Number
*/
public clientY: number = -1;
//
/**
* The horizontal coordinate of point relative to the viewport in pixels, including any scroll offset
* @property pageX
* @type Number
*/
public pageX: number = -1;
/**
* The vertical coordinate of point relative to the viewport in pixels, including any scroll offset
* @property pageY
* @type Number
*/
public pageY: number = -1;
/**
* The horizontal coordinate of point relative to the screen in pixels
* @property screenX
* @type Number
*/
public screenX: number = -1;
/**
* The vertical coordinate of point relative to the screen in pixels
* @property screenY
* @type Number
*/
public screenY: number = -1;
/**
* The horizontal coordinate of point relative to the game element
* @property x
* @type Number
*/
public x: number = -1;
/**
* The vertical coordinate of point relative to the game element
* @property y
* @type Number
*/
public y: number = -1;
/**
* The Element on which the touch point started when it was first placed on the surface, even if the touch point has since moved outside the interactive area of that element.
* @property target
* @type Any
*/
public target;
/**
*
* @property isDown
* @type Boolean
**/
public isDown: bool = false;
/**
*
* @property isUp
* @type Boolean
**/
public isUp: bool = false;
/**
*
* @property timeDown
* @type Number
**/
public timeDown: number = 0;
/**
*
* @property duration
* @type Number
**/
public duration: number = 0;
/**
*
* @property timeUp
* @type Number
**/
public timeUp: number = 0;
/**
*
* @property justPressedRate
* @type Number
**/
public justPressedRate: number = 200;
/**
*
* @property justReleasedRate
* @type Number
**/
public justReleasedRate: number = 200;
/**
*
* @method start
* @param {Any} event
*/
public start(event) {
this.identifier = event.identifier;
this.target = event.target;
// populate geom objects
if (this.point === null)
{
this.point = new Point();
}
if (this.circle === null)
{
this.circle = new Circle(0, 0, 44);
/**
*
* @property _game
* @type Phaser.Game
* @private
**/
private _game: Game;
/**
* An identification number for each touch point. When a touch point becomes active, it must be assigned an identifier that is distinct from any other active touch point. While the touch point remains active, all events that refer to it must assign it the same identifier.
* @property identifier
* @type Number
*/
public identifier: number;
/**
*
* @property active
* @type Boolean
*/
public active: bool;
/**
*
* @property point
* @type Point
**/
public point: Point = null;
/**
*
* @property circle
* @type Circle
**/
public circle: Circle = null;
/**
*
* @property withinGame
* @type Boolean
*/
public withinGame: bool = false;
/**
* The horizontal coordinate of point relative to the viewport in pixels, excluding any scroll offset
* @property clientX
* @type Number
*/
public clientX: number = -1;
//
/**
* The vertical coordinate of point relative to the viewport in pixels, excluding any scroll offset
* @property clientY
* @type Number
*/
public clientY: number = -1;
//
/**
* The horizontal coordinate of point relative to the viewport in pixels, including any scroll offset
* @property pageX
* @type Number
*/
public pageX: number = -1;
/**
* The vertical coordinate of point relative to the viewport in pixels, including any scroll offset
* @property pageY
* @type Number
*/
public pageY: number = -1;
/**
* The horizontal coordinate of point relative to the screen in pixels
* @property screenX
* @type Number
*/
public screenX: number = -1;
/**
* The vertical coordinate of point relative to the screen in pixels
* @property screenY
* @type Number
*/
public screenY: number = -1;
/**
* The horizontal coordinate of point relative to the game element
* @property x
* @type Number
*/
public x: number = -1;
/**
* The vertical coordinate of point relative to the game element
* @property y
* @type Number
*/
public y: number = -1;
/**
* The Element on which the touch point started when it was first placed on the surface, even if the touch point has since moved outside the interactive area of that element.
* @property target
* @type Any
*/
public target;
/**
*
* @property isDown
* @type Boolean
**/
public isDown: bool = false;
/**
*
* @property isUp
* @type Boolean
**/
public isUp: bool = false;
/**
*
* @property timeDown
* @type Number
**/
public timeDown: number = 0;
/**
*
* @property duration
* @type Number
**/
public duration: number = 0;
/**
*
* @property timeUp
* @type Number
**/
public timeUp: number = 0;
/**
*
* @property justPressedRate
* @type Number
**/
public justPressedRate: number = 200;
/**
*
* @property justReleasedRate
* @type Number
**/
public justReleasedRate: number = 200;
/**
*
* @method start
* @param {Any} event
*/
public start(event) {
this.identifier = event.identifier;
this.target = event.target;
// populate geom objects
if (this.point === null)
{
this.point = new Point();
}
if (this.circle === null)
{
this.circle = new Circle(0, 0, 44);
}
this.move(event);
this.active = true;
this.withinGame = true;
this.isDown = true;
this.isUp = false;
this.timeDown = this._game.time.now;
}
this.move(event);
/**
*
* @method move
* @param {Any} event
*/
public move(event) {
this.active = true;
this.withinGame = true;
this.isDown = true;
this.isUp = false;
this.timeDown = this._game.time.now;
this.clientX = event.clientX;
this.clientY = event.clientY;
this.pageX = event.pageX;
this.pageY = event.pageY;
this.screenX = event.screenX;
this.screenY = event.screenY;
}
this.x = this.pageX - this._game.stage.offset.x;
this.y = this.pageY - this._game.stage.offset.y;
/**
*
* @method move
* @param {Any} event
*/
public move(event) {
this.point.setTo(this.x, this.y);
this.circle.setTo(this.x, this.y, 44);
this.clientX = event.clientX;
this.clientY = event.clientY;
this.pageX = event.pageX;
this.pageY = event.pageY;
this.screenX = event.screenX;
this.screenY = event.screenY;
// Droppings history (used for gestures and motion tracking)
this.x = this.pageX - this._game.stage.offset.x;
this.y = this.pageY - this._game.stage.offset.y;
this.duration = this._game.time.now - this.timeDown;
this.point.setTo(this.x, this.y);
this.circle.setTo(this.x, this.y, 44);
// Droppings history (used for gestures and motion tracking)
this.duration = this._game.time.now - this.timeDown;
}
/**
*
* @method leave
* @param {Any} event
*/
public leave(event) {
this.withinGame = false;
this.move(event);
}
/**
*
* @method stop
* @param {Any} event
*/
public stop(event) {
this.active = false;
this.withinGame = false;
this.isDown = false;
this.isUp = true;
this.timeUp = this._game.time.now;
this.duration = this.timeUp - this.timeDown;
}
/**
*
* @method justPressed
* @param {Number} [duration].
* @return {Boolean}
*/
public justPressed(duration?: number = this.justPressedRate): bool {
if (this.isDown === true && (this.timeDown + duration) > this._game.time.now)
{
return true;
}
else
{
return false;
/**
*
* @method leave
* @param {Any} event
*/
public leave(event) {
this.withinGame = false;
this.move(event);
}
/**
*
* @method stop
* @param {Any} event
*/
public stop(event) {
this.active = false;
this.withinGame = false;
this.isDown = false;
this.isUp = true;
this.timeUp = this._game.time.now;
this.duration = this.timeUp - this.timeDown;
}
/**
*
* @method justPressed
* @param {Number} [duration].
* @return {Boolean}
*/
public justPressed(duration?: number = this.justPressedRate): bool {
if (this.isDown === true && (this.timeDown + duration) > this._game.time.now)
{
return true;
}
else
{
return false;
}
}
/**
*
* @method justReleased
* @param {Number} [duration].
* @return {Boolean}
*/
public justReleased(duration?: number = this.justReleasedRate): bool {
if (this.isUp === true && (this.timeUp + duration) > this._game.time.now)
{
return true;
}
else
{
return false;
}
}
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the instance.
**/
public toString(): string {
return "[{Finger (identifer=" + this.identifier + " active=" + this.active + " duration=" + this.duration + " withinGame=" + this.withinGame + " x=" + this.x + " y=" + this.y + " clientX=" + this.clientX + " clientY=" + this.clientY + " screenX=" + this.screenX + " screenY=" + this.screenY + " pageX=" + this.pageX + " pageY=" + this.pageY + ")}]";
}
}
/**
*
* @method justReleased
* @param {Number} [duration].
* @return {Boolean}
*/
public justReleased(duration?: number = this.justReleasedRate): bool {
if (this.isUp === true && (this.timeUp + duration) > this._game.time.now)
{
return true;
}
else
{
return false;
}
}
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the instance.
**/
public toString(): string {
return "[{Finger (identifer=" + this.identifier + " active=" + this.active + " duration=" + this.duration + " withinGame=" + this.withinGame + " x=" + this.x + " y=" + this.y + " clientX=" + this.clientX + " clientY=" + this.clientY + " screenX=" + this.screenX + " screenY=" + this.screenY + " pageX=" + this.pageX + " pageY=" + this.pageY + ")}]";
}
}
}

View file

@ -1,76 +1,81 @@
/// <reference path="../../Game.ts" />
/// <reference path="Mouse.ts" />
/// <reference path="Keyboard.ts" />
/// <reference path="Touch.ts" />
class Input {
/**
* Phaser
*/
constructor(game: Game) {
module Phaser {
this._game = game;
export class Input {
this.mouse = new Mouse(this._game);
this.keyboard = new Keyboard(this._game);
this.touch = new Touch(this._game);
constructor(game: Game) {
this._game = game;
this.mouse = new Mouse(this._game);
this.keyboard = new Keyboard(this._game);
this.touch = new Touch(this._game);
}
private _game: Game;
public mouse: Mouse;
public keyboard: Keyboard;
public touch: Touch;
public x: number = 0;
public y: number = 0;
public scaleX: number = 1;
public scaleY: number = 1;
public worldX: number = 0;
public worldY: number = 0;
public update() {
this.x = Math.round(this.x);
this.y = Math.round(this.y);
this.worldX = this._game.camera.worldView.x + this.x;
this.worldY = this._game.camera.worldView.y + this.y;
this.mouse.update();
this.touch.update();
}
public reset() {
this.mouse.reset();
this.keyboard.reset();
this.touch.reset();
}
public getWorldX(camera?: Camera = this._game.camera) {
return camera.worldView.x + this.x;
}
public getWorldY(camera?: Camera = this._game.camera) {
return camera.worldView.y + this.y;
}
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
this._game.stage.context.fillStyle = color;
this._game.stage.context.fillText('Input', x, y);
this._game.stage.context.fillText('Screen X: ' + this.x + ' Screen Y: ' + this.y, x, y + 14);
this._game.stage.context.fillText('World X: ' + this.worldX + ' World Y: ' + this.worldY, x, y + 28);
this._game.stage.context.fillText('Scale X: ' + this.scaleX.toFixed(1) + ' Scale Y: ' + this.scaleY.toFixed(1), x, y + 42);
}
}
private _game: Game;
public mouse: Mouse;
public keyboard: Keyboard;
public touch: Touch;
public x: number = 0;
public y: number = 0;
public scaleX: number = 1;
public scaleY: number = 1;
public worldX: number = 0;
public worldY: number = 0;
public update() {
this.x = Math.round(this.x);
this.y = Math.round(this.y);
this.worldX = this._game.camera.worldView.x + this.x;
this.worldY = this._game.camera.worldView.y + this.y;
this.mouse.update();
this.touch.update();
}
public reset() {
this.mouse.reset();
this.keyboard.reset();
this.touch.reset();
}
public getWorldX(camera?: Camera = this._game.camera) {
return camera.worldView.x + this.x;
}
public getWorldY(camera?: Camera = this._game.camera) {
return camera.worldView.y + this.y;
}
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
this._game.stage.context.fillStyle = color;
this._game.stage.context.fillText('Input', x, y);
this._game.stage.context.fillText('Screen X: ' + this.x + ' Screen Y: ' + this.y, x, y + 14);
this._game.stage.context.fillText('World X: ' + this.worldX + ' World Y: ' + this.worldY, x, y + 28);
this._game.stage.context.fillText('Scale X: ' + this.scaleX.toFixed(1) + ' Scale Y: ' + this.scaleY.toFixed(1), x, y + 42);
}
}
}

View file

@ -1,214 +1,241 @@
/// <reference path="../../Game.ts" />
/// <reference path="Input.ts" />
class Keyboard {
/**
* Phaser
*/
constructor(game: Game) {
module Phaser {
this._game = game;
this.start();
export class Keyboard {
constructor(game: Game) {
this._game = game;
this.start();
}
private _game: Game;
private _keys = {};
private _capture = {};
public start() {
document.body.addEventListener('keydown', (event: KeyboardEvent) => this.onKeyDown(event), false);
document.body.addEventListener('keyup', (event: KeyboardEvent) => this.onKeyUp(event), false);
}
public addKeyCapture(keycode: number) {
this._capture[keycode] = true;
}
public removeKeyCapture(keycode: number) {
delete this._capture[keycode];
}
public clearCaptures() {
this._capture = {};
}
public onKeyDown(event: KeyboardEvent) {
if (this._capture[event.keyCode])
{
event.preventDefault();
}
if (!this._keys[event.keyCode])
{
this._keys[event.keyCode] = { isDown: true, timeDown: this._game.time.now, timeUp: 0 };
}
else
{
this._keys[event.keyCode].isDown = true;
this._keys[event.keyCode].timeDown = this._game.time.now;
}
}
public onKeyUp(event: KeyboardEvent) {
if (this._capture[event.keyCode])
{
event.preventDefault();
}
if (!this._keys[event.keyCode])
{
this._keys[event.keyCode] = { isDown: false, timeDown: 0, timeUp: this._game.time.now };
}
else
{
this._keys[event.keyCode].isDown = false;
this._keys[event.keyCode].timeUp = this._game.time.now;
}
}
public reset() {
for (var key in this._keys)
{
this._keys[key].isDown = false;
}
}
public justPressed(keycode: number, duration?: number = 250): bool {
if (this._keys[keycode] && this._keys[keycode].isDown === true && (this._game.time.now - this._keys[keycode].timeDown < duration))
{
return true;
}
else
{
return false;
}
}
public justReleased(keycode: number, duration?: number = 250): bool {
if (this._keys[keycode] && this._keys[keycode].isDown === false && (this._game.time.now - this._keys[keycode].timeUp < duration))
{
return true;
}
else
{
return false;
}
}
public isDown(keycode: number): bool {
if (this._keys[keycode])
{
return this._keys[keycode].isDown;
}
else
{
return false;
}
}
// Letters
public static A: number = "A".charCodeAt(0);
public static B: number = "B".charCodeAt(0);
public static C: number = "C".charCodeAt(0);
public static D: number = "D".charCodeAt(0);
public static E: number = "E".charCodeAt(0);
public static F: number = "F".charCodeAt(0);
public static G: number = "G".charCodeAt(0);
public static H: number = "H".charCodeAt(0);
public static I: number = "I".charCodeAt(0);
public static J: number = "J".charCodeAt(0);
public static K: number = "K".charCodeAt(0);
public static L: number = "L".charCodeAt(0);
public static M: number = "M".charCodeAt(0);
public static N: number = "N".charCodeAt(0);
public static O: number = "O".charCodeAt(0);
public static P: number = "P".charCodeAt(0);
public static Q: number = "Q".charCodeAt(0);
public static R: number = "R".charCodeAt(0);
public static S: number = "S".charCodeAt(0);
public static T: number = "T".charCodeAt(0);
public static U: number = "U".charCodeAt(0);
public static V: number = "V".charCodeAt(0);
public static W: number = "W".charCodeAt(0);
public static X: number = "X".charCodeAt(0);
public static Y: number = "Y".charCodeAt(0);
public static Z: number = "Z".charCodeAt(0);
// Numbers
public static ZERO: number = "0".charCodeAt(0);
public static ONE: number = "1".charCodeAt(0);
public static TWO: number = "2".charCodeAt(0);
public static THREE: number = "3".charCodeAt(0);
public static FOUR: number = "4".charCodeAt(0);
public static FIVE: number = "5".charCodeAt(0);
public static SIX: number = "6".charCodeAt(0);
public static SEVEN: number = "7".charCodeAt(0);
public static EIGHT: number = "8".charCodeAt(0);
public static NINE: number = "9".charCodeAt(0);
// Numpad
public static NUMPAD_0: number = 96;
public static NUMPAD_1: number = 97;
public static NUMPAD_2: number = 98;
public static NUMPAD_3: number = 99;
public static NUMPAD_4: number = 100;
public static NUMPAD_5: number = 101;
public static NUMPAD_6: number = 102;
public static NUMPAD_7: number = 103;
public static NUMPAD_8: number = 104;
public static NUMPAD_9: number = 105;
public static NUMPAD_MULTIPLY: number = 106;
public static NUMPAD_ADD: number = 107;
public static NUMPAD_ENTER: number = 108;
public static NUMPAD_SUBTRACT: number = 109;
public static NUMPAD_DECIMAL: number = 110;
public static NUMPAD_DIVIDE: number = 111;
// Function Keys
public static F1: number = 112;
public static F2: number = 113;
public static F3: number = 114;
public static F4: number = 115;
public static F5: number = 116;
public static F6: number = 117;
public static F7: number = 118;
public static F8: number = 119;
public static F9: number = 120;
public static F10: number = 121;
public static F11: number = 122;
public static F12: number = 123;
public static F13: number = 124;
public static F14: number = 125;
public static F15: number = 126;
// Symbol Keys
public static COLON: number = 186;
public static EQUALS: number = 187;
public static UNDERSCORE: number = 189;
public static QUESTION_MARK: number = 191;
public static TILDE: number = 192;
public static OPEN_BRACKET: number = 219;
public static BACKWARD_SLASH: number = 220;
public static CLOSED_BRACKET: number = 221;
public static QUOTES: number = 222;
// Other Keys
public static BACKSPACE: number = 8;
public static TAB: number = 9;
public static CLEAR: number = 12;
public static ENTER: number = 13;
public static SHIFT: number = 16;
public static CONTROL: number = 17;
public static ALT: number = 18;
public static CAPS_LOCK: number = 20;
public static ESC: number = 27;
public static SPACEBAR: number = 32;
public static PAGE_UP: number = 33;
public static PAGE_DOWN: number = 34;
public static END: number = 35;
public static HOME: number = 36;
public static LEFT: number = 37;
public static UP: number = 38;
public static RIGHT: number = 39;
public static DOWN: number = 40;
public static INSERT: number = 45;
public static DELETE: number = 46;
public static HELP: number = 47;
public static NUM_LOCK: number = 144;
}
private _game: Game;
private _keys = {};
public start() {
document.body.addEventListener('keydown', (event: KeyboardEvent) => this.onKeyDown(event), false);
document.body.addEventListener('keyup', (event: KeyboardEvent) => this.onKeyUp(event), false);
}
public onKeyDown(event: KeyboardEvent) {
//event.preventDefault();
if (!this._keys[event.keyCode])
{
this._keys[event.keyCode] = { isDown: true, timeDown: this._game.time.now, timeUp: 0 };
}
else
{
this._keys[event.keyCode].isDown = true;
this._keys[event.keyCode].timeDown = this._game.time.now;
}
}
public onKeyUp(event: KeyboardEvent) {
//event.preventDefault();
if (!this._keys[event.keyCode])
{
this._keys[event.keyCode] = { isDown: false, timeDown: 0, timeUp: this._game.time.now };
}
else
{
this._keys[event.keyCode].isDown = false;
this._keys[event.keyCode].timeUp = this._game.time.now;
}
}
public reset() {
for (var key in this._keys)
{
this._keys[key].isDown = false;
}
}
public justPressed(keycode: number, duration?: number = 250): bool {
if (this._keys[keycode] && this._keys[keycode].isDown === true && (this._game.time.now - this._keys[keycode].timeDown < duration))
{
return true;
}
else
{
return false;
}
}
public justReleased(keycode: number, duration?: number = 250): bool {
if (this._keys[keycode] && this._keys[keycode].isDown === false && (this._game.time.now - this._keys[keycode].timeUp < duration))
{
return true;
}
else
{
return false;
}
}
public isDown(keycode: number): bool {
if (this._keys[keycode])
{
return this._keys[keycode].isDown;
}
else
{
return false;
}
}
// Letters
public static A: number = "A".charCodeAt(0);
public static B: number = "B".charCodeAt(0);
public static C: number = "C".charCodeAt(0);
public static D: number = "D".charCodeAt(0);
public static E: number = "E".charCodeAt(0);
public static F: number = "F".charCodeAt(0);
public static G: number = "G".charCodeAt(0);
public static H: number = "H".charCodeAt(0);
public static I: number = "I".charCodeAt(0);
public static J: number = "J".charCodeAt(0);
public static K: number = "K".charCodeAt(0);
public static L: number = "L".charCodeAt(0);
public static M: number = "M".charCodeAt(0);
public static N: number = "N".charCodeAt(0);
public static O: number = "O".charCodeAt(0);
public static P: number = "P".charCodeAt(0);
public static Q: number = "Q".charCodeAt(0);
public static R: number = "R".charCodeAt(0);
public static S: number = "S".charCodeAt(0);
public static T: number = "T".charCodeAt(0);
public static U: number = "U".charCodeAt(0);
public static V: number = "V".charCodeAt(0);
public static W: number = "W".charCodeAt(0);
public static X: number = "X".charCodeAt(0);
public static Y: number = "Y".charCodeAt(0);
public static Z: number = "Z".charCodeAt(0);
// Numbers
public static ZERO: number = "0".charCodeAt(0);
public static ONE: number = "1".charCodeAt(0);
public static TWO: number = "2".charCodeAt(0);
public static THREE: number = "3".charCodeAt(0);
public static FOUR: number = "4".charCodeAt(0);
public static FIVE: number = "5".charCodeAt(0);
public static SIX: number = "6".charCodeAt(0);
public static SEVEN: number = "7".charCodeAt(0);
public static EIGHT: number = "8".charCodeAt(0);
public static NINE: number = "9".charCodeAt(0);
// Numpad
public static NUMPAD_0: number = 96;
public static NUMPAD_1: number = 97;
public static NUMPAD_2: number = 98;
public static NUMPAD_3: number = 99;
public static NUMPAD_4: number = 100;
public static NUMPAD_5: number = 101;
public static NUMPAD_6: number = 102;
public static NUMPAD_7: number = 103;
public static NUMPAD_8: number = 104;
public static NUMPAD_9: number = 105;
public static NUMPAD_MULTIPLY: number = 106;
public static NUMPAD_ADD: number = 107;
public static NUMPAD_ENTER: number = 108;
public static NUMPAD_SUBTRACT: number = 109;
public static NUMPAD_DECIMAL: number = 110;
public static NUMPAD_DIVIDE: number = 111;
// Function Keys
public static F1: number = 112;
public static F2: number = 113;
public static F3: number = 114;
public static F4: number = 115;
public static F5: number = 116;
public static F6: number = 117;
public static F7: number = 118;
public static F8: number = 119;
public static F9: number = 120;
public static F10: number = 121;
public static F11: number = 122;
public static F12: number = 123;
public static F13: number = 124;
public static F14: number = 125;
public static F15: number = 126;
// Symbol Keys
public static COLON: number = 186;
public static EQUALS: number = 187;
public static UNDERSCORE: number = 189;
public static QUESTION_MARK: number = 191;
public static TILDE: number = 192;
public static OPEN_BRACKET: number = 219;
public static BACKWARD_SLASH: number = 220;
public static CLOSED_BRACKET: number = 221;
public static QUOTES: number = 222;
// Other Keys
public static BACKSPACE: number = 8;
public static TAB: number = 9;
public static CLEAR: number = 12;
public static ENTER: number = 13;
public static SHIFT: number = 16;
public static CONTROL: number = 17;
public static ALT: number = 18;
public static CAPS_LOCK: number = 20;
public static ESC: number = 27;
public static SPACEBAR: number = 32;
public static PAGE_UP: number = 33;
public static PAGE_DOWN: number = 34;
public static END: number = 35;
public static HOME: number = 36;
public static LEFT: number = 37;
public static UP: number = 38;
public static RIGHT: number = 39;
public static DOWN: number = 40;
public static INSERT: number = 45;
public static DELETE: number = 46;
public static HELP: number = 47;
public static NUM_LOCK: number = 144;
}
}

View file

@ -1,101 +1,108 @@
/// <reference path="../../Game.ts" />
/// <reference path="Input.ts" />
class Mouse {
/**
* Phaser
*/
constructor(game: Game) {
module Phaser {
this._game = game;
this.start();
export class Mouse {
}
constructor(game: Game) {
private _game: Game;
this._game = game;
this.start();
private _x: number = 0;
private _y: number = 0;
}
public button: number;
private _game: Game;
public static LEFT_BUTTON: number = 0;
public static MIDDLE_BUTTON: number = 1;
public static RIGHT_BUTTON: number = 2;
private _x: number = 0;
private _y: number = 0;
public isDown: bool = false;
public isUp: bool = true;
public timeDown: number = 0;
public duration: number = 0;
public timeUp: number = 0;
public button: number;
public start() {
public static LEFT_BUTTON: number = 0;
public static MIDDLE_BUTTON: number = 1;
public static RIGHT_BUTTON: number = 2;
this._game.stage.canvas.addEventListener('mousedown', (event: MouseEvent) => this.onMouseDown(event), true);
this._game.stage.canvas.addEventListener('mousemove', (event: MouseEvent) => this.onMouseMove(event), true);
this._game.stage.canvas.addEventListener('mouseup', (event: MouseEvent) => this.onMouseUp(event), true);
public isDown: bool = false;
public isUp: bool = true;
public timeDown: number = 0;
public duration: number = 0;
public timeUp: number = 0;
}
public reset() {
public start() {
this.isDown = false;
this.isUp = true;
this._game.stage.canvas.addEventListener('mousedown', (event: MouseEvent) => this.onMouseDown(event), true);
this._game.stage.canvas.addEventListener('mousemove', (event: MouseEvent) => this.onMouseMove(event), true);
this._game.stage.canvas.addEventListener('mouseup', (event: MouseEvent) => this.onMouseUp(event), true);
}
}
public onMouseDown(event: MouseEvent) {
public reset() {
this.button = event.button;
this.isDown = false;
this.isUp = true;
this._x = event.clientX - this._game.stage.x;
this._y = event.clientY - this._game.stage.y;
}
this._game.input.x = this._x * this._game.input.scaleX;
this._game.input.y = this._y * this._game.input.scaleY;
public onMouseDown(event: MouseEvent) {
this.isDown = true;
this.isUp = false;
this.timeDown = this._game.time.now;
this.button = event.button;
}
this._x = event.clientX - this._game.stage.x;
this._y = event.clientY - this._game.stage.y;
public update() {
this._game.input.x = this._x * this._game.input.scaleX;
this._game.input.y = this._y * this._game.input.scaleY;
//this._game.input.x = this._x * this._game.input.scaleX;
//this._game.input.y = this._y * this._game.input.scaleY;
this.isDown = true;
this.isUp = false;
this.timeDown = this._game.time.now;
}
public update() {
//this._game.input.x = this._x * this._game.input.scaleX;
//this._game.input.y = this._y * this._game.input.scaleY;
if (this.isDown)
{
this.duration = this._game.time.now - this.timeDown;
}
}
public onMouseMove(event: MouseEvent) {
this.button = event.button;
this._x = event.clientX - this._game.stage.x;
this._y = event.clientY - this._game.stage.y;
this._game.input.x = this._x * this._game.input.scaleX;
this._game.input.y = this._y * this._game.input.scaleY;
}
public onMouseUp(event: MouseEvent) {
this.button = event.button;
this.isDown = false;
this.isUp = true;
this.timeUp = this._game.time.now;
this.duration = this.timeUp - this.timeDown;
this._x = event.clientX - this._game.stage.x;
this._y = event.clientY - this._game.stage.y;
this._game.input.x = this._x * this._game.input.scaleX;
this._game.input.y = this._y * this._game.input.scaleY;
if (this.isDown)
{
this.duration = this._game.time.now - this.timeDown;
}
}
public onMouseMove(event: MouseEvent) {
this.button = event.button;
this._x = event.clientX - this._game.stage.x;
this._y = event.clientY - this._game.stage.y;
this._game.input.x = this._x * this._game.input.scaleX;
this._game.input.y = this._y * this._game.input.scaleY;
}
public onMouseUp(event: MouseEvent) {
this.button = event.button;
this.isDown = false;
this.isUp = true;
this.timeUp = this._game.time.now;
this.duration = this.timeUp - this.timeDown;
this._x = event.clientX - this._game.stage.x;
this._y = event.clientY - this._game.stage.y;
this._game.input.x = this._x * this._game.input.scaleX;
this._game.input.y = this._y * this._game.input.scaleY;
}
}
}

View file

@ -1,5 +1,4 @@
/// <reference path="../../Game.ts" />
/// <reference path="../../Signal.ts" />
/// <reference path="Finger.ts" />
/**
@ -20,430 +19,437 @@
* Input Zones (mouse and touch) - lock entities within them + axis aligned drags
*/
class Touch {
/**
* Phaser
*/
/**
* Constructor
* @param {Game} game.
* @return {Touch} This object.
*/
constructor(game: Game) {
module Phaser {
this._game = game;
export class Touch {
this.finger1 = new Finger(this._game);
this.finger2 = new Finger(this._game);
this.finger3 = new Finger(this._game);
this.finger4 = new Finger(this._game);
this.finger5 = new Finger(this._game);
this.finger6 = new Finger(this._game);
this.finger7 = new Finger(this._game);
this.finger8 = new Finger(this._game);
this.finger9 = new Finger(this._game);
this.finger10 = new Finger(this._game);
/**
* Constructor
* @param {Game} game.
* @return {Touch} This object.
*/
constructor(game: Game) {
this._fingers = [this.finger1, this.finger2, this.finger3, this.finger4, this.finger5, this.finger6, this.finger7, this.finger8, this.finger9, this.finger10];
this._game = game;
this.touchDown = new Signal();
this.touchUp = new Signal();
this.finger1 = new Finger(this._game);
this.finger2 = new Finger(this._game);
this.finger3 = new Finger(this._game);
this.finger4 = new Finger(this._game);
this.finger5 = new Finger(this._game);
this.finger6 = new Finger(this._game);
this.finger7 = new Finger(this._game);
this.finger8 = new Finger(this._game);
this.finger9 = new Finger(this._game);
this.finger10 = new Finger(this._game);
this.start();
this._fingers = [this.finger1, this.finger2, this.finger3, this.finger4, this.finger5, this.finger6, this.finger7, this.finger8, this.finger9, this.finger10];
}
this.touchDown = new Signal();
this.touchUp = new Signal();
/**
*
* @property _game
* @type Game
* @private
**/
private _game: Game;
this.start();
/**
*
* @property x
* @type Number
**/
public x: number = 0;
}
/**
*
* @property y
* @type Number
**/
public y: number = 0;
/**
*
* @property _game
* @type Game
* @private
**/
private _game: Game;
/**
*
* @property _fingers
* @type Array
* @private
**/
private _fingers: Finger[];
/**
*
* @property x
* @type Number
**/
public x: number = 0;
/**
*
* @property finger1
* @type Finger
**/
public finger1: Finger;
/**
*
* @property y
* @type Number
**/
public y: number = 0;
/**
*
* @property finger2
* @type Finger
**/
public finger2: Finger;
/**
*
* @property _fingers
* @type Array
* @private
**/
private _fingers: Finger[];
/**
*
* @property finger3
* @type Finger
**/
public finger3: Finger;
/**
*
* @property finger1
* @type Finger
**/
public finger1: Finger;
/**
*
* @property finger4
* @type Finger
**/
public finger4: Finger;
/**
*
* @property finger2
* @type Finger
**/
public finger2: Finger;
/**
*
* @property finger5
* @type Finger
**/
public finger5: Finger;
/**
*
* @property finger3
* @type Finger
**/
public finger3: Finger;
/**
*
* @property finger6
* @type Finger
**/
public finger6: Finger;
/**
*
* @property finger4
* @type Finger
**/
public finger4: Finger;
/**
*
* @property finger7
* @type Finger
**/
public finger7: Finger;
/**
*
* @property finger5
* @type Finger
**/
public finger5: Finger;
/**
*
* @property finger8
* @type Finger
**/
public finger8: Finger;
/**
*
* @property finger6
* @type Finger
**/
public finger6: Finger;
/**
*
* @property finger9
* @type Finger
**/
public finger9: Finger;
/**
*
* @property finger7
* @type Finger
**/
public finger7: Finger;
/**
*
* @property finger10
* @type Finger
**/
public finger10: Finger;
/**
*
* @property finger8
* @type Finger
**/
public finger8: Finger;
/**
*
* @property latestFinger
* @type Finger
**/
public latestFinger: Finger;
/**
*
* @property finger9
* @type Finger
**/
public finger9: Finger;
/**
*
* @property isDown
* @type Boolean
**/
public isDown: bool = false;
/**
*
* @property finger10
* @type Finger
**/
public finger10: Finger;
/**
*
* @property isUp
* @type Boolean
**/
public isUp: bool = true;
/**
*
* @property latestFinger
* @type Finger
**/
public latestFinger: Finger;
public touchDown: Signal;
public touchUp: Signal;
/**
*
* @property isDown
* @type Boolean
**/
public isDown: bool = false;
/**
*
* @method start
*/
public start() {
/**
*
* @property isUp
* @type Boolean
**/
public isUp: bool = true;
this._game.stage.canvas.addEventListener('touchstart', (event) => this.onTouchStart(event), false);
this._game.stage.canvas.addEventListener('touchmove', (event) => this.onTouchMove(event), false);
this._game.stage.canvas.addEventListener('touchend', (event) => this.onTouchEnd(event), false);
this._game.stage.canvas.addEventListener('touchenter', (event) => this.onTouchEnter(event), false);
this._game.stage.canvas.addEventListener('touchleave', (event) => this.onTouchLeave(event), false);
this._game.stage.canvas.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false);
public touchDown: Signal;
public touchUp: Signal;
document.addEventListener('touchmove', (event) => this.consumeTouchMove(event), false);
/**
*
* @method start
*/
public start() {
}
this._game.stage.canvas.addEventListener('touchstart', (event) => this.onTouchStart(event), false);
this._game.stage.canvas.addEventListener('touchmove', (event) => this.onTouchMove(event), false);
this._game.stage.canvas.addEventListener('touchend', (event) => this.onTouchEnd(event), false);
this._game.stage.canvas.addEventListener('touchenter', (event) => this.onTouchEnter(event), false);
this._game.stage.canvas.addEventListener('touchleave', (event) => this.onTouchLeave(event), false);
this._game.stage.canvas.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false);
/**
* Prevent iOS bounce-back (doesn't work?)
* @method consumeTouchMove
* @param {Any} event
**/
private consumeTouchMove(event) {
document.addEventListener('touchmove', (event) => this.consumeTouchMove(event), false);
event.preventDefault();
}
}
/**
* Prevent iOS bounce-back (doesn't work?)
* @method consumeTouchMove
* @param {Any} event
**/
private consumeTouchMove(event) {
/**
*
* @method onTouchStart
* @param {Any} event
**/
private onTouchStart(event) {
event.preventDefault();
event.preventDefault();
}
// A list of all the touch points that BECAME active with the current event
// https://developer.mozilla.org/en-US/docs/DOM/TouchList
/**
*
* @method onTouchStart
* @param {Any} event
**/
private onTouchStart(event) {
// event.targetTouches = list of all touches on the TARGET ELEMENT (i.e. game dom element)
// event.touches = list of all touches on the ENTIRE DOCUMENT, not just the target element
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
for (var f = 0; f < this._fingers.length; f++)
event.preventDefault();
// A list of all the touch points that BECAME active with the current event
// https://developer.mozilla.org/en-US/docs/DOM/TouchList
// event.targetTouches = list of all touches on the TARGET ELEMENT (i.e. game dom element)
// event.touches = list of all touches on the ENTIRE DOCUMENT, not just the target element
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
if (this._fingers[f].active === false)
for (var f = 0; f < this._fingers.length; f++)
{
this._fingers[f].start(event.changedTouches[i]);
this.x = this._fingers[f].x;
this.y = this._fingers[f].y;
this._game.input.x = this.x * this._game.input.scaleX;
this._game.input.y = this.y * this._game.input.scaleY;
this.touchDown.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration);
this.isDown = true;
this.isUp = false;
break;
if (this._fingers[f].active === false)
{
this._fingers[f].start(event.changedTouches[i]);
this.x = this._fingers[f].x;
this.y = this._fingers[f].y;
this._game.input.x = this.x * this._game.input.scaleX;
this._game.input.y = this.y * this._game.input.scaleY;
this.touchDown.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration);
this.isDown = true;
this.isUp = false;
break;
}
}
}
}
/**
* Doesn't appear to be supported by most browsers yet
* @method onTouchCancel
* @param {Any} event
**/
private onTouchCancel(event) {
event.preventDefault();
// Touch cancel - touches that were disrupted (perhaps by moving into a plugin or browser chrome)
// http://www.w3.org/TR/touch-events/#dfn-touchcancel
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].identifier === event.changedTouches[i].identifier)
{
this._fingers[f].stop(event.changedTouches[i]);
break;
}
}
}
}
/**
* Doesn't appear to be supported by most browsers yet
* @method onTouchEnter
* @param {Any} event
**/
private onTouchEnter(event) {
event.preventDefault();
// For touch enter and leave its a list of the touch points that have entered or left the target
// event.targetTouches = list of all touches on the TARGET ELEMENT (i.e. game dom element)
// event.touches = list of all touches on the ENTIRE DOCUMENT, not just the target element
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].active === false)
{
this._fingers[f].start(event.changedTouches[i]);
break;
}
}
}
}
/**
* Doesn't appear to be supported by most browsers yet
* @method onTouchLeave
* @param {Any} event
**/
private onTouchLeave(event) {
event.preventDefault();
// For touch enter and leave its a list of the touch points that have entered or left the target
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].identifier === event.changedTouches[i].identifier)
{
this._fingers[f].leave(event.changedTouches[i]);
break;
}
}
}
}
/**
*
* @method onTouchMove
* @param {Any} event
**/
private onTouchMove(event) {
event.preventDefault();
// event.targetTouches = list of all touches on the TARGET ELEMENT (i.e. game dom element)
// event.touches = list of all touches on the ENTIRE DOCUMENT, not just the target element
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].identifier === event.changedTouches[i].identifier)
{
this._fingers[f].move(event.changedTouches[i]);
this.x = this._fingers[f].x;
this.y = this._fingers[f].y;
this._game.input.x = this.x * this._game.input.scaleX;
this._game.input.y = this.y * this._game.input.scaleY;
break;
}
}
}
}
/**
*
* @method onTouchEnd
* @param {Any} event
**/
private onTouchEnd(event) {
event.preventDefault();
// For touch end its a list of the touch points that have been removed from the surface
// https://developer.mozilla.org/en-US/docs/DOM/TouchList
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].identifier === event.changedTouches[i].identifier)
{
this._fingers[f].stop(event.changedTouches[i]);
this.x = this._fingers[f].x;
this.y = this._fingers[f].y;
this._game.input.x = this.x * this._game.input.scaleX;
this._game.input.y = this.y * this._game.input.scaleY;
this.touchUp.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration);
this.isDown = false;
this.isUp = true;
break;
}
}
}
}
/**
*
* @method calculateDistance
* @param {Finger} finger1
* @param {Finger} finger2
**/
public calculateDistance(finger1: Finger, finger2: Finger) {
}
/**
*
* @method calculateAngle
* @param {Finger} finger1
* @param {Finger} finger2
**/
public calculateAngle(finger1: Finger, finger2: Finger) {
}
/**
*
* @method checkOverlap
* @param {Finger} finger1
* @param {Finger} finger2
**/
public checkOverlap(finger1: Finger, finger2: Finger) {
}
/**
*
* @method update
*/
public update() {
}
/**
*
* @method stop
*/
public stop() {
//this._domElement.addEventListener('touchstart', (event) => this.onTouchStart(event), false);
//this._domElement.addEventListener('touchmove', (event) => this.onTouchMove(event), false);
//this._domElement.addEventListener('touchend', (event) => this.onTouchEnd(event), false);
//this._domElement.addEventListener('touchenter', (event) => this.onTouchEnter(event), false);
//this._domElement.addEventListener('touchleave', (event) => this.onTouchLeave(event), false);
//this._domElement.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false);
}
/**
*
* @method reset
**/
public reset() {
this.isDown = false;
this.isUp = false;
}
}
/**
* Doesn't appear to be supported by most browsers yet
* @method onTouchCancel
* @param {Any} event
**/
private onTouchCancel(event) {
event.preventDefault();
// Touch cancel - touches that were disrupted (perhaps by moving into a plugin or browser chrome)
// http://www.w3.org/TR/touch-events/#dfn-touchcancel
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].identifier === event.changedTouches[i].identifier)
{
this._fingers[f].stop(event.changedTouches[i]);
break;
}
}
}
}
/**
* Doesn't appear to be supported by most browsers yet
* @method onTouchEnter
* @param {Any} event
**/
private onTouchEnter(event) {
event.preventDefault();
// For touch enter and leave its a list of the touch points that have entered or left the target
// event.targetTouches = list of all touches on the TARGET ELEMENT (i.e. game dom element)
// event.touches = list of all touches on the ENTIRE DOCUMENT, not just the target element
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].active === false)
{
this._fingers[f].start(event.changedTouches[i]);
break;
}
}
}
}
/**
* Doesn't appear to be supported by most browsers yet
* @method onTouchLeave
* @param {Any} event
**/
private onTouchLeave(event) {
event.preventDefault();
// For touch enter and leave its a list of the touch points that have entered or left the target
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].identifier === event.changedTouches[i].identifier)
{
this._fingers[f].leave(event.changedTouches[i]);
break;
}
}
}
}
/**
*
* @method onTouchMove
* @param {Any} event
**/
private onTouchMove(event) {
event.preventDefault();
// event.targetTouches = list of all touches on the TARGET ELEMENT (i.e. game dom element)
// event.touches = list of all touches on the ENTIRE DOCUMENT, not just the target element
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].identifier === event.changedTouches[i].identifier)
{
this._fingers[f].move(event.changedTouches[i]);
this.x = this._fingers[f].x;
this.y = this._fingers[f].y;
this._game.input.x = this.x * this._game.input.scaleX;
this._game.input.y = this.y * this._game.input.scaleY;
break;
}
}
}
}
/**
*
* @method onTouchEnd
* @param {Any} event
**/
private onTouchEnd(event) {
event.preventDefault();
// For touch end its a list of the touch points that have been removed from the surface
// https://developer.mozilla.org/en-US/docs/DOM/TouchList
// event.changedTouches = the touches that CHANGED in this event, not the total number of them
for (var i = 0; i < event.changedTouches.length; i++)
{
for (var f = 0; f < this._fingers.length; f++)
{
if (this._fingers[f].identifier === event.changedTouches[i].identifier)
{
this._fingers[f].stop(event.changedTouches[i]);
this.x = this._fingers[f].x;
this.y = this._fingers[f].y;
this._game.input.x = this.x * this._game.input.scaleX;
this._game.input.y = this.y * this._game.input.scaleY;
this.touchUp.dispatch(this._fingers[f].x, this._fingers[f].y, this._fingers[f].timeDown, this._fingers[f].timeUp, this._fingers[f].duration);
this.isDown = false;
this.isUp = true;
break;
}
}
}
}
/**
*
* @method calculateDistance
* @param {Finger} finger1
* @param {Finger} finger2
**/
public calculateDistance(finger1: Finger, finger2: Finger) {
}
/**
*
* @method calculateAngle
* @param {Finger} finger1
* @param {Finger} finger2
**/
public calculateAngle(finger1: Finger, finger2: Finger) {
}
/**
*
* @method checkOverlap
* @param {Finger} finger1
* @param {Finger} finger2
**/
public checkOverlap(finger1: Finger, finger2: Finger) {
}
/**
*
* @method update
*/
public update() {
}
/**
*
* @method stop
*/
public stop() {
//this._domElement.addEventListener('touchstart', (event) => this.onTouchStart(event), false);
//this._domElement.addEventListener('touchmove', (event) => this.onTouchMove(event), false);
//this._domElement.addEventListener('touchend', (event) => this.onTouchEnd(event), false);
//this._domElement.addEventListener('touchenter', (event) => this.onTouchEnter(event), false);
//this._domElement.addEventListener('touchleave', (event) => this.onTouchLeave(event), false);
//this._domElement.addEventListener('touchcancel', (event) => this.onTouchCancel(event), false);
}
/**
*
* @method reset
**/
public reset() {
this.isDown = false;
this.isUp = false;
}
}
}

View file

@ -1,9 +1,9 @@
Phaser
======
Version 0.8
Version 0.9
15th April 2013
18th April 2013
By Richard Davey, [Photon Storm](http://www.photonstorm.com)
@ -18,6 +18,17 @@ For support post to the Phaser board on the [HTML5 Game Devs forum](http://www.h
Change Log
----------
V0.9
Large refactoring. Everything now lives inside the Phaser module, so all code and all tests have been updated to reflect this. Makes coding a tiny bit
more verbose but stops the framework from globbing up the global namespace. Also should make code-insight work in WebStorm and similar editors.<br />
Added the new GeomSprite object. This is a sprite that uses a geometry class for display (Circle, Rectangle, Point, Line). It's extremely flexible!<br />
Added Geometry intersection results objects.<br />
Added new Collision class and moved some functions there. Contains all the Game Object and Geometry Intersection methods.<br />
Can now create a sprite animation based on frame names rather than indexes. Useful when you've an animation inside a texture atlas. Added test to show.<br />
Added addKeyCapture(), removeKeyCapture() and clearCaptures() to Input.Keyboard. Calls event.preventDefault() on any keycode set to capture, allowing you to avoid page scrolling when using the cursor keys in a game for example.<br />
Added new Motion class which contains lots of handy functions like 'moveTowardsObject', 'velocityFromAngle' and more.<br />
Tween Manager added. You can now create tweens via Game.createTween (or for more control game.tweens). All the usual suspects are here: Bounce, Elastic, Quintic, etc and it's hooked into the core game clock, so if your game pauses and resumes your tweens adjust accordingly.
V0.8
Added ability to set Sprite frame by name (sprite.frameName), useful when you've loaded a Texture Atlas with filename values set rather than using frame indexes.<br />

View file

@ -96,12 +96,48 @@
<TypeScriptCompile Include="sprites\dynamic texture 1.ts" />
</ItemGroup>
<ItemGroup>
<Content Include="tweens\bounce.js">
<DependentUpon>bounce.ts</DependentUpon>
</Content>
<Content Include="tweens\elastic.js">
<DependentUpon>elastic.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="tweens\elastic.ts" />
<TypeScriptCompile Include="tweens\bounce.ts" />
<TypeScriptCompile Include="sprites\animate by framename.ts" />
<TypeScriptCompile Include="geometry\rectangle.ts" />
<TypeScriptCompile Include="geometry\rect vs rect.ts" />
<TypeScriptCompile Include="geometry\circle.ts" />
<Content Include="geometry\circle.js">
<DependentUpon>circle.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geometry\point.ts" />
<TypeScriptCompile Include="geometry\line.ts" />
<Content Include="geometry\line.js">
<DependentUpon>line.ts</DependentUpon>
</Content>
<Content Include="geometry\point.js">
<DependentUpon>point.ts</DependentUpon>
</Content>
<Content Include="geometry\rect vs rect.js">
<DependentUpon>rect vs rect.ts</DependentUpon>
</Content>
<Content Include="geometry\rectangle.js">
<DependentUpon>rectangle.ts</DependentUpon>
</Content>
<Content Include="sprites\animate by framename.js">
<DependentUpon>animate by framename.ts</DependentUpon>
</Content>
<Content Include="sprites\dynamic texture 1.js">
<DependentUpon>dynamic texture 1.ts</DependentUpon>
</Content>
<Content Include="sprites\dynamic texture 2.js">
<DependentUpon>dynamic texture 2.ts</DependentUpon>
</Content>
<Content Include="sprites\rotation.js">
<DependentUpon>rotation.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="sprites\rotation.ts" />
<TypeScriptCompile Include="sprites\dynamic texture 2.ts" />
</ItemGroup>
<Import Project="$(VSToolsPath)\TypeScript\Microsoft.TypeScript.targets" />

View file

@ -1,7 +1,7 @@
{"frames": [
{
"filename": "running bot.swf/0000",
"filename": "run00",
"frame": {"x":34,"y":128,"w":56,"h":60},
"rotated": false,
"trimmed": true,
@ -9,7 +9,7 @@
"sourceSize": {"w":56,"h":64}
},
{
"filename": "running bot.swf/0001",
"filename": "run01",
"frame": {"x":54,"y":0,"w":56,"h":58},
"rotated": false,
"trimmed": true,
@ -17,7 +17,7 @@
"sourceSize": {"w":56,"h":64}
},
{
"filename": "running bot.swf/0002",
"filename": "run02",
"frame": {"x":54,"y":58,"w":56,"h":58},
"rotated": false,
"trimmed": true,
@ -25,7 +25,7 @@
"sourceSize": {"w":56,"h":64}
},
{
"filename": "running bot.swf/0003",
"filename": "run03",
"frame": {"x":0,"y":192,"w":34,"h":64},
"rotated": false,
"trimmed": true,
@ -33,7 +33,7 @@
"sourceSize": {"w":56,"h":64}
},
{
"filename": "running bot.swf/0004",
"filename": "run04",
"frame": {"x":0,"y":64,"w":54,"h":64},
"rotated": false,
"trimmed": true,
@ -41,7 +41,7 @@
"sourceSize": {"w":56,"h":64}
},
{
"filename": "running bot.swf/0005",
"filename": "run05",
"frame": {"x":196,"y":0,"w":56,"h":58},
"rotated": false,
"trimmed": true,
@ -49,7 +49,7 @@
"sourceSize": {"w":56,"h":64}
},
{
"filename": "running bot.swf/0006",
"filename": "run06",
"frame": {"x":0,"y":0,"w":54,"h":64},
"rotated": false,
"trimmed": true,
@ -57,7 +57,7 @@
"sourceSize": {"w":56,"h":64}
},
{
"filename": "running bot.swf/0007",
"filename": "run07",
"frame": {"x":140,"y":0,"w":56,"h":58},
"rotated": false,
"trimmed": true,
@ -65,7 +65,7 @@
"sourceSize": {"w":56,"h":64}
},
{
"filename": "running bot.swf/0008",
"filename": "run08",
"frame": {"x":34,"y":188,"w":50,"h":60},
"rotated": false,
"trimmed": true,
@ -73,7 +73,7 @@
"sourceSize": {"w":56,"h":64}
},
{
"filename": "running bot.swf/0009",
"filename": "run09",
"frame": {"x":0,"y":128,"w":34,"h":64},
"rotated": false,
"trimmed": true,
@ -81,7 +81,7 @@
"sourceSize": {"w":56,"h":64}
},
{
"filename": "running bot.swf/0010",
"filename": "run10",
"frame": {"x":84,"y":188,"w":56,"h":58},
"rotated": false,
"trimmed": true,

View file

@ -1,6 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(2240, 2240);
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
@ -12,10 +12,10 @@
function create() {
myGame.createSprite(0, 0, 'grid');
car = myGame.createSprite(400, 300, 'car');
myGame.camera.follow(car, Camera.STYLE_TOPDOWN);
myGame.camera.follow(car, Phaser.Camera.STYLE_TOPDOWN);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam = myGame.createCamera(0, 0, 300, 300);
miniCam.follow(car, Camera.STYLE_TOPDOWN_TIGHT);
miniCam.follow(car, Phaser.Camera.STYLE_TOPDOWN_TIGHT);
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam.showBorder = true;
miniCam.alpha = 0.7;
@ -25,13 +25,13 @@
car.velocity.y = 0;
car.angularVelocity = 0;
car.angularAcceleration = 0;
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
car.angularVelocity = -200;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
car.angularVelocity = 200;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
var motion = myGame.math.velocityFromAngle(car.angle, 300);
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}
}

View file

@ -1,8 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -15,8 +15,8 @@
}
var car: Sprite;
var miniCam: Camera;
var car: Phaser.Sprite;
var miniCam: Phaser.Camera;
function create() {
@ -24,11 +24,11 @@
car = myGame.createSprite(400, 300, 'car');
myGame.camera.follow(car, Camera.STYLE_TOPDOWN);
myGame.camera.follow(car, Phaser.Camera.STYLE_TOPDOWN);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam = myGame.createCamera(0, 0, 300, 300);
miniCam.follow(car, Camera.STYLE_TOPDOWN_TIGHT);
miniCam.follow(car, Phaser.Camera.STYLE_TOPDOWN_TIGHT);
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam.showBorder = true;
miniCam.alpha = 0.7;
@ -42,18 +42,18 @@
car.angularVelocity = 0;
car.angularAcceleration = 0;
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
car.angularVelocity = -200;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
car.angularVelocity = 200;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
var motion:Point = myGame.math.velocityFromAngle(car.angle, 300);
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(1920, 1200);
myGame.camera.setBounds(0, 0, 1920, 1200);
@ -17,14 +16,14 @@
}
function update() {
myGame.camera.renderDebugInfo(32, 32);
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
myGame.camera.scroll.x -= 4;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
myGame.camera.scroll.x += 4;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
myGame.camera.scroll.y -= 4;
} else if(myGame.input.keyboard.isDown(Keyboard.DOWN)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
myGame.camera.scroll.y += 4;
}
}

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -32,20 +31,20 @@
myGame.camera.renderDebugInfo(32, 32);
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
myGame.camera.scroll.x -= 4;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
myGame.camera.scroll.x += 4;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
myGame.camera.scroll.y -= 4;
}
else if (myGame.input.keyboard.isDown(Keyboard.DOWN))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
{
myGame.camera.scroll.y += 4;
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(3000, 3000);
myGame.loader.addImageFile('melon', 'assets/sprites/melon.png');
@ -23,17 +22,17 @@
function update() {
myGame.camera.renderDebugInfo(16, 16);
cam2.renderDebugInfo(200, 16);
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
myGame.camera.x -= 4;
cam2.x -= 2;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
myGame.camera.x += 4;
cam2.x += 2;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
myGame.camera.y -= 4;
cam2.y -= 2;
} else if(myGame.input.keyboard.isDown(Keyboard.DOWN)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
myGame.camera.y += 4;
cam2.y += 2;
}

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -15,7 +14,7 @@
}
var cam2: Camera;
var cam2: Phaser.Camera;
function create() {
@ -40,23 +39,23 @@
myGame.camera.renderDebugInfo(16, 16);
cam2.renderDebugInfo(200, 16);
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
myGame.camera.x -= 4;
cam2.x -= 2;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
myGame.camera.x += 4;
cam2.x += 2;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
myGame.camera.y -= 4;
cam2.y -= 2;
}
else if (myGame.input.keyboard.isDown(Keyboard.DOWN))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
{
myGame.camera.y += 4;
cam2.y += 2;

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(3000, 3000);
myGame.loader.addImageFile('car', 'assets/sprites/car.png');
@ -21,14 +20,14 @@
}
function update() {
myGame.camera.renderDebugInfo(600, 32);
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
myGame.camera.rotation -= 2;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
myGame.camera.rotation += 2;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
myGame.camera.scroll.y -= 4;
} else if(myGame.input.keyboard.isDown(Keyboard.DOWN)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
myGame.camera.scroll.y += 4;
}
}

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -39,20 +38,20 @@
myGame.camera.renderDebugInfo(600, 32);
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
myGame.camera.rotation -= 2;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
myGame.camera.rotation += 2;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
myGame.camera.scroll.y -= 4;
}
else if (myGame.input.keyboard.isDown(Keyboard.DOWN))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
{
myGame.camera.scroll.y += 4;
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(2240, 2240);
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
@ -15,15 +14,15 @@
myGame.createSprite(0, 0, 'grid');
car = myGame.createSprite(400, 300, 'car');
myGame.camera.follow(car);
myGame.camera.deadzone = new Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam = myGame.createCamera(600, 32, 200, 200);
miniCam.follow(car, Camera.STYLE_LOCKON);
miniCam.follow(car, Phaser.Camera.STYLE_LOCKON);
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam.showBorder = true;
miniCam.scale.setTo(0.5, 0.5);
bigCam = myGame.createCamera(32, 32, 200, 200);
bigCam.follow(car, Camera.STYLE_LOCKON);
bigCam.follow(car, Phaser.Camera.STYLE_LOCKON);
bigCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
bigCam.showBorder = true;
bigCam.scale.setTo(2, 2);
@ -33,13 +32,13 @@
car.velocity.y = 0;
car.angularVelocity = 0;
car.angularAcceleration = 0;
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
car.angularVelocity = -200;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
car.angularVelocity = 200;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
var motion = myGame.math.velocityFromAngle(car.angle, 300);
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}
}

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -16,9 +15,9 @@
}
var car: Sprite;
var miniCam: Camera;
var bigCam: Camera;
var car: Phaser.Sprite;
var miniCam: Phaser.Camera;
var bigCam: Phaser.Camera;
function create() {
@ -27,17 +26,17 @@
car = myGame.createSprite(400, 300, 'car');
myGame.camera.follow(car);
myGame.camera.deadzone = new Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam = myGame.createCamera(600, 32, 200, 200);
miniCam.follow(car, Camera.STYLE_LOCKON);
miniCam.follow(car, Phaser.Camera.STYLE_LOCKON);
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam.showBorder = true;
miniCam.scale.setTo(0.5, 0.5);
bigCam = myGame.createCamera(32, 32, 200, 200);
bigCam.follow(car, Camera.STYLE_LOCKON);
bigCam.follow(car, Phaser.Camera.STYLE_LOCKON);
bigCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
bigCam.showBorder = true;
bigCam.scale.setTo(2, 2);
@ -51,18 +50,18 @@
car.angularVelocity = 0;
car.angularAcceleration = 0;
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
car.angularVelocity = -200;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
car.angularVelocity = 200;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
var motion:Point = myGame.math.velocityFromAngle(car.angle, 300);
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(2240, 2240);
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
@ -15,16 +14,16 @@
myGame.createSprite(0, 0, 'grid');
car = myGame.createSprite(400, 300, 'car');
myGame.camera.follow(car);
myGame.camera.deadzone = new Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam = myGame.createCamera(600, 32, 200, 200);
miniCam.follow(car, Camera.STYLE_LOCKON);
miniCam.follow(car, Phaser.Camera.STYLE_LOCKON);
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam.showBorder = true;
miniCam.scale.setTo(0.5, 0.5);
miniCam.showShadow = true;
bigCam = myGame.createCamera(32, 32, 200, 200);
bigCam.follow(car, Camera.STYLE_LOCKON);
bigCam.follow(car, Phaser.Camera.STYLE_LOCKON);
bigCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
bigCam.showBorder = true;
bigCam.scale.setTo(2, 2);
@ -35,13 +34,13 @@
car.velocity.y = 0;
car.angularVelocity = 0;
car.angularAcceleration = 0;
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
car.angularVelocity = -200;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
car.angularVelocity = 200;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
var motion = myGame.math.velocityFromAngle(car.angle, 300);
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}
}

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -16,9 +15,9 @@
}
var car: Sprite;
var miniCam: Camera;
var bigCam: Camera;
var car: Phaser.Sprite;
var miniCam: Phaser.Camera;
var bigCam: Phaser.Camera;
function create() {
@ -27,18 +26,18 @@
car = myGame.createSprite(400, 300, 'car');
myGame.camera.follow(car);
myGame.camera.deadzone = new Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam = myGame.createCamera(600, 32, 200, 200);
miniCam.follow(car, Camera.STYLE_LOCKON);
miniCam.follow(car, Phaser.Camera.STYLE_LOCKON);
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
miniCam.showBorder = true;
miniCam.scale.setTo(0.5, 0.5);
miniCam.showShadow = true;
bigCam = myGame.createCamera(32, 32, 200, 200);
bigCam.follow(car, Camera.STYLE_LOCKON);
bigCam.follow(car, Phaser.Camera.STYLE_LOCKON);
bigCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
bigCam.showBorder = true;
bigCam.scale.setTo(2, 2);
@ -53,18 +52,18 @@
car.angularVelocity = 0;
car.angularAcceleration = 0;
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
car.angularVelocity = -200;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
car.angularVelocity = 200;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
var motion:Point = myGame.math.velocityFromAngle(car.angle, 300);
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(2240, 2240);
myGame.loader.addImageFile('balls', 'assets/sprites/balls.png');
@ -16,7 +15,7 @@
car = myGame.createSprite(400, 300, 'car');
myGame.camera.setTexture('balls');
myGame.camera.follow(car);
myGame.camera.deadzone = new Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
//miniCam = myGame.createCamera(600, 32, 200, 200);
//miniCam.follow(car, Camera.STYLE_LOCKON);
@ -34,13 +33,13 @@
car.velocity.y = 0;
car.angularVelocity = 0;
car.angularAcceleration = 0;
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
car.angularVelocity = -200;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
car.angularVelocity = 200;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
var motion = myGame.math.velocityFromAngle(car.angle, 300);
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}
}

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -16,9 +15,9 @@
}
var car: Sprite;
var miniCam: Camera;
var bigCam: Camera;
var car: Phaser.Sprite;
var miniCam: Phaser.Camera;
var bigCam: Phaser.Camera;
function create() {
@ -28,7 +27,7 @@
myGame.camera.setTexture('balls');
myGame.camera.follow(car);
myGame.camera.deadzone = new Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
//miniCam = myGame.createCamera(600, 32, 200, 200);
@ -52,18 +51,18 @@
car.angularVelocity = 0;
car.angularAcceleration = 0;
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
car.angularVelocity = -200;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
car.angularVelocity = 200;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
var motion:Point = myGame.math.velocityFromAngle(car.angle, 300);
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.loader.addImageFile('background', 'assets/pics/large-color-wheel.png');
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
@ -18,13 +17,13 @@
car.velocity.y = 0;
car.angularVelocity = 0;
car.angularAcceleration = 0;
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
car.angularVelocity = -200;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
car.angularVelocity = 200;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
var motion = myGame.math.velocityFromAngle(car.angle, 300);
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}
// Fade when the car hits the edges, a different colour per edge

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -14,7 +13,7 @@
}
var car: Sprite;
var car: Phaser.Sprite;
function create() {
@ -33,18 +32,18 @@
car.angularVelocity = 0;
car.angularAcceleration = 0;
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
car.angularVelocity = -200;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
car.angularVelocity = 200;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
var motion:Point = myGame.math.velocityFromAngle(car.angle, 300);
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.loader.addImageFile('background', 'assets/pics/large-color-wheel.png');
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
@ -18,13 +17,13 @@
car.velocity.y = 0;
car.angularVelocity = 0;
car.angularAcceleration = 0;
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
car.angularVelocity = -200;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
car.angularVelocity = 200;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
var motion = myGame.math.velocityFromAngle(car.angle, 300);
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}
// Flash when the car hits the edges, a different colour per edge

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -14,7 +13,7 @@
}
var car: Sprite;
var car: Phaser.Sprite;
function create() {
@ -33,18 +32,18 @@
car.angularVelocity = 0;
car.angularAcceleration = 0;
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
car.angularVelocity = -200;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
car.angularVelocity = 200;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
var motion:Point = myGame.math.velocityFromAngle(car.angle, 300);
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(1920, 1920);
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
@ -24,13 +23,13 @@
function update() {
myGame.camera.renderDebugInfo(32, 32);
melon.renderDebugInfo(200, 32);
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
myGame.camera.focusOnXY(640, 640);
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
myGame.camera.focusOnXY(1234, 800);
} else if(myGame.input.keyboard.isDown(Keyboard.UP)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
myGame.camera.focusOnXY(50, 200);
} else if(myGame.input.keyboard.isDown(Keyboard.DOWN)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
myGame.camera.focusOnXY(1700, 1700);
}
}

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -17,7 +16,7 @@
}
var melon: Sprite;
var melon: Phaser.Sprite;
function create() {
@ -41,19 +40,19 @@
myGame.camera.renderDebugInfo(32, 32);
melon.renderDebugInfo(200, 32);
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
myGame.camera.focusOnXY(640, 640);
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
myGame.camera.focusOnXY(1234, 800);
}
else if (myGame.input.keyboard.isDown(Keyboard.UP))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
myGame.camera.focusOnXY(50, 200);
}
else if (myGame.input.keyboard.isDown(Keyboard.DOWN))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
{
myGame.camera.focusOnXY(1700, 1700);
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(2240, 2240);
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
@ -14,7 +13,7 @@
car = myGame.createSprite(400, 300, 'car');
myGame.camera.follow(car);
// Here we'll set our own custom deadzone which is 64px smaller than the stage size on all sides
myGame.camera.deadzone = new Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
}
function update() {
@ -24,13 +23,13 @@
car.velocity.y = 0;
car.angularVelocity = 0;
car.angularAcceleration = 0;
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
car.angularVelocity = -200;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
car.angularVelocity = 200;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
var motion = myGame.math.velocityFromAngle(car.angle, 300);
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}
}

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -16,7 +15,7 @@
}
var car: Sprite;
var car: Phaser.Sprite;
function create() {
@ -26,7 +25,7 @@
myGame.camera.follow(car);
// Here we'll set our own custom deadzone which is 64px smaller than the stage size on all sides
myGame.camera.deadzone = new Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
}
@ -41,18 +40,18 @@
car.angularVelocity = 0;
car.angularAcceleration = 0;
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
car.angularVelocity = -200;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
car.angularVelocity = 200;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
var motion:Point = myGame.math.velocityFromAngle(car.angle, 300);
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(1920, 1920);
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
@ -21,13 +20,13 @@
car.velocity.y = 0;
car.angularVelocity = 0;
car.angularAcceleration = 0;
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
car.angularVelocity = -200;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
car.angularVelocity = 200;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
var motion = myGame.math.velocityFromAngle(car.angle, 300);
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}
}

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -38,18 +37,18 @@
car.angularVelocity = 0;
car.angularAcceleration = 0;
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
car.angularVelocity = -200;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
car.angularVelocity = 200;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
var motion:Point = myGame.math.velocityFromAngle(car.angle, 300);
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(2240, 2240);
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
@ -12,7 +11,7 @@
function create() {
myGame.createSprite(0, 0, 'grid');
car = myGame.createSprite(400, 300, 'car');
myGame.camera.follow(car, Camera.STYLE_TOPDOWN);
myGame.camera.follow(car, Phaser.Camera.STYLE_TOPDOWN);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
}
function update() {
@ -22,13 +21,13 @@
car.velocity.y = 0;
car.angularVelocity = 0;
car.angularAcceleration = 0;
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
car.angularVelocity = -200;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
car.angularVelocity = 200;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
var motion = myGame.math.velocityFromAngle(car.angle, 300);
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}
}

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -16,7 +15,7 @@
}
var car: Sprite;
var car: Phaser.Sprite;
function create() {
@ -24,7 +23,7 @@
car = myGame.createSprite(400, 300, 'car');
myGame.camera.follow(car, Camera.STYLE_TOPDOWN);
myGame.camera.follow(car, Phaser.Camera.STYLE_TOPDOWN);
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
}
@ -39,18 +38,18 @@
car.angularVelocity = 0;
car.angularAcceleration = 0;
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
car.angularVelocity = -200;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
car.angularVelocity = 200;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
var motion:Point = myGame.math.velocityFromAngle(car.angle, 300);
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
car.velocity.copyFrom(motion);
}

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(3000, 3000);
myGame.loader.addImageFile('car', 'assets/sprites/car.png');
@ -27,17 +26,17 @@
function update() {
myGame.camera.renderDebugInfo(16, 16);
cam2.renderDebugInfo(200, 16);
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
myGame.camera.scroll.x -= 4;
cam2.scroll.x -= 2;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
myGame.camera.scroll.x += 4;
cam2.scroll.x += 2;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
myGame.camera.scroll.y -= 4;
cam2.scroll.y -= 2;
} else if(myGame.input.keyboard.isDown(Keyboard.DOWN)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
myGame.camera.scroll.y += 4;
cam2.scroll.y += 2;
}

View file

@ -1,9 +1,8 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
@ -17,7 +16,7 @@
}
var cam2: Camera;
var cam2: Phaser.Camera;
function create() {
@ -44,23 +43,23 @@
myGame.camera.renderDebugInfo(16, 16);
cam2.renderDebugInfo(200, 16);
if (myGame.input.keyboard.isDown(Keyboard.LEFT))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
myGame.camera.scroll.x -= 4;
cam2.scroll.x -= 2;
}
else if (myGame.input.keyboard.isDown(Keyboard.RIGHT))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
myGame.camera.scroll.x += 4;
cam2.scroll.x += 2;
}
if (myGame.input.keyboard.isDown(Keyboard.UP))
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
{
myGame.camera.scroll.y -= 4;
cam2.scroll.y -= 2;
}
else if (myGame.input.keyboard.isDown(Keyboard.DOWN))
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
{
myGame.camera.scroll.y += 4;
cam2.scroll.y += 2;

View file

@ -1,7 +1,6 @@
/// <reference path="../../Phaser/Game.ts" />
/// <reference path="../../Phaser/Sprite.ts" />
/// <reference path="../../Phaser/Phaser.ts" />
(function () {
var myGame = new Game(this, 'game', 800, 600, init, create, update);
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
function init() {
myGame.world.setSize(1920, 1200);
myGame.loader.addImageFile('backdrop', 'assets/pics/remember-me.jpg');
@ -24,14 +23,14 @@
function update() {
myGame.camera.renderDebugInfo(32, 32);
melon.renderDebugInfo(200, 32);
if(myGame.input.keyboard.isDown(Keyboard.LEFT)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
myGame.camera.scroll.x -= 1;
} else if(myGame.input.keyboard.isDown(Keyboard.RIGHT)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
myGame.camera.scroll.x += 1;
}
if(myGame.input.keyboard.isDown(Keyboard.UP)) {
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
myGame.camera.scroll.y -= 1;
} else if(myGame.input.keyboard.isDown(Keyboard.DOWN)) {
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
myGame.camera.scroll.y += 1;
}
}

Some files were not shown because too many files have changed in this diff Show more