4 Commits
2374 changed files with 108733 additions and 667645 deletions
-14
View File
@@ -1,15 +1 @@
# System and IDE files
Thumbs.db
.DS_Store .DS_Store
.idea
Phaser OSX.sublime-project
Phaser OSX.sublime-workspace
Phaser.sublime-project
Phaser.sublime-workspace
*.suo
# Vendors
node_modules/
# Build
dist/
-75
View File
@@ -1,75 +0,0 @@
{
"globals" : { "Phaser": false, "PIXI": false },
// Ignore Environment Globals
"browser" : true, // Standard browser globals e.g. `window`, `document`.
"couch" : false,
"dojo" : false,
"jquery" : true,
"mootools" : false,
"node" : false,
"nonstandard" : false,
"phantom" : false,
"prototypejs" : false,
"rhino" : false,
"worker" : false,
"wsh" : true, // Windows Scripting Host.
"yui" : false,
// Development
"debug" : true, // Allow debugger statements e.g. browser breakpoints.
"devel" : true, // Allow developments statements e.g. `console.log();`.
// ECMAScript Support
"es3" : true, // Support legacy browser and javascript environments.
"esnext" : false, // This option tells JSHint that your code uses ECMAScript 6 specific syntax.
"strict" : false, // Require `use strict` pragma in every file.
"globalstrict" : false, // Allow global "use strict" (also enables 'strict').
// Functionality
"asi" : true, // Tolerate Automatic Semicolon Insertion (no semicolons).
"bitwise" : false, // Prohibit bitwise operators (&, |, ^, etc.).
"boss" : true, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
"camelcase" : true, // Force all variable names to use either camelCase style or UPPER_CASE with underscores.
"curly" : true, // Require {} for every new block or scope.
"eqeqeq" : false, // Require triple equals i.e. `===`.
"eqnull" : true, // Tolerate use of `== null`.
"evil" : false, // Tolerate use of `eval`.
"expr" : false, // Tolerate `ExpressionStatement` as Programs.
"forin" : false, // Tolerate `for in` loops without `hasOwnPrototype`.
"freeze" : true, // Prohibits overwriting prototypes of native objects such as Array and Date.
"funcscope" : true, // This option suppresses warnings about declaring variables inside of control structures while accessing them later from the outside.
"immed" : false, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
"iterator" : true, // This option suppresses warnings about the __iterator__ property.
"lastsemic" : true, // This option suppresses warnings about missing semicolons, but only when the semicolon is omitted for the last statement in a one-line block.
"latedef" : false, // Prohipit variable use before definition.
"laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
"laxcomma" : false, // This option suppresses warnings about comma-first coding style.
"loopfunc" : true, // Allow functions to be defined within loops.
// "maxcomplexity" : 10, // This option lets you control cyclomatic complexity throughout your code.
// "maxdepth" : 2, // This option lets you control how nested do you want your blocks to be.
// "maxlen" : 80, // This option lets you set the maximum length of a line.
// "maxparams" : 5, // This option lets you set the max number of formal parameters allowed per function.
// "maxstatements" : 25, // This option lets you set the max number of statements allowed per function.This option lets you set the max number of formal parameters allowed per function.
"moz" : false, // This options tells JSHint that your code uses Mozilla JavaScript extensions.
"multistr" : true, // This option suppresses warnings about multi-line strings.
"noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`.
"notypeof" : false, // This option suppresses warnings about invalid typeof operator values.
"proto" : true, // This option suppresses warnings about the __proto__ property.
"scripturl" : true, // Tolerate script-targeted URLs.
"shadow" : true, // Allows re-define variables later in code e.g. `var x=1; x=2;`.
"smarttabs" : false, // This option suppresses warnings about mixed tabs and spaces when the latter are used for alignmnent only.
"supernew" : false, // Tolerate `new function () { ... };` and `new Object;`.
"undef" : true, // Require all non-global variables be declared before they are used.
"unused" : true, // This option warns when you define and never use your variables.
"validthis" : true, // This option suppresses warnings about possible strict violations when the code is running in strict mode and you use this in a non-constructor function.
// Styling
"indent" : 4, // Specify indentation spacing
"newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`.
"noempty" : true, // Prohibit use of empty blocks.
"nonew" : true, // Prohibit use of constructors for side-effects.
"plusplus" : false, // Prohibit use of `++` & `--`.
"quotmark" : false, // This option enforces the consistency of quotation marks used throughout your code.
"sub" : true, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
"trailing" : true // Prohibit trailing whitespaces.
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Before

Width:  |  Height:  |  Size: 612 KiB

After

Width:  |  Height:  |  Size: 612 KiB

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 176 KiB

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

+58
View File
@@ -0,0 +1,58 @@
module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-typescript');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
typescript: {
base: {
src: ['Phaser/**/*.ts'],
dest: 'build/phaser.js',
options: {
target: 'ES5'
}
}
},
copy: {
main: {
files: [{
src: 'build/phaser.js',
dest: 'Tests/phaser.js'
}]
},
amd: {
files: [{
src: 'build/phaser.js',
dest: 'build/phaser.amd.js'
}],
options: {
processContent: function(content) {
var replacement = [
'(function (root, factory) {',
' if (typeof exports === \'object\') {',
' module.exports = factory();',
' } else if (typeof define === \'function\' && define.amd) {',
' define(factory);',
' } else {',
' root.Phaser = factory();',
' }',
'}(this, function () {',
content,
'return Phaser;',
'}));'
];
return replacement.join('\n');
}
}
}
},
watch: {
files: '**/*.ts',
tasks: ['typescript', 'copy']
}
});
grunt.registerTask('default', ['watch']);
}
-177
View File
@@ -1,177 +0,0 @@
module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadTasks('./tasks');
grunt.initConfig({
compile_dir: 'dist',
src: {
phaser: [
'src/Intro.js',
'src/pixi/Pixi.js',
'src/Phaser.js',
'src/utils/Utils.js',
'src/pixi/core/Matrix.js',
'src/pixi/core/Point.js',
'src/pixi/core/Rectangle.js',
'src/pixi/core/Polygon.js',
'src/pixi/display/DisplayObject.js',
'src/pixi/display/DisplayObjectContainer.js',
'src/pixi/display/Sprite.js',
'src/pixi/display/Stage.js',
'src/pixi/extras/CustomRenderable.js',
'src/pixi/extras/Strip.js',
'src/pixi/extras/Rope.js',
'src/pixi/extras/TilingSprite.js',
'src/pixi/filters/AbstractFilter.js',
'src/pixi/filters/FilterBlock.js',
'src/pixi/primitives/Graphics.js',
'src/pixi/renderers/canvas/CanvasGraphics.js',
'src/pixi/renderers/canvas/CanvasRenderer.js',
'src/pixi/renderers/webgl/PixiShader.js',
'src/pixi/renderers/webgl/PrimitiveShader.js',
'src/pixi/renderers/webgl/StripShader.js',
'src/pixi/renderers/webgl/WebGLBatch.js',
'src/pixi/renderers/webgl/WebGLFilterManager.js',
'src/pixi/renderers/webgl/WebGLGraphics.js',
'src/pixi/renderers/webgl/WebGLRenderer.js',
'src/pixi/renderers/webgl/WebGLRenderGroup.js',
'src/pixi/renderers/webgl/WebGLShaders.js',
'src/pixi/text/BitmapText.js',
'src/pixi/text/Text.js',
'src/pixi/textures/BaseTexture.js',
'src/pixi/textures/Texture.js',
'src/pixi/textures/RenderTexture.js',
'src/pixi/utils/EventTarget.js',
'src/pixi/utils/Polyk.js',
'src/core/Camera.js',
'src/core/State.js',
'src/core/StateManager.js',
'src/core/LinkedList.js',
'src/core/Signal.js',
'src/core/SignalBinding.js',
'src/core/Filter.js',
'src/core/Plugin.js',
'src/core/PluginManager.js',
'src/core/Stage.js',
'src/core/Group.js',
'src/core/World.js',
'src/core/Game.js',
'src/input/Input.js',
'src/input/Key.js',
'src/input/Keyboard.js',
'src/input/Mouse.js',
'src/input/MSPointer.js',
'src/input/Pointer.js',
'src/input/Touch.js',
'src/input/InputHandler.js',
'src/gameobjects/Events.js',
'src/gameobjects/GameObjectFactory.js',
'src/gameobjects/BitmapData.js',
'src/gameobjects/Sprite.js',
'src/gameobjects/TileSprite.js',
'src/gameobjects/Text.js',
'src/gameobjects/BitmapText.js',
'src/gameobjects/Button.js',
'src/gameobjects/Graphics.js',
'src/gameobjects/RenderTexture.js',
'src/system/Canvas.js',
'src/system/StageScaleMode.js',
'src/system/Device.js',
'src/system/RequestAnimationFrame.js',
'src/math/RandomDataGenerator.js',
'src/math/Math.js',
'src/math/QuadTree.js',
'src/geom/Circle.js',
'src/geom/Point.js',
'src/geom/Rectangle.js',
'src/geom/Polygon.js',
'src/net/Net.js',
'src/tween/TweenManager.js',
'src/tween/Tween.js',
'src/tween/Easing.js',
'src/time/Time.js',
'src/time/Timer.js',
'src/animation/AnimationManager.js',
'src/animation/Animation.js',
'src/animation/Frame.js',
'src/animation/FrameData.js',
'src/animation/AnimationParser.js',
'src/loader/Cache.js',
'src/loader/Loader.js',
'src/loader/LoaderParser.js',
'src/sound/Sound.js',
'src/sound/SoundManager.js',
'src/utils/Debug.js',
'src/utils/Color.js',
'src/physics/arcade/ArcadePhysics.js',
'src/physics/arcade/Body.js',
'src/particles/Particles.js',
'src/particles/arcade/ArcadeParticles.js',
'src/particles/arcade/Emitter.js',
'src/tilemap/Tile.js',
'src/tilemap/Tilemap.js',
'src/tilemap/TilemapLayer.js',
'src/tilemap/TilemapParser.js',
'src/tilemap/Tileset.js',
'src/PixiPatch.js'
]
},
pkg: grunt.file.readJSON('package.json'),
clean: ['<%= compile_dir %>'],
concat: {
phaser: {
options: {
process: {
data: {
version: '<%= pkg.version %>',
buildDate: '<%= grunt.template.today() %>'
}
}
},
src: ['<%= src.phaser %>'],
dest: '<%= compile_dir %>/phaser.js'
}
},
umd: {
phaser: {
src: '<%= concat.phaser.dest %>',
dest: '<%= umd.phaser.src %>'
}
},
uglify: {
phaser: {
options: {
banner: '/*! Phaser v<%= pkg.version %> | (c) 2013 Photon Storm Ltd. */\n'
},
src: ['<%= umd.phaser.dest %>'],
dest: '<%= compile_dir %>/phaser.min.js'
}
},
examples: {
all: {
options: {
base: 'examples',
excludes: ['_site', 'assets', 'states', 'wip']
},
src: ['examples/**/*.js'],
dest: 'examples/_site/examples.json'
}
},
connect: {
root: {
options: {
keepalive: true
}
}
}
});
grunt.registerTask('default', ['build', 'examples']);
grunt.registerTask('build', ['clean', 'concat', 'umd', 'uglify']);
};
+38
View File
@@ -0,0 +1,38 @@
#ignore thumbnails created by windows
Thumbs.db
#Ignore files build by Visual Studio
*.obj
*.exe
*.pdb
*.user
*.aps
*.pch
*.vspscc
*_i.c
*_p.c
*.ncb
*.suo
*.sln
*.tlb
*.tlh
*.bak
*.cache
*.ilk
*.log
*.map
*.orig
*.js
!phaser.js
*.map
*.config
.DS_Store
[Bb]in
[Dd]ebug*/
*.lib
*.sbr
obj/
[Rr]elease*/
_ReSharper*/
[Tt]est[Rr]esult*
+186
View File
@@ -0,0 +1,186 @@
/// <reference path="Game.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" />
/**
* Phaser - AnimationManager
*
* Any Sprite that has animation contains an instance of the AnimationManager, which is used to add, play and update
* sprite specific animations.
*/
module Phaser {
export class AnimationManager {
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: any[] = null, frameRate: number = 60, loop: bool = false, useNumericIndex: bool = true) {
if (this._frameData == null)
{
return;
}
if (frames == null)
{
frames = this._frameData.getFrameIndexes();
}
else
{
if (this.validateFrames(frames, useNumericIndex) == false)
{
throw Error('Invalid frames given to Animation ' + name);
return;
}
}
if (useNumericIndex == false)
{
frames = this._frameData.getFrameIndexesByName(frames);
}
this._anims[name] = new Animation(this._game, this._parent, this._frameData, name, frames, frameRate, loop);
this.currentAnim = this._anims[name];
this.currentFrame = this.currentAnim.currentFrame;
}
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;
}
public play(name: string, frameRate?: number = null, loop?: bool) {
if (this._anims[name])
{
if (this.currentAnim == this._anims[name])
{
if (this.currentAnim.isPlaying == false)
{
this.currentAnim.play(frameRate, loop);
}
}
else
{
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) {
if (this._frameData.getFrame(value) !== null)
{
this.currentFrame = this._frameData.getFrame(value);
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) {
if (this._frameData.getFrameByName(value) !== null)
{
this.currentFrame = this._frameData.getFrameByName(value);
this._parent.bounds.width = this.currentFrame.width;
this._parent.bounds.height = this.currentFrame.height;
this._frameIndex = this.currentFrame.index;
}
}
}
}
+138
View File
@@ -0,0 +1,138 @@
/// <reference path="Game.ts" />
/**
* Phaser - Basic
*
* A useful "generic" object on which all GameObjects and Groups are based.
* It has no size, position or graphical data.
*/
module Phaser {
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 State/Group.
*/
public exists: bool;
/**
* Controls whether <code>update()</code> is automatically called by State/Group.
*/
public active: bool;
/**
* Controls whether <code>draw()</code> is automatically called by State/Group.
*/
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>Object.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 "";
}
}
}
+176
View File
@@ -0,0 +1,176 @@
/// <reference path="Game.ts" />
/**
* Phaser - Cache
*
* A game only has one instance of a Cache and it is used to store all externally loaded assets such
* as images, sounds and data files as a result of Loader calls. Cache items use string based keys for look-up.
*/
module Phaser {
export class Cache {
constructor(game: Game) {
this._game = game;
this._canvases = {};
this._images = {};
this._sounds = {};
this._text = {};
}
private _game: Game;
private _canvases;
private _images;
private _sounds;
private _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;
}
public getImage(key: string) {
if (this._images[key])
{
return this._images[key].data;
}
return null;
}
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']];
}
}
}
}
+89
View File
@@ -0,0 +1,89 @@
/// <reference path="Game.ts" />
/// <reference path="system/Camera.ts" />
/**
* Phaser - CameraManager
*
* Your game only has one CameraManager instance and it's responsible for looking after, creating and destroying
* all of the cameras in the world.
*
* 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
*/
module Phaser {
export class CameraManager {
constructor(game: Game, x: number, y: number, width: number, height: number) {
this._game = game;
this._cameras = [];
this.current = this.addCamera(x, y, width, height);
}
private _game: Game;
private _cameras: Camera[];
private _cameraInstance: number = 0;
public current: Camera;
public getAll(): Camera[] {
return this._cameras;
}
public update() {
this._cameras.forEach((camera) => camera.update());
}
public render() {
this._cameras.forEach((camera) => camera.render());
}
public addCamera(x: number, y: number, width: number, height: number): Camera {
var newCam: Camera = new Camera(this._game, this._cameraInstance, x, y, width, height);
this._cameras.push(newCam);
this._cameraInstance++;
return newCam;
}
public removeCamera(id: number): bool {
for (var c = 0; c < this._cameras.length; c++)
{
if (this._cameras[c].ID == id)
{
if (this.current.ID === this._cameras[c].ID)
{
this.current = null;
}
this._cameras.splice(c, 1);
return true;
}
}
return false;
}
public destroy() {
this._cameras.length = 0;
this.current = this.addCamera(0, 0, this._game.stage.width, this._game.stage.height);
}
}
}
File diff suppressed because it is too large Load Diff
+217
View File
@@ -0,0 +1,217 @@
/// <reference path="Game.ts" />
/**
* Phaser - DynamicTexture
*
* A DynamicTexture can be thought of as a mini canvas into which you can draw anything.
* Game Objects can be assigned a DynamicTexture, so when they render in the world they do so
* based on the contents of the texture at the time. This allows you to create powerful effects
* once and have them replicated across as many game objects as you like.
*/
module Phaser {
export class DynamicTexture {
constructor(game: Game, width: number, height: number) {
this._game = game;
this.canvas = <HTMLCanvasElement> document.createElement('canvas');
this.canvas.width = width;
this.canvas.height = height;
this.context = this.canvas.getContext('2d');
this.bounds = new Rectangle(0, 0, width, height);
}
private _game: Game;
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?
public bounds: Rectangle;
public canvas: HTMLCanvasElement;
public context: CanvasRenderingContext2D;
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);
return this.getColor(imageData.data[0], imageData.data[1], imageData.data[2]);
}
public getPixel32(x: number, y: number) {
var imageData = this.context.getImageData(x, y, 1, 1);
return this.getColor32(imageData.data[3], imageData.data[0], imageData.data[1], imageData.data[2]);
}
// Returns a CanvasPixelArray
public getPixels(rect: Rectangle) {
return this.context.getImageData(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 setPixel32(x: number, y: number, color: number) {
this.context.fillStyle = color;
this.context.fillRect(x, y, 1, 1);
}
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;
}
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)
);
}
}
// 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;
}
}
}
+429
View File
@@ -0,0 +1,429 @@
/// <reference path="AnimationManager.ts" />
/// <reference path="Basic.ts" />
/// <reference path="Cache.ts" />
/// <reference path="CameraManager.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="SoundManager.ts" />
/// <reference path="Stage.ts" />
/// <reference path="Time.ts" />
/// <reference path="TweenManager.ts" />
/// <reference path="World.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" />
/// <reference path="gameobjects/ScrollZone.ts" />
/**
* Phaser - Game
*
* This is where the magic happens. The Game object is the heart of your game,
* providing quick access to common functions and handling the boot process.
*
* "Hell, there are no rules here - we're trying to accomplish something."
* Thomas A. Edison
*/
module Phaser {
export class Game {
constructor(callbackContext, parent?: string = '', width?: number = 800, height?: number = 600, initCallback = null, createCallback = null, updateCallback = null, renderCallback = null) {
this.callbackContext = callbackContext;
this.onInitCallback = initCallback;
this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback;
if (document.readyState === 'complete' || document.readyState === 'interactive')
{
setTimeout(() => this.boot(parent, width, height));
}
else
{
document.addEventListener('DOMContentLoaded', () => this.boot(parent, width, height), false);
window.addEventListener('load', () => this.boot(parent, width, height), false);
}
}
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 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 (this.isBooted == true)
{
return;
}
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.isBooted = false;
this.stage.drawInitScreen();
}
else
{
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() {
this.time.update();
this.tweens.update();
if (this._paused == true)
{
if (this.onPausedCallback !== null)
{
this.onPausedCallback.call(this.callbackContext);
}
return;
}
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.loader.reset();
this.onInitCallback.call(this.callbackContext);
// Is the loader empty?
if (this.loader.queueSize == 0)
{
if (this.onCreateCallback !== null)
{
this.onCreateCallback.call(this.callbackContext);
}
this._loadComplete = true;
}
}
else
{
// No init? Then there was nothing to load either
if (this.onCreateCallback !== null)
{
this.onCreateCallback.call(this.callbackContext);
}
this._loadComplete = true;
}
}
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 new Error("Invalid State object given. Must contain at least a create or update function.");
}
}
// 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.cache = null;
this.input = null;
this.loader = null;
this.sound = null;
this.stage = null;
this.time = null;
this.world = null;
this.isBooted = false;
}
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(width: number, height: number): DynamicTexture {
return this.world.createDynamicTexture(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 createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
return this.world.createScrollZone(key, x, y, width, height);
}
public createTilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
return this.world.createTilemap(key, mapData, format, resizeWorld, 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);
}
public get camera(): Camera {
return this.world.cameras.current;
}
}
}
@@ -1,4 +1,4 @@
/// <reference path="../_definitions.ts" /> /// <reference path="Game.ts" />
/** /**
* Phaser - GameMath * Phaser - GameMath
@@ -13,65 +13,52 @@ module Phaser {
constructor(game: Game) { constructor(game: Game) {
this.game = game; this._game = game;
GameMath.sinA = [];
GameMath.cosA = [];
for (var i = 0; i < 360; i++)
{
GameMath.sinA.push(Math.sin(this.degreesToRadians(i)));
GameMath.cosA.push(Math.cos(this.degreesToRadians(i)));
}
} }
public game: Phaser.Game; private _game: Game;
// Pre-calculated tables containing Math.sin(angle) and Math.cos(angle) from -180 to 180 public static PI: number = 3.141592653589793; //number pi
// So sinA[sprite.rotation] would be the same as Math.sin(sprite.rotation) without a call to Math.sin public static PI_2: number = 1.5707963267948965; //PI / 2 OR 90 deg
static sinA: number[]; public static PI_4: number = 0.7853981633974483; //PI / 4 OR 45 deg
static cosA: number[]; public static PI_8: number = 0.39269908169872413; //PI / 8 OR 22.5 deg
public static PI_16: number = 0.19634954084936206; //PI / 16 OR 11.25 deg
public static TWO_PI: number = 6.283185307179586; //2 * PI OR 180 deg
public static THREE_PI_2: number = 4.7123889803846895; //3 * PI_2 OR 270 deg
public static E: number = 2.71828182845905; //number e
public static LN10: number = 2.302585092994046; //ln(10)
public static LN2: number = 0.6931471805599453; //ln(2)
public static LOG10E: number = 0.4342944819032518; //logB10(e)
public static LOG2E: number = 1.442695040888963387; //logB2(e)
public static SQRT1_2: number = 0.7071067811865476; //sqrt( 1 / 2 )
public static SQRT2: number = 1.4142135623730951; //sqrt( 2 )
public static DEG_TO_RAD: number = 0.017453292519943294444444444444444; //PI / 180;
public static RAD_TO_DEG: number = 57.295779513082325225835265587527; // 180.0 / PI;
static PI: number = 3.141592653589793; //number pi public static B_16: number = 65536;//2^16
static PI_2: number = 1.5707963267948965; //PI / 2 OR 90 deg public static B_31: number = 2147483648;//2^31
static PI_4: number = 0.7853981633974483; //PI / 4 OR 45 deg public static B_32: number = 4294967296;//2^32
static PI_8: number = 0.39269908169872413; //PI / 8 OR 22.5 deg public static B_48: number = 281474976710656;//2^48
static PI_16: number = 0.19634954084936206; //PI / 16 OR 11.25 deg public static B_53: number = 9007199254740992;//2^53 !!NOTE!! largest accurate double floating point whole value
static TWO_PI: number = 6.283185307179586; //2 * PI OR 180 deg public static B_64: number = 18446744073709551616;//2^64 !!NOTE!! Not accurate see B_53
static THREE_PI_2: number = 4.7123889803846895; //3 * PI_2 OR 270 deg
static E: number = 2.71828182845905; //number e
static LN10: number = 2.302585092994046; //ln(10)
static LN2: number = 0.6931471805599453; //ln(2)
static LOG10E: number = 0.4342944819032518; //logB10(e)
static LOG2E: number = 1.442695040888963387; //logB2(e)
static SQRT1_2: number = 0.7071067811865476; //sqrt( 1 / 2 )
static SQRT2: number = 1.4142135623730951; //sqrt( 2 )
static DEG_TO_RAD: number = 0.017453292519943294444444444444444; //PI / 180;
static RAD_TO_DEG: number = 57.295779513082325225835265587527; // 180.0 / PI;
static B_16: number = 65536;//2^16 public static ONE_THIRD: number = 0.333333333333333333333333333333333; // 1.0/3.0;
static B_31: number = 2147483648;//2^31 public static TWO_THIRDS: number = 0.666666666666666666666666666666666; // 2.0/3.0;
static B_32: number = 4294967296;//2^32 public static ONE_SIXTH: number = 0.166666666666666666666666666666666; // 1.0/6.0;
static B_48: number = 281474976710656;//2^48
static B_53: number = 9007199254740992;//2^53 !!NOTE!! largest accurate double floating point whole value
static B_64: number = 18446744073709551616;//2^64 !!NOTE!! Not accurate see B_53
static ONE_THIRD: number = 0.333333333333333333333333333333333; // 1.0/3.0; public static COS_PI_3: number = 0.86602540378443864676372317075294;//COS( PI / 3 )
static TWO_THIRDS: number = 0.666666666666666666666666666666666; // 2.0/3.0; public static SIN_2PI_3: number = 0.03654595;// SIN( 2*PI/3 )
static ONE_SIXTH: number = 0.166666666666666666666666666666666; // 1.0/6.0;
static COS_PI_3: number = 0.86602540378443864676372317075294;//COS( PI / 3 ) public static CIRCLE_ALPHA: number = 0.5522847498307933984022516322796; //4*(Math.sqrt(2)-1)/3.0;
static SIN_2PI_3: number = 0.03654595;// SIN( 2*PI/3 )
static CIRCLE_ALPHA: number = 0.5522847498307933984022516322796; //4*(Math.sqrt(2)-1)/3.0; public static ON: bool = true;
public static OFF: bool = false;
static ON: bool = true; public static SHORT_EPSILON: number = 0.1;//round integer epsilon
static OFF: bool = false; public static PERC_EPSILON: number = 0.001;//percentage epsilon
public static EPSILON: number = 0.0001;//single float average epsilon
static SHORT_EPSILON: number = 0.1;//round integer epsilon public static LONG_EPSILON: number = 0.00000001;//arbitrary 8 digit epsilon
static PERC_EPSILON: number = 0.001;//percentage epsilon
static EPSILON: number = 0.0001;//single float average epsilon
static LONG_EPSILON: number = 0.00000001;//arbitrary 8 digit epsilon
public cosTable = []; public cosTable = [];
public sinTable = []; public sinTable = [];
@@ -179,7 +166,7 @@ module Phaser {
* *
* @param input - the value to snap * @param input - the value to snap
* @param gap - the interval gap of the grid * @param gap - the interval gap of the grid
* @param [start] - optional starting offset for gap * @param start - optional starting offset for gap
*/ */
public snapTo(input: number, gap: number, start: number = 0): number { public snapTo(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input; if (gap == 0) return input;
@@ -196,7 +183,7 @@ module Phaser {
* *
* @param input - the value to snap * @param input - the value to snap
* @param gap - the interval gap of the grid * @param gap - the interval gap of the grid
* @param [start] - optional starting offset for gap * @param start - optional starting offset for gap
*/ */
public snapToFloor(input: number, gap: number, start: number = 0): number { public snapToFloor(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input; if (gap == 0) return input;
@@ -213,7 +200,7 @@ module Phaser {
* *
* @param input - the value to snap * @param input - the value to snap
* @param gap - the interval gap of the grid * @param gap - the interval gap of the grid
* @param [start] - optional starting offset for gap * @param start - optional starting offset for gap
*/ */
public snapToCeil(input: number, gap: number, start: number = 0): number { public snapToCeil(input: number, gap: number, start: number = 0): number {
if (gap == 0) return input; if (gap == 0) return input;
@@ -226,7 +213,7 @@ module Phaser {
/** /**
* Snaps a value to the nearest value in an array. * Snaps a value to the nearest value in an array.
*/ */
public snapToInArray(input: number, arr: number[], sort: bool = true): number { public snapToInArray(input: number, arr: number[], sort?: bool = true): number {
if (sort) arr.sort(); if (sort) arr.sort();
if (input < arr[0]) return arr[0]; if (input < arr[0]) return arr[0];
@@ -323,7 +310,7 @@ module Phaser {
/** /**
* set an angle within the bounds of -PI to PI * set an angle with in the bounds of -PI to PI
*/ */
public normalizeAngle(angle: number, radians: bool = true): number { public normalizeAngle(angle: number, radians: bool = true): number {
var rd: number = (radians) ? GameMath.PI : 180; var rd: number = (radians) ? GameMath.PI : 180;
@@ -521,7 +508,7 @@ module Phaser {
} }
/** /**
* Generate a random bool result based on the chance value * Generate a random boolean result based on the chance value
* <p> * <p>
* Returns true or false based on the chance value (default 50%). For example if you wanted a player to have a 30% chance * Returns true or false based on the chance value (default 50%). For example if you wanted a player to have a 30% chance
* of getting a bonus, call chanceRoll(30) - true means the chance passed, false means it failed. * of getting a bonus, call chanceRoll(30) - true means the chance passed, false means it failed.
@@ -725,7 +712,7 @@ module Phaser {
* @method linear * @method linear
* @param {Any} v * @param {Any} v
* @param {Any} k * @param {Any} k
* @public * @static
*/ */
public linearInterpolation(v, k) { public linearInterpolation(v, k) {
@@ -744,7 +731,7 @@ module Phaser {
* @method Bezier * @method Bezier
* @param {Any} v * @param {Any} v
* @param {Any} k * @param {Any} k
* @public * @static
*/ */
public bezierInterpolation(v, k) { public bezierInterpolation(v, k) {
@@ -764,7 +751,7 @@ module Phaser {
* @method CatmullRom * @method CatmullRom
* @param {Any} v * @param {Any} v
* @param {Any} k * @param {Any} k
* @public * @static
*/ */
public catmullRomInterpolation(v, k) { public catmullRomInterpolation(v, k) {
@@ -795,7 +782,7 @@ module Phaser {
* @param {Any} p0 * @param {Any} p0
* @param {Any} p1 * @param {Any} p1
* @param {Any} t * @param {Any} t
* @public * @static
*/ */
public linear(p0, p1, t) { public linear(p0, p1, t) {
@@ -807,7 +794,7 @@ module Phaser {
* @method Bernstein * @method Bernstein
* @param {Any} n * @param {Any} n
* @param {Any} i * @param {Any} i
* @public * @static
*/ */
public bernstein(n, i) { public bernstein(n, i) {
@@ -822,7 +809,7 @@ module Phaser {
* @param {Any} p2 * @param {Any} p2
* @param {Any} p3 * @param {Any} p3
* @param {Any} t * @param {Any} t
* @public * @static
*/ */
public catmullRom(p0, p1, p2, p3, t) { public catmullRom(p0, p1, p2, p3, t) {
@@ -837,30 +824,60 @@ module Phaser {
} }
/**
* The global random number generator seed (for deterministic behavior in recordings and saves).
*/
public globalSeed: number = Math.random();
/**
* Generates a random number. Deterministic, meaning safe
* to use if you want to record replays in random environments.
*
* @return A <code>Number</code> between 0 and 1.
*/
public random(): number {
return this.globalSeed = this.srand(this.globalSeed);
}
/**
* Generates a random number based on the seed provided.
*
* @param Seed A number between 0 and 1, used to generate a predictable random number (very optional).
*
* @return A <code>Number</code> between 0 and 1.
*/
public srand(Seed: number): number {
return ((69621 * (Seed * 0x7FFFFFFF)) % 0x7FFFFFFF) / 0x7FFFFFFF;
}
/** /**
* Fetch a random entry from the given array. * Fetch a random entry from the given array.
* Will return null if random selection is missing, or array has no entries. * Will return null if random selection is missing, or array has no entries.
* <code>G.getRandom()</code> is deterministic and safe for use with replays/recordings.
* HOWEVER, <code>U.getRandom()</code> is NOT deterministic and unsafe for use with replays/recordings.
* *
* @param objects An array of objects. * @param Objects An array of objects.
* @param startIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array. * @param StartIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param length Optional restriction on the number of values you want to randomly select from. * @param Length Optional restriction on the number of values you want to randomly select from.
* *
* @return The random object that was selected. * @return The random object that was selected.
*/ */
public getRandom(objects, startIndex: number = 0, length: number = 0) { public getRandom(Objects, StartIndex: number = 0, Length: number = 0) {
if (objects != null) if (Objects != null)
{ {
var l: number = length; var l: number = Length;
if ((l == 0) || (l > objects.length - startIndex)) if ((l == 0) || (l > Objects.length - StartIndex))
{ {
l = objects.length - startIndex; l = Objects.length - StartIndex;
} }
if (l > 0) if (l > 0)
{ {
return objects[startIndex + Math.floor(Math.random() * l)]; return Objects[StartIndex + Math.floor(Math.random() * l)];
} }
} }
@@ -875,9 +892,9 @@ module Phaser {
* *
* @return The rounded value of that number. * @return The rounded value of that number.
*/ */
public floor(value: number): number { public floor(Value: number): number {
var n: number = value | 0; var n: number = Value | 0;
return (value > 0) ? (n) : ((n != value) ? (n - 1) : (n)); return (Value > 0) ? (n) : ((n != Value) ? (n - 1) : (n));
} }
/** /**
@@ -887,9 +904,9 @@ module Phaser {
* *
* @return The rounded value of that number. * @return The rounded value of that number.
*/ */
public ceil(value: number): number { public ceil(Value: number): number {
var n: number = value | 0; var n: number = Value | 0;
return (value > 0) ? ((n != value) ? (n + 1) : (n)) : (n); return (Value > 0) ? ((n != Value) ? (n + 1) : (n)) : (n);
} }
/** /**
@@ -906,7 +923,7 @@ module Phaser {
* @see getSinTable * @see getSinTable
* @see getCosTable * @see getCosTable
*/ */
public sinCosGenerator(length: number, sinAmplitude: number = 1.0, cosAmplitude: number = 1.0, frequency: number = 1.0) { public sinCosGenerator(length: number, sinAmplitude?: number = 1.0, cosAmplitude?: number = 1.0, frequency?: number = 1.0) {
var sin: number = sinAmplitude; var sin: number = sinAmplitude;
var cos: number = cosAmplitude; var cos: number = cosAmplitude;
@@ -960,42 +977,7 @@ module Phaser {
} }
/** /**
* Shuffles the data in the given array into a new order
* @param array The array to shuffle
* @return The array
*/
public shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--)
{
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
/**
* Returns the distance from this Point object to the given Point object.
* @method distanceFrom
* @param {Point} target - The destination Point object.
* @param {bool} round - Round the distance to the nearest integer (default false)
* @return {Number} The distance between this Point object and the destination Point object.
**/
public distanceBetween(x1: number, y1: number, x2: number, y2: number): number {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
/**
* Finds the length of the given vector * Finds the length of the given vector
* *
* @param dx * @param dx
@@ -1003,10 +985,27 @@ module Phaser {
* *
* @return * @return
*/ */
public vectorLength(dx: number, dy: number): number { public vectorLength(dx:number, dy:number):number
{
return Math.sqrt(dx * dx + dy * dy); return Math.sqrt(dx * dx + dy * dy);
} }
/**
* Finds the dot product value of two vectors
*
* @param ax Vector X
* @param ay Vector Y
* @param bx Vector X
* @param by Vector Y
*
* @return Dot product
*/
public dotProduct(ax:number, ay:number, bx:number, by:number):number
{
return ax * bx + ay * by;
}
} }
} }
+769
View File
@@ -0,0 +1,769 @@
/// <reference path="Basic.ts" />
/// <reference path="Game.ts" />
/**
* Phaser - Group
*
* This class is used for organising, updating and sorting game objects.
*
*/
module Phaser {
export class Group extends Basic {
constructor(game: Game, MaxSize?: number = 0) {
super(game);
this.isGroup = true;
this.members = [];
this.length = 0;
this._maxSize = MaxSize;
this._marker = 0;
this._sortIndex = null;
}
/**
* Use with <code>sort()</code> to sort in ascending order.
*/
public static ASCENDING: number = -1;
/**
* Use with <code>sort()</code> to sort in descending order.
*/
public static DESCENDING: number = 1;
/**
* Array of all the <code>Basic</code>s that exist in this group.
*/
public members: Basic[];
/**
* The number of entries in the members array.
* For performance and safety you should check this variable
* instead of members.length unless you really know what you're doing!
*/
public length: number;
/**
* Internal tracker for the maximum capacity of the group.
* Default is 0, or no max capacity.
*/
private _maxSize: number;
/**
* Internal helper variable for recycling objects a la <code>Emitter</code>.
*/
private _marker: number;
/**
* Helper for sort.
*/
private _sortIndex: string;
/**
* Helper for sort.
*/
private _sortOrder: number;
/**
* Override this function to handle any deleting or "shutdown" type operations you might need,
* such as removing traditional Flash children like Basic objects.
*/
public destroy() {
if (this.members != null)
{
var basic: Basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if (basic != null)
{
basic.destroy();
}
}
this.members.length = 0;
}
this._sortIndex = null;
}
/**
* Automatically goes through and calls update on everything you added.
*/
public update() {
var basic: Basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if ((basic != null) && basic.exists && basic.active)
{
basic.preUpdate();
basic.update();
basic.postUpdate();
}
}
}
/**
* Automatically goes through and calls render on everything you added.
*/
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
var basic: Basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if ((basic != null) && basic.exists && basic.visible)
{
basic.render(camera, cameraOffsetX, cameraOffsetY);
}
}
}
/**
* The maximum capacity of this group. Default is 0, meaning no max capacity, and the group can just grow.
*/
public get maxSize(): number {
return this._maxSize;
}
/**
* @private
*/
public set maxSize(Size: number) {
this._maxSize = Size;
if (this._marker >= this._maxSize)
{
this._marker = 0;
}
if ((this._maxSize == 0) || (this.members == null) || (this._maxSize >= this.members.length))
{
return;
}
//If the max size has shrunk, we need to get rid of some objects
var basic: Basic;
var i: number = this._maxSize;
var l: number = this.members.length;
while (i < l)
{
basic = this.members[i++];
if (basic != null)
{
basic.destroy();
}
}
this.length = this.members.length = this._maxSize;
}
/**
* Adds a new <code>Basic</code> subclass (Basic, Basic, Enemy, etc) to the group.
* Group will try to replace a null member of the array first.
* Failing that, Group will add it to the end of the member array,
* assuming there is room for it, and doubling the size of the array if necessary.
*
* <p>WARNING: If the group has a maxSize that has already been met,
* the object will NOT be added to the group!</p>
*
* @param Object The object you want to add to the group.
*
* @return The same <code>Basic</code> object that was passed in.
*/
public add(Object: Basic) {
//Don't bother adding an object twice.
if (this.members.indexOf(Object) >= 0)
{
return Object;
}
//First, look for a null entry where we can add the object.
var i: number = 0;
var l: number = this.members.length;
while (i < l)
{
if (this.members[i] == null)
{
this.members[i] = Object;
if (i >= this.length)
{
this.length = i + 1;
}
return Object;
}
i++;
}
//Failing that, expand the array (if we can) and add the object.
if (this._maxSize > 0)
{
if (this.members.length >= this._maxSize)
{
return Object;
}
else if (this.members.length * 2 <= this._maxSize)
{
this.members.length *= 2;
}
else
{
this.members.length = this._maxSize;
}
}
else
{
this.members.length *= 2;
}
//If we made it this far, then we successfully grew the group,
//and we can go ahead and add the object at the first open slot.
this.members[i] = Object;
this.length = i + 1;
return Object;
}
/**
* Recycling is designed to help you reuse game objects without always re-allocating or "newing" them.
*
* <p>If you specified a maximum size for this group (like in Emitter),
* then recycle will employ what we're calling "rotating" recycling.
* Recycle() will first check to see if the group is at capacity yet.
* If group is not yet at capacity, recycle() returns a new object.
* If the group IS at capacity, then recycle() just returns the next object in line.</p>
*
* <p>If you did NOT specify a maximum size for this group,
* then recycle() will employ what we're calling "grow-style" recycling.
* Recycle() will return either the first object with exists == false,
* or, finding none, add a new object to the array,
* doubling the size of the array if necessary.</p>
*
* <p>WARNING: If this function needs to create a new object,
* and no object class was provided, it will return null
* instead of a valid object!</p>
*
* @param ObjectClass The class type you want to recycle (e.g. Basic, EvilRobot, etc). Do NOT "new" the class in the parameter!
*
* @return A reference to the object that was created. Don't forget to cast it back to the Class you want (e.g. myObject = myGroup.recycle(myObjectClass) as myObjectClass;).
*/
public recycle(ObjectClass = null) {
var basic;
if (this._maxSize > 0)
{
if (this.length < this._maxSize)
{
if (ObjectClass == null)
{
return null;
}
return this.add(new ObjectClass(this._game));
}
else
{
basic = this.members[this._marker++];
if (this._marker >= this._maxSize)
{
this._marker = 0;
}
return basic;
}
}
else
{
basic = this.getFirstAvailable(ObjectClass);
if (basic != null)
{
return basic;
}
if (ObjectClass == null)
{
return null;
}
return this.add(new ObjectClass(this._game));
}
}
/**
* Removes an object from the group.
*
* @param Object The <code>Basic</code> you want to remove.
* @param Splice Whether the object should be cut from the array entirely or not.
*
* @return The removed object.
*/
public remove(Object: Basic, Splice: bool = false): Basic {
var index: number = this.members.indexOf(Object);
if ((index < 0) || (index >= this.members.length))
{
return null;
}
if (Splice)
{
this.members.splice(index, 1);
this.length--;
}
else
{
this.members[index] = null;
}
return Object;
}
/**
* Replaces an existing <code>Basic</code> with a new one.
*
* @param OldObject The object you want to replace.
* @param NewObject The new object you want to use instead.
*
* @return The new object.
*/
public replace(OldObject: Basic, NewObject: Basic): Basic {
var index: number = this.members.indexOf(OldObject);
if ((index < 0) || (index >= this.members.length))
{
return null;
}
this.members[index] = NewObject;
return NewObject;
}
/**
* Call this function to sort the group according to a particular value and order.
* For example, to sort game objects for Zelda-style overlaps you might call
* <code>myGroup.sort("y",Group.ASCENDING)</code> at the bottom of your
* <code>State.update()</code> override. To sort all existing objects after
* a big explosion or bomb attack, you might call <code>myGroup.sort("exists",Group.DESCENDING)</code>.
*
* @param Index The <code>string</code> name of the member variable you want to sort on. Default value is "y".
* @param Order A <code>Group</code> constant that defines the sort order. Possible values are <code>Group.ASCENDING</code> and <code>Group.DESCENDING</code>. Default value is <code>Group.ASCENDING</code>.
*/
public sort(Index: string = "y", Order: number = Group.ASCENDING) {
this._sortIndex = Index;
this._sortOrder = Order;
this.members.sort(this.sortHandler);
}
/**
* Go through and set the specified variable to the specified value on all members of the group.
*
* @param VariableName The string representation of the variable name you want to modify, for example "visible" or "scrollFactor".
* @param Value The value you want to assign to that variable.
* @param Recurse Default value is true, meaning if <code>setAll()</code> encounters a member that is a group, it will call <code>setAll()</code> on that group rather than modifying its variable.
*/
public setAll(VariableName: string, Value: Object, Recurse: bool = true) {
var basic: Basic;
var i: number = 0;
while (i < length)
{
basic = this.members[i++];
if (basic != null)
{
if (Recurse && (basic.isGroup == true))
{
<Group> basic['setAll'](VariableName, Value, Recurse);
}
else
{
basic[VariableName] = Value;
}
}
}
}
/**
* Go through and call the specified function on all members of the group.
* Currently only works on functions that have no required parameters.
*
* @param FunctionName The string representation of the function you want to call on each object, for example "kill()" or "init()".
* @param Recurse Default value is true, meaning if <code>callAll()</code> encounters a member that is a group, it will call <code>callAll()</code> on that group rather than calling the group's function.
*/
public callAll(FunctionName: string, Recurse: bool = true) {
var basic: Basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if (basic != null)
{
if (Recurse && (basic.isGroup == true))
{
<Group> basic['callAll'](FunctionName, Recurse);
}
else
{
basic[FunctionName]();
}
}
}
}
public forEach(callback, recursive: bool = false) {
var basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if (basic != null)
{
if (recursive && (basic.isGroup == true))
{
basic.forEach(callback, true);
}
else
{
callback.call(this, basic);
}
}
}
}
public forEachAlive(context, callback, recursive: bool = false) {
var basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if (basic != null && basic.alive)
{
if (recursive && (basic.isGroup == true))
{
basic.forEachAlive(context, callback, true);
}
else
{
callback.call(context, basic);
}
}
}
}
/**
* Call this function to retrieve the first object with exists == false in the group.
* This is handy for recycling in general, e.g. respawning enemies.
*
* @param ObjectClass An optional parameter that lets you narrow the results to instances of this particular class.
*
* @return A <code>Basic</code> currently flagged as not existing.
*/
public getFirstAvailable(ObjectClass = null) {
var basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if ((basic != null) && !basic.exists && ((ObjectClass == null) || (typeof basic === ObjectClass)))
{
return basic;
}
}
return null;
}
/**
* Call this function to retrieve the first index set to 'null'.
* Returns -1 if no index stores a null object.
*
* @return An <code>int</code> indicating the first null slot in the group.
*/
public getFirstNull(): number {
var basic: Basic;
var i: number = 0;
var l: number = this.members.length;
while (i < l)
{
if (this.members[i] == null)
{
return i;
}
else
{
i++;
}
}
return -1;
}
/**
* Call this function to retrieve the first object with exists == true in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return A <code>Basic</code> currently flagged as existing.
*/
public getFirstExtant(): Basic {
var basic: Basic;
var i: number = 0;
while (i < length)
{
basic = this.members[i++];
if ((basic != null) && basic.exists)
{
return basic;
}
}
return null;
}
/**
* Call this function to retrieve the first object with dead == false in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return A <code>Basic</code> currently flagged as not dead.
*/
public getFirstAlive(): Basic {
var basic: Basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if ((basic != null) && basic.exists && basic.alive)
{
return basic;
}
}
return null;
}
/**
* Call this function to retrieve the first object with dead == true in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return A <code>Basic</code> currently flagged as dead.
*/
public getFirstDead(): Basic {
var basic: Basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if ((basic != null) && !basic.alive)
{
return basic;
}
}
return null;
}
/**
* Call this function to find out how many members of the group are not dead.
*
* @return The number of <code>Basic</code>s flagged as not dead. Returns -1 if group is empty.
*/
public countLiving(): number {
var count: number = -1;
var basic: Basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if (basic != null)
{
if (count < 0)
{
count = 0;
}
if (basic.exists && basic.alive)
{
count++;
}
}
}
return count;
}
/**
* Call this function to find out how many members of the group are dead.
*
* @return The number of <code>Basic</code>s flagged as dead. Returns -1 if group is empty.
*/
public countDead(): number {
var count: number = -1;
var basic: Basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if (basic != null)
{
if (count < 0)
{
count = 0;
}
if (!basic.alive)
{
count++;
}
}
}
return count;
}
/**
* Returns a member at random from the group.
*
* @param StartIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param Length Optional restriction on the number of values you want to randomly select from.
*
* @return A <code>Basic</code> from the members list.
*/
public getRandom(StartIndex: number = 0, Length: number = 0): Basic {
if (Length == 0)
{
Length = this.length;
}
return this._game.math.getRandom(this.members, StartIndex, Length);
}
/**
* Remove all instances of <code>Basic</code> subclass (Basic, Block, etc) from the list.
* WARNING: does not destroy() or kill() any of these objects!
*/
public clear() {
this.length = this.members.length = 0;
}
/**
* Calls kill on the group's members and then on the group itself.
*/
public kill() {
var basic: Basic;
var i: number = 0;
while (i < this.length)
{
basic = this.members[i++];
if ((basic != null) && basic.exists)
{
basic.kill();
}
}
}
/**
* Helper function for the sort process.
*
* @param Obj1 The first object being sorted.
* @param Obj2 The second object being sorted.
*
* @return An integer value: -1 (Obj1 before Obj2), 0 (same), or 1 (Obj1 after Obj2).
*/
public sortHandler(Obj1: Basic, Obj2: Basic): number {
if (Obj1[this._sortIndex] < Obj2[this._sortIndex])
{
return this._sortOrder;
}
else if (Obj1[this._sortIndex] > Obj2[this._sortIndex])
{
return -this._sortOrder;
}
return 0;
}
}
}
+347
View File
@@ -0,0 +1,347 @@
/// <reference path="Game.ts" />
/**
* Phaser - Loader
*
* The Loader handles loading all external content such as Images, Sounds, Texture Atlases and data files.
* It uses a combination of Image() loading and xhr and provides for progress and completion callbacks.
*/
module Phaser {
export class Loader {
constructor(game: Game, callback) {
this._game = game;
this._gameCreateComplete = callback;
this._keys = [];
this._fileList = {};
this._xhr = new XMLHttpRequest();
this._queueSize = 0;
}
private _game: Game;
private _keys: string[];
private _fileList;
private _gameCreateComplete;
private _onComplete;
private _onFileLoad;
private _progressChunk: number;
private _xhr: XMLHttpRequest;
private _queueSize: number;
public hasLoaded: bool;
public progress: number;
public reset() {
this._queueSize = 0;
}
public get queueSize(): number {
return this._queueSize;
}
public addImageFile(key: string, url: string) {
if (this.checkKeyExists(key) === false)
{
this._queueSize++;
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) {
if (this.checkKeyExists(key) === false)
{
this._queueSize++;
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) {
if (this.checkKeyExists(key) === false)
{
if (jsonURL !== null)
{
// A URL to a json file has been given
this._queueSize++;
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: jsonURL, jsonData: null, error: false, loaded: false };
this._keys.push(key);
}
else
{
// A json string or object has been given
if (typeof jsonData === 'string')
{
var data = JSON.parse(jsonData);
// Malformed?
if (data['frames'])
{
this._queueSize++;
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
{
// Malformed?
if (jsonData['frames'])
{
this._queueSize++;
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._queueSize++;
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._queueSize++;
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;
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':
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
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) {
var data = JSON.parse(this._xhr.response);
// 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) {
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.progress > 1)
{
this.progress = 1;
}
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);
}
}
}
private checkKeyExists(key: string): bool {
if (this._fileList[key])
{
return true;
}
else
{
return false;
}
}
}
}
@@ -22,12 +22,12 @@ module Phaser {
/** /**
* A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity.
* *
* @param {number} Velocity Any component of velocity (e.g. 20). * @param Velocity Any component of velocity (e.g. 20).
* @param {number} Acceleration Rate at which the velocity is changing. * @param Acceleration Rate at which the velocity is changing.
* @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set. * @param Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set.
* @param {number} Max An absolute value cap for the velocity. * @param Max An absolute value cap for the velocity.
* *
* @return {number} The altered Velocity value. * @return The altered Velocity value.
*/ */
public computeVelocity(Velocity: number, Acceleration: number = 0, Drag: number = 0, Max: number = 10000): number { public computeVelocity(Velocity: number, Acceleration: number = 0, Drag: number = 0, Max: number = 10000): number {
@@ -72,10 +72,10 @@ module Phaser {
/** /**
* Given the angle and speed calculate the velocity and return it as a Point * Given the angle and speed calculate the velocity and return it as a Point
* *
* @param {number} angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) * @param angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
* @param {number} speed The speed it will move, in pixels per second sq * @param speed The speed it will move, in pixels per second sq
* *
* @return {Point} A Point where Point.x contains the velocity x value and Point.y contains the velocity y value * @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 { public velocityFromAngle(angle: number, speed: number): Point {
@@ -98,10 +98,10 @@ module Phaser {
* If you need the object to accelerate, see accelerateTowardsObject() instead * 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) * 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 {GameObject} source The Sprite on which the velocity will be set * @param source The Sprite on which the velocity will be set
* @param {GameObject} dest The Sprite where the source object will move to * @param dest The Sprite where the source object will move to
* @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) * @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param {number} 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 * @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) public moveTowardsObject(source:GameObject, dest:GameObject, speed:number= 60, maxTime:number = 0)
{ {
@@ -125,11 +125,11 @@ module Phaser {
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<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. * If you don't need acceleration look at moveTowardsObject() instead.
* *
* @param {GameObject} source The Sprite on which the acceleration will be set * @param source The Sprite on which the acceleration will be set
* @param {GameObject} dest The Sprite where the source object will move towards * @param dest The Sprite where the source object will move towards
* @param {number} speed The speed it will accelerate in pixels per second * @param speed The speed it will accelerate in pixels per second
* @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally * @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically * @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) public accelerateTowardsObject(source:GameObject, dest:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
{ {
@@ -152,9 +152,9 @@ module Phaser {
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<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> * The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
* *
* @param {GameObject} source The Sprite to move * @param source The Sprite to move
* @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) * @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param {number} 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 * @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) public moveTowardsMouse(source:GameObject, speed:number = 60, maxTime:number = 0)
{ {
@@ -178,10 +178,10 @@ module Phaser {
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<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. * If you don't need acceleration look at moveTowardsMouse() instead.
* *
* @param {GameObject} source The Sprite on which the acceleration will be set * @param source The Sprite on which the acceleration will be set
* @param {number} speed The speed it will accelerate in pixels per second * @param speed The speed it will accelerate in pixels per second
* @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally * @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically * @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) public accelerateTowardsMouse(source:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
{ {
@@ -203,10 +203,10 @@ module Phaser {
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<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> * The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
* *
* @param {GameObject} source The Sprite to move * @param source The Sprite to move
* @param {Point} target The Point coordinates to move the source Sprite towards * @param target The Point coordinates to move the source Sprite towards
* @param {number} speed The speed it will move, in pixels per second (default is 60 pixels/sec) * @param speed The speed it will move, in pixels per second (default is 60 pixels/sec)
* @param {number} 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 * @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) public moveTowardsPoint(source:GameObject, target:Point, speed:number = 60, maxTime:number = 0)
{ {
@@ -229,11 +229,11 @@ module Phaser {
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<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. * If you don't need acceleration look at moveTowardsPoint() instead.
* *
* @param {GameObject} source The Sprite on which the acceleration will be set * @param source The Sprite on which the acceleration will be set
* @param {Point} target The Point coordinates to move the source Sprite towards * @param target The Point coordinates to move the source Sprite towards
* @param {number} speed The speed it will accelerate in pixels per second * @param speed The speed it will accelerate in pixels per second
* @param {number} xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally * @param xSpeedMax The maximum speed in pixels per second in which the sprite can move horizontally
* @param {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically * @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) public accelerateTowardsPoint(source:GameObject, target:Point, speed:number, xSpeedMax:number, ySpeedMax:number)
{ {
@@ -252,9 +252,9 @@ module Phaser {
/** /**
* Find the distance (in pixels, rounded) between two Sprites, taking their origin into account * Find the distance (in pixels, rounded) between two Sprites, taking their origin into account
* *
* @param {GameObject} a The first Sprite * @param a The first Sprite
* @param {GameObject} b The second Sprite * @param b The second Sprite
* @return {number} int Distance (in pixels) * @return int Distance (in pixels)
*/ */
public distanceBetween(a:GameObject, b:GameObject):number public distanceBetween(a:GameObject, b:GameObject):number
{ {
@@ -268,9 +268,9 @@ module Phaser {
/** /**
* Find the distance (in pixels, rounded) from an Sprite to the given Point, taking the source origin into account * Find the distance (in pixels, rounded) from an Sprite to the given Point, taking the source origin into account
* *
* @param {GameObject} a The Sprite * @param a The Sprite
* @param {Point} target The Point * @param target The Point
* @return {number} Distance (in pixels) * @return int Distance (in pixels)
*/ */
public distanceToPoint(a:GameObject, target:Point):number public distanceToPoint(a:GameObject, target:Point):number
{ {
@@ -283,8 +283,8 @@ module Phaser {
/** /**
* Find the distance (in pixels, rounded) from the object x/y and the mouse x/y * Find the distance (in pixels, rounded) from the object x/y and the mouse x/y
* *
* @param {GameObject} a Sprite to test against * @param a The Sprite to test against
* @return {number} The distance between the given sprite and the mouse coordinates * @return int The distance between the given sprite and the mouse coordinates
*/ */
public distanceToMouse(a:GameObject):number public distanceToMouse(a:GameObject):number
{ {
@@ -298,11 +298,11 @@ module Phaser {
* Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account. * 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) * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
* *
* @param {GameObject} a The Sprite to test from * @param a The Sprite to test from
* @param {Point} target The Point to angle the Sprite towards * @param target The Point to angle the Sprite towards
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true * @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) * @return Number The angle (in radians unless asDegrees is true)
*/ */
public angleBetweenPoint(a:GameObject, target:Point, asDegrees:bool = false):number public angleBetweenPoint(a:GameObject, target:Point, asDegrees:bool = false):number
{ {
@@ -323,11 +323,11 @@ module Phaser {
* Find the angle (in radians) between the two Sprite, taking their x/y and origin into account. * 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) * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
* *
* @param {GameObject} a The Sprite to test from * @param a The Sprite to test from
* @param {GameObject} b The Sprite to test to * @param b The Sprite to test to
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true * @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) * @return Number The angle (in radians unless asDegrees is true)
*/ */
public angleBetween(a:GameObject, b:GameObject, asDegrees:bool = false):number public angleBetween(a:GameObject, b:GameObject, asDegrees:bool = false):number
{ {
@@ -347,10 +347,10 @@ module Phaser {
/** /**
* Given the GameObject and speed calculate the velocity and return it as an Point based on the direction the sprite is facing * Given the GameObject and speed calculate the velocity and return it as an Point based on the direction the sprite is facing
* *
* @param {GameObject} parent The Sprite to get the facing value from * @param parent The Sprite to get the facing value from
* @param {number} speed The speed it will move, in pixels per second sq * @param speed The speed it will move, in pixels per second sq
* *
* @return {Point} An Point where Point.x contains the velocity x value and Point.y contains the velocity y value * @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 public velocityFromFacing(parent:GameObject, speed:number):Point
{ {
@@ -381,10 +381,10 @@ module Phaser {
* Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account. * 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) * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
* *
* @param {GameObject} a The Object to test from * @param a The Object to test from
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true * @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) * @return Number The angle (in radians unless asDegrees is true)
*/ */
public angleBetweenMouse(a:GameObject, asDegrees:bool = false):number public angleBetweenMouse(a:GameObject, asDegrees:bool = false):number
{ {
+331
View File
@@ -0,0 +1,331 @@
<?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>
<ProjectGuid>{A90BE60F-CAEA-4747-904A-CDB097BA2459}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<OutputPath>bin</OutputPath>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
<UseIISExpress>true</UseIISExpress>
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
</PropertyGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<PropertyGroup>
<RootNamespace>Phaser</RootNamespace>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>0</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:51891/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<TypeScriptTarget>ES5</TypeScriptTarget>
<TypeScriptIncludeComments>true</TypeScriptIncludeComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
<TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TypeScriptTarget>ES5</TypeScriptTarget>
<TypeScriptIncludeComments>false</TypeScriptIncludeComments>
<TypeScriptSourceMap>false</TypeScriptSourceMap>
<TypeScriptOutFile>../build/phaser.js</TypeScriptOutFile>
</PropertyGroup>
<ItemGroup>
<Folder Include="plugins\" />
</ItemGroup>
<ItemGroup>
<Content Include="AnimationManager.js">
<DependentUpon>AnimationManager.ts</DependentUpon>
</Content>
<Content Include="Collision.js">
<DependentUpon>Collision.ts</DependentUpon>
</Content>
<Content Include="DynamicTexture.js">
<DependentUpon>DynamicTexture.ts</DependentUpon>
</Content>
<Content Include="Game.js">
<DependentUpon>Game.ts</DependentUpon>
</Content>
<Content Include="GameMath.js">
<DependentUpon>GameMath.ts</DependentUpon>
</Content>
<Content Include="gameobjects\Emitter.js">
<DependentUpon>Emitter.ts</DependentUpon>
</Content>
<Content Include="gameobjects\GameObject.js">
<DependentUpon>GameObject.ts</DependentUpon>
</Content>
<Content Include="gameobjects\GeomSprite.js">
<DependentUpon>GeomSprite.ts</DependentUpon>
</Content>
<Content Include="gameobjects\Particle.js">
<DependentUpon>Particle.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="gameobjects\ScrollZone.ts" />
<TypeScriptCompile Include="gameobjects\ScrollRegion.ts" />
<Content Include="gameobjects\ScrollRegion.js">
<DependentUpon>ScrollRegion.ts</DependentUpon>
</Content>
<Content Include="gameobjects\ScrollZone.js">
<DependentUpon>ScrollZone.ts</DependentUpon>
</Content>
<Content Include="gameobjects\Sprite.js">
<DependentUpon>Sprite.ts</DependentUpon>
</Content>
<Content Include="gameobjects\Tilemap.js">
<DependentUpon>Tilemap.ts</DependentUpon>
</Content>
<Content Include="geom\Circle.js">
<DependentUpon>Circle.ts</DependentUpon>
</Content>
<Content Include="geom\IntersectResult.js">
<DependentUpon>IntersectResult.ts</DependentUpon>
</Content>
<Content Include="geom\Line.js">
<DependentUpon>Line.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geom\MicroPoint.ts" />
<Content Include="geom\MicroPoint.js">
<DependentUpon>MicroPoint.ts</DependentUpon>
</Content>
<Content Include="geom\Point.js">
<DependentUpon>Point.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="geom\Quad.ts" />
<Content Include="geom\Quad.js">
<DependentUpon>Quad.ts</DependentUpon>
</Content>
<Content Include="geom\Rectangle.js">
<DependentUpon>Rectangle.ts</DependentUpon>
</Content>
<Content Include="SoundManager.js">
<DependentUpon>SoundManager.ts</DependentUpon>
</Content>
<Content Include="system\Sound.js">
<DependentUpon>Sound.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="system\Sound.ts" />
<TypeScriptCompile Include="SoundManager.ts" />
<Content Include="system\animation\Animation.js">
<DependentUpon>Animation.ts</DependentUpon>
</Content>
<Content Include="system\animation\AnimationLoader.js">
<DependentUpon>AnimationLoader.ts</DependentUpon>
</Content>
<Content Include="system\animation\Frame.js">
<DependentUpon>Frame.ts</DependentUpon>
</Content>
<Content Include="system\animation\FrameData.js">
<DependentUpon>FrameData.ts</DependentUpon>
</Content>
<Content Include="system\Camera.js">
<DependentUpon>Camera.ts</DependentUpon>
</Content>
<Content Include="system\Device.js">
<DependentUpon>Device.ts</DependentUpon>
</Content>
<Content Include="system\LinkedList.js">
<DependentUpon>LinkedList.ts</DependentUpon>
</Content>
<Content Include="system\QuadTree.js">
<DependentUpon>QuadTree.ts</DependentUpon>
</Content>
<Content Include="system\RandomDataGenerator.js">
<DependentUpon>RandomDataGenerator.ts</DependentUpon>
</Content>
<Content Include="system\RequestAnimationFrame.js">
<DependentUpon>RequestAnimationFrame.ts</DependentUpon>
</Content>
<Content Include="system\StageScaleMode.js">
<DependentUpon>StageScaleMode.ts</DependentUpon>
</Content>
<Content Include="system\Tile.js">
<DependentUpon>Tile.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="system\TilemapLayer.ts" />
<Content Include="system\TilemapLayer.js">
<DependentUpon>TilemapLayer.ts</DependentUpon>
</Content>
<Content Include="system\Tween.js">
<DependentUpon>Tween.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="system\Tween.ts" />
<TypeScriptCompile Include="system\Tile.ts" />
<TypeScriptCompile Include="system\StageScaleMode.ts" />
<TypeScriptCompile Include="system\RequestAnimationFrame.ts" />
<TypeScriptCompile Include="system\RandomDataGenerator.ts" />
<TypeScriptCompile Include="system\QuadTree.ts" />
<TypeScriptCompile Include="system\LinkedList.ts" />
<TypeScriptCompile Include="system\Device.ts" />
<TypeScriptCompile Include="system\Camera.ts" />
<Content Include="system\easing\Back.js">
<DependentUpon>Back.ts</DependentUpon>
</Content>
<Content Include="system\easing\Bounce.js">
<DependentUpon>Bounce.ts</DependentUpon>
</Content>
<Content Include="system\easing\Circular.js">
<DependentUpon>Circular.ts</DependentUpon>
</Content>
<Content Include="system\easing\Cubic.js">
<DependentUpon>Cubic.ts</DependentUpon>
</Content>
<Content Include="system\easing\Elastic.js">
<DependentUpon>Elastic.ts</DependentUpon>
</Content>
<Content Include="system\easing\Exponential.js">
<DependentUpon>Exponential.ts</DependentUpon>
</Content>
<Content Include="system\easing\Linear.js">
<DependentUpon>Linear.ts</DependentUpon>
</Content>
<Content Include="system\easing\Quadratic.js">
<DependentUpon>Quadratic.ts</DependentUpon>
</Content>
<Content Include="system\easing\Quartic.js">
<DependentUpon>Quartic.ts</DependentUpon>
</Content>
<Content Include="system\easing\Quintic.js">
<DependentUpon>Quintic.ts</DependentUpon>
</Content>
<Content Include="system\easing\Sinusoidal.js">
<DependentUpon>Sinusoidal.ts</DependentUpon>
</Content>
<Content Include="system\input\Finger.js">
<DependentUpon>Finger.ts</DependentUpon>
</Content>
<Content Include="system\input\Input.js">
<DependentUpon>Input.ts</DependentUpon>
</Content>
<Content Include="system\input\Keyboard.js">
<DependentUpon>Keyboard.ts</DependentUpon>
</Content>
<Content Include="system\input\Mouse.js">
<DependentUpon>Mouse.ts</DependentUpon>
</Content>
<Content Include="system\input\Touch.js">
<DependentUpon>Touch.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="system\input\Touch.ts" />
<TypeScriptCompile Include="system\input\Mouse.ts" />
<TypeScriptCompile Include="system\input\Keyboard.ts" />
<TypeScriptCompile Include="system\input\Input.ts" />
<TypeScriptCompile Include="system\input\Finger.ts" />
<TypeScriptCompile Include="system\easing\Sinusoidal.ts" />
<TypeScriptCompile Include="system\easing\Quintic.ts" />
<TypeScriptCompile Include="system\easing\Quartic.ts" />
<TypeScriptCompile Include="system\easing\Quadratic.ts" />
<TypeScriptCompile Include="system\easing\Linear.ts" />
<TypeScriptCompile Include="system\easing\Exponential.ts" />
<TypeScriptCompile Include="system\easing\Elastic.ts" />
<TypeScriptCompile Include="system\easing\Cubic.ts" />
<TypeScriptCompile Include="system\easing\Circular.ts" />
<TypeScriptCompile Include="system\easing\Bounce.ts" />
<TypeScriptCompile Include="system\easing\Back.ts" />
<TypeScriptCompile Include="system\animation\FrameData.ts" />
<TypeScriptCompile Include="system\animation\Frame.ts" />
<TypeScriptCompile Include="system\animation\AnimationLoader.ts" />
<TypeScriptCompile Include="system\animation\Animation.ts" />
<TypeScriptCompile Include="geom\Rectangle.ts" />
<TypeScriptCompile Include="geom\Point.ts" />
<TypeScriptCompile Include="geom\Line.ts" />
<TypeScriptCompile Include="geom\IntersectResult.ts" />
<TypeScriptCompile Include="geom\Circle.ts" />
<TypeScriptCompile Include="gameobjects\Tilemap.ts" />
<TypeScriptCompile Include="gameobjects\Sprite.ts" />
<TypeScriptCompile Include="gameobjects\Particle.ts" />
<TypeScriptCompile Include="gameobjects\GeomSprite.ts" />
<TypeScriptCompile Include="gameobjects\GameObject.ts" />
<TypeScriptCompile Include="gameobjects\Emitter.ts" />
<Content Include="Group.js">
<DependentUpon>Group.ts</DependentUpon>
</Content>
<Content Include="Loader.js">
<DependentUpon>Loader.ts</DependentUpon>
</Content>
<Content Include="Motion.js">
<DependentUpon>Motion.ts</DependentUpon>
</Content>
<Content Include="Phaser.js">
<DependentUpon>Phaser.ts</DependentUpon>
</Content>
<Content Include="Signal.js">
<DependentUpon>Signal.ts</DependentUpon>
</Content>
<Content Include="SignalBinding.js">
<DependentUpon>SignalBinding.ts</DependentUpon>
</Content>
<Content Include="Stage.js">
<DependentUpon>Stage.ts</DependentUpon>
</Content>
<Content Include="State.js">
<DependentUpon>State.ts</DependentUpon>
</Content>
<Content Include="Time.js">
<DependentUpon>Time.ts</DependentUpon>
</Content>
<Content Include="TweenManager.js">
<DependentUpon>TweenManager.ts</DependentUpon>
</Content>
<Content Include="World.js">
<DependentUpon>World.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="World.ts" />
<TypeScriptCompile Include="TweenManager.ts" />
<TypeScriptCompile Include="Time.ts" />
<TypeScriptCompile Include="State.ts" />
<TypeScriptCompile Include="Stage.ts" />
<TypeScriptCompile Include="SignalBinding.ts" />
<TypeScriptCompile Include="Signal.ts" />
<TypeScriptCompile Include="Phaser.ts" />
<TypeScriptCompile Include="Motion.ts" />
<TypeScriptCompile Include="Loader.ts" />
<TypeScriptCompile Include="Group.ts" />
<TypeScriptCompile Include="GameMath.ts" />
<TypeScriptCompile Include="Game.ts" />
<TypeScriptCompile Include="DynamicTexture.ts" />
<TypeScriptCompile Include="Collision.ts" />
<TypeScriptCompile Include="AnimationManager.ts" />
<Content Include="Basic.js">
<DependentUpon>Basic.ts</DependentUpon>
</Content>
<Content Include="Cache.js">
<DependentUpon>Cache.ts</DependentUpon>
</Content>
<Content Include="CameraManager.js">
<DependentUpon>CameraManager.ts</DependentUpon>
</Content>
<TypeScriptCompile Include="CameraManager.ts" />
<TypeScriptCompile Include="Cache.ts" />
<TypeScriptCompile Include="Basic.ts" />
</ItemGroup>
<Import Project="$(VSToolsPath)\TypeScript\Microsoft.TypeScript.targets" />
<PropertyGroup>
<PostBuildEvent>cd $(ProjectDir)..\build
copy phaser.js ..\Tests\</PostBuildEvent>
</PropertyGroup>
</Project>
+21
View File
@@ -0,0 +1,21 @@
/**
* Phaser
*
* v0.9.4 - April 28th 2013
*
* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi.
*
* Richard Davey (@photonstorm)
*
* Many thanks to Adam Saltsman (@ADAMATOMIC) for the original Flixel AS3 code on which Phaser is based.
*
* "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.4';
}
@@ -1,4 +1,4 @@
/// <reference path="../_definitions.ts" /> /// <reference path="SignalBinding.ts" />
/** /**
* Phaser - Signal * Phaser - Signal
@@ -41,12 +41,12 @@ module Phaser {
* If Signal should keep record of previously dispatched parameters and * If Signal should keep record of previously dispatched parameters and
* automatically execute listener during `add()`/`addOnce()` if Signal was * automatically execute listener during `add()`/`addOnce()` if Signal was
* already dispatched before. * already dispatched before.
* @type bool * @type boolean
*/ */
public memorize: bool = false; public memorize: bool = false;
/** /**
* @type bool * @type boolean
* @private * @private
*/ */
private _shouldPropagate: bool = true; private _shouldPropagate: bool = true;
@@ -54,7 +54,7 @@ module Phaser {
/** /**
* If Signal is active and should broadcast events. * 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> * <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 bool * @type boolean
*/ */
public active: bool = true; public active: bool = true;
@@ -75,7 +75,7 @@ module Phaser {
/** /**
* @param {Function} listener * @param {Function} listener
* @param {bool} isOnce * @param {boolean} isOnce
* @param {Object} [listenerContext] * @param {Object} [listenerContext]
* @param {Number} [priority] * @param {Number} [priority]
* @return {SignalBinding} * @return {SignalBinding}
@@ -159,9 +159,9 @@ module Phaser {
* Check if listener was attached to Signal. * Check if listener was attached to Signal.
* @param {Function} listener * @param {Function} listener
* @param {Object} [context] * @param {Object} [context]
* @return {bool} if Signal has the specified listener. * @return {boolean} if Signal has the specified listener.
*/ */
public has(listener, context: any = null): bool { public has(listener, context?: any = null): bool {
return this._indexOfListener(listener, context) !== -1; return this._indexOfListener(listener, context) !== -1;
@@ -174,7 +174,7 @@ module Phaser {
* @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) * @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. * @return {SignalBinding} An Object representing the binding between the Signal and listener.
*/ */
public add(listener, listenerContext: any = null, priority: number = 0): SignalBinding { public add(listener, listenerContext?: any = null, priority?: number = 0): SignalBinding {
this.validateListener(listener, 'add'); this.validateListener(listener, 'add');
@@ -189,7 +189,7 @@ module Phaser {
* @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) * @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. * @return {SignalBinding} An Object representing the binding between the Signal and listener.
*/ */
public addOnce(listener, listenerContext: any = null, priority: number = 0): SignalBinding { public addOnce(listener, listenerContext?: any = null, priority?: number = 0): SignalBinding {
this.validateListener(listener, 'addOnce'); this.validateListener(listener, 'addOnce');
@@ -203,7 +203,7 @@ module Phaser {
* @param {Object} [context] Execution context (since you can add the same handler multiple times if executing in a different context). * @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. * @return {Function} Listener handler function.
*/ */
public remove(listener, context: any = null) { public remove(listener, context?: any = null) {
this.validateListener(listener, 'remove'); this.validateListener(listener, 'remove');
@@ -211,7 +211,7 @@ module Phaser {
if (i !== -1) if (i !== -1)
{ {
this._bindings[i]._destroy(); this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal
this._bindings.splice(i, 1); this._bindings.splice(i, 1);
} }
@@ -224,18 +224,15 @@ module Phaser {
*/ */
public removeAll() { public removeAll() {
if (this._bindings) var n: number = this._bindings.length;
while (n--)
{ {
var n: number = this._bindings.length; this._bindings[n]._destroy();
while (n--)
{
this._bindings[n]._destroy();
}
this._bindings.length = 0;
} }
this._bindings.length = 0;
} }
/** /**
@@ -1,4 +1,4 @@
/// <reference path="../_definitions.ts" /> /// <reference path="Signal.ts" />
/** /**
* Phaser - SignalBinding * Phaser - SignalBinding
@@ -23,11 +23,11 @@ module Phaser {
* @name SignalBinding * @name SignalBinding
* @param {Signal} signal Reference to Signal object that listener is currently bound to. * @param {Signal} signal Reference to Signal object that listener is currently bound to.
* @param {Function} listener Handler function bound to the signal. * @param {Function} listener Handler function bound to the signal.
* @param {bool} isOnce If binding should be executed just once. * @param {boolean} isOnce If binding should be executed just once.
* @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener 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. (default = 0). * @param {Number} [priority] The priority level of the event listener. (default = 0).
*/ */
constructor(signal: Signal, listener, isOnce: bool, listenerContext, priority: number = 0) { constructor(signal: Signal, listener, isOnce: bool, listenerContext, priority?: number = 0) {
this._listener = listener; this._listener = listener;
this._isOnce = isOnce; this._isOnce = isOnce;
@@ -46,7 +46,7 @@ module Phaser {
/** /**
* If binding should be executed just once. * If binding should be executed just once.
* @type bool * @type boolean
* @private * @private
*/ */
private _isOnce: bool; private _isOnce: bool;
@@ -74,7 +74,7 @@ module Phaser {
/** /**
* If binding is active and should be executed. * If binding is active and should be executed.
* @type bool * @type boolean
*/ */
public active: bool = true; public active: bool = true;
@@ -90,7 +90,7 @@ module Phaser {
* @param {Array} [paramsArr] Array of parameters that should be passed to the listener * @param {Array} [paramsArr] Array of parameters that should be passed to the listener
* @return {*} Value returned by the listener. * @return {*} Value returned by the listener.
*/ */
public execute(paramsArr: any[]) { public execute(paramsArr?: any[]) {
var handlerReturn; var handlerReturn;
var params; var params;
@@ -123,7 +123,7 @@ module Phaser {
} }
/** /**
* @return {bool} `true` if binding is still bound to the signal and have a listener. * @return {Boolean} `true` if binding is still bound to the signal and have a listener.
*/ */
public isBound(): bool { public isBound(): bool {
@@ -132,7 +132,7 @@ module Phaser {
} }
/** /**
* @return {bool} If SignalBinding will only be executed once. * @return {boolean} If SignalBinding will only be executed once.
*/ */
public isOnce(): bool { public isOnce(): bool {
+124
View File
@@ -0,0 +1,124 @@
/// <reference path="Game.ts" />
/// <reference path="system/Sound.ts" />
/**
* Phaser - SoundManager
*
* This is an embroyonic web audio sound management class. There is a lot of work still to do here.
*/
module Phaser {
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;
}
}
}
private _game: Game;
private _context = null;
private _gainNode;
private _volume: number;
public mute() {
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 play(key: string, volume?: number = 1, loop?: bool = false): Sound {
if (this._context === null)
{
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;
}
}
}
}
}
+247
View File
@@ -0,0 +1,247 @@
/// <reference path="Phaser.ts" />
/// <reference path="Game.ts" />
/// <reference path="system/StageScaleMode.ts" />
/**
* Phaser - Stage
*
* The Stage is the canvas on which everything is displayed. This class handles display within the web browser, focus handling,
* resizing, scaling and pause/boot screens.
*/
module Phaser {
export class Stage {
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);
}
// Consume default actions on the canvas
this.canvas.style.msTouchAction = 'none';
this.canvas.style['touch-action'] = 'none';
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;
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 disablePauseScreen: bool = false;
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() {
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);
}
}
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);
}
//if (document['hidden'] === true || document['webkitHidden'] === true)
private visibilityChange(event) {
//console.log(event);
if (this.disablePauseScreen)
{
return;
}
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;
}
}
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==";
}
}
+103
View File
@@ -0,0 +1,103 @@
/// <reference path="Game.ts" />
/**
* Phaser - State
*
* This is a base State class which can be extended if you are creating your game using TypeScript.
*/
module Phaser {
export class State {
constructor(game: Game) {
this.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 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() { }
// Handy Proxy methods
public createCamera(x: number, y: number, width: number, height: number): Camera {
return this.game.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.game.world.createSprite(x, y, key);
}
public createDynamicTexture(width: number, height: number): DynamicTexture {
return this.game.world.createDynamicTexture(width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return this.game.world.createGroup(MaxSize);
}
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 createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
return this.game.world.createScrollZone(key, x, y, width, height);
}
public createTilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
return this.game.world.createTilemap(key, mapData, format, resizeWorld, 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);
}
}
}
+140
View File
@@ -0,0 +1,140 @@
/// <reference path="Game.ts" />
/**
* Phaser - Time
*
* This is the game clock and it manages elapsed time and calculation of delta values, used for game object motion.
*/
module Phaser {
export class Time {
constructor(game: Game) {
this._started = Date.now();
this._timeLastSecond = this._started;
this.time = this._started;
}
private _game: Game;
private _started: number;
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
//// 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;
}
}
}
+95
View File
@@ -0,0 +1,95 @@
/// <reference path="Game.ts" />
/// <reference path="system/Tween.ts" />
/**
* Phaser - TweenManager
*
* The Game has a single instance of the TweenManager through which all Tween objects are created and updated.
* Tweens are hooked into the game clock and pause system, adjusting based on the game state.
* TweenManager is based heavily on tween.js by sole (http://soledadpenades.com).
* I converted it to TypeScript, swapped the callbacks for signals and patched a few issues with regard
* to properties and completion errors. Please see https://github.com/sole/tween.js for a full list of contributors.
*/
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;
}
}
}
+159
View File
@@ -0,0 +1,159 @@
/// <reference path="Game.ts" />
/**
* Phaser - World
*
* A game has only one world. The world is an abstract place in which all game objects live. It is not bound
* by stage limits and can be any size or dimension. You look into the world via cameras and all game objects
* live within the world at world-based coordinates. By default a world is created the same size as your Stage.
*/
module Phaser {
export class World {
constructor(game: Game, width: number, height: number) {
this._game = game;
this.cameras = new CameraManager(this._game, 0, 0, width, height);
this._game.camera = this.cameras.current;
this.group = new Group(this._game, 0);
this.bounds = new Rectangle(0, 0, width, height);
this.worldDivisions = 6;
}
private _game: Game;
public cameras: CameraManager;
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);
}
}
public get width(): number {
return this.bounds.width;
}
public set width(value: number) {
this.bounds.width = value;
}
public get height(): number {
return this.bounds.height;
}
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 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();
}
// Game Objects
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(width: number, height: number): DynamicTexture {
return new DynamicTexture(this._game, width, height);
}
public createGroup(MaxSize?: number = 0): Group {
return <Group> this.group.add(new Group(this._game, MaxSize));
}
public createScrollZone(key: string, x?: number = 0, y?: number = 0, width?: number = 0, height?: number = 0): ScrollZone {
return <ScrollZone> this.group.add(new ScrollZone(this._game, key, x, y, width, height));
}
public createTilemap(key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0): Tilemap {
return <Tilemap> this.group.add(new Tilemap(this._game, key, mapData, format, resizeWorld, tileWidth, tileHeight));
}
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));
}
}
}
@@ -17,16 +17,14 @@ module Phaser {
* Creates a new <code>Emitter</code> object at a specific position. * Creates a new <code>Emitter</code> object at a specific position.
* Does NOT automatically generate or attach particles! * Does NOT automatically generate or attach particles!
* *
* @param x {number} The X position of the emitter. * @param X The X position of the emitter.
* @param y {number} The Y position of the emitter. * @param Y The Y position of the emitter.
* @param [size] {number} Specifies a maximum capacity for this emitter. * @param Size Optional, specifies a maximum capacity for this emitter.
*/ */
constructor(game: Game, x: number = 0, y: number = 0, size: number = 0) { constructor(game: Game, X: number = 0, Y: number = 0, Size: number = 0) {
super(game, Size);
super(game, size); this.x = X;
this.y = Y;
this.x = x;
this.y = y;
this.width = 0; this.width = 0;
this.height = 0; this.height = 0;
this.minParticleSpeed = new MicroPoint(-100, -100); this.minParticleSpeed = new MicroPoint(-100, -100);
@@ -44,7 +42,6 @@ module Phaser {
this._explode = true; this._explode = true;
this.on = false; this.on = false;
this._point = new MicroPoint(); this._point = new MicroPoint();
} }
/** /**
@@ -169,16 +166,17 @@ module Phaser {
/** /**
* This function generates a new array of particle sprites to attach to the emitter. * 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 Sprite objects, you can simply pass in a particle image or sprite sheet. * @param Graphics If you opted to not pre-configure an array of Sprite objects, you can simply pass in a particle image or sprite sheet.
* @param quantity {number} The number of particles to generate when using the "create from image" option. * @param Quantity The number of particles to generate when using the "create from image" option.
* @param multiple {boolean} 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 BakedRotations How many frames of baked rotation to use (boosts performance). Set to zero to not use baked rotations.
* @param collide {number} 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. * @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 Emitter instance (nice for chaining stuff together, if you're into that). * @return This Emitter instance (nice for chaining stuff together, if you're into that).
*/ */
public makeParticles(graphics, quantity: number = 50, multiple: bool = false, collide: number = 0): Emitter { public makeParticles(Graphics, Quantity: number = 50, BakedRotations: number = 16, Multiple: bool = false, Collide: number = 0): Emitter {
this.maxSize = quantity; this.maxSize = Quantity;
var totalFrames: number = 1; var totalFrames: number = 1;
@@ -196,7 +194,7 @@ module Phaser {
var particle: Particle; var particle: Particle;
var i: number = 0; var i: number = 0;
while (i < quantity) while (i < Quantity)
{ {
if (this.particleClass == null) if (this.particleClass == null)
{ {
@@ -207,7 +205,7 @@ module Phaser {
particle = new this.particleClass(this._game); particle = new this.particleClass(this._game);
} }
if (multiple) if (Multiple)
{ {
/* /*
randomFrame = this._game.math.random()*totalFrames; randomFrame = this._game.math.random()*totalFrames;
@@ -229,18 +227,18 @@ module Phaser {
particle.loadGraphic(Graphics); particle.loadGraphic(Graphics);
*/ */
if (graphics) if (Graphics)
{ {
particle.loadGraphic(graphics); particle.loadGraphic(Graphics);
} }
} }
if (collide > 0) if (Collide > 0)
{ {
particle.allowCollisions = Collision.ANY; particle.allowCollisions = Collision.ANY;
particle.width *= collide; particle.width *= Collide;
particle.height *= collide; particle.height *= Collide;
//particle.centerOffsets(); //particle.centerOffsets();
} }
else else
@@ -321,22 +319,22 @@ module Phaser {
/** /**
* Call this function to start emitting particles. * Call this function to start emitting particles.
* *
* @param explode {boolean} Whether the particles should all burst out at once. * @param Explode Whether the particles should all burst out at once.
* @param lifespan {number} How long each particle lives once emitted. 0 = forever. * @param Lifespan How long each particle lives once emitted. 0 = forever.
* @param frequency {number} 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 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 {number} How many particles to launch. 0 = "all of the particles". * @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) { public start(Explode: bool = true, Lifespan: number = 0, Frequency: number = 0.1, Quantity: number = 0) {
this.revive(); this.revive();
this.visible = true; this.visible = true;
this.on = true; this.on = true;
this._explode = explode; this._explode = Explode;
this.lifespan = lifespan; this.lifespan = Lifespan;
this.frequency = frequency; this.frequency = Frequency;
this._quantity += quantity; this._quantity += Quantity;
this._counter = 0; this._counter = 0;
this._timer = 0; this._timer = 0;
@@ -398,54 +396,54 @@ module Phaser {
/** /**
* A more compact way of setting the width and height of the emitter. * A more compact way of setting the width and height of the emitter.
* *
* @param width {number} The desired width of the emitter (particles are spawned randomly within these dimensions). * @param Width The desired width of the emitter (particles are spawned randomly within these dimensions).
* @param height {number} The desired height of the emitter. * @param Height The desired height of the emitter.
*/ */
public setSize(width: number, height: number) { public setSize(Width: number, Height: number) {
this.width = width; this.width = Width;
this.height = height; this.height = Height;
} }
/** /**
* A more compact way of setting the X velocity range of the emitter. * A more compact way of setting the X velocity range of the emitter.
* *
* @param Min {number} The minimum value for this range. * @param Min The minimum value for this range.
* @param Max {number} The maximum value for this range. * @param Max The maximum value for this range.
*/ */
public setXSpeed(min: number = 0, max: number = 0) { public setXSpeed(Min: number = 0, Max: number = 0) {
this.minParticleSpeed.x = min; this.minParticleSpeed.x = Min;
this.maxParticleSpeed.x = max; this.maxParticleSpeed.x = Max;
} }
/** /**
* A more compact way of setting the Y velocity range of the emitter. * A more compact way of setting the Y velocity range of the emitter.
* *
* @param Min {number} The minimum value for this range. * @param Min The minimum value for this range.
* @param Max {number} The maximum value for this range. * @param Max The maximum value for this range.
*/ */
public setYSpeed(min: number = 0, max: number = 0) { public setYSpeed(Min: number = 0, Max: number = 0) {
this.minParticleSpeed.y = min; this.minParticleSpeed.y = Min;
this.maxParticleSpeed.y = max; this.maxParticleSpeed.y = Max;
} }
/** /**
* A more compact way of setting the angular velocity constraints of the emitter. * A more compact way of setting the angular velocity constraints of the emitter.
* *
* @param Min {number} The minimum value for this range. * @param Min The minimum value for this range.
* @param Max {number} The maximum value for this range. * @param Max The maximum value for this range.
*/ */
public setRotation(min: number = 0, max: number = 0) { public setRotation(Min: number = 0, Max: number = 0) {
this.minRotation = min; this.minRotation = Min;
this.maxRotation = max; this.maxRotation = Max;
} }
/** /**
* Change the emitter's midpoint to match the midpoint of a <code>Object</code>. * Change the emitter's midpoint to match the midpoint of a <code>Object</code>.
* *
* @param Object {object} The <code>Object</code> that you want to sync up with. * @param Object The <code>Object</code> that you want to sync up with.
*/ */
public at(object) { public at(Object) {
object.getMidpoint(this._point); Object.getMidpoint(this._point);
this.x = this._point.x - (this.width >> 1); this.x = this._point.x - (this.width >> 1);
this.y = this._point.y - (this.height >> 1); this.y = this._point.y - (this.height >> 1);
} }
+600
View File
@@ -0,0 +1,600 @@
/// <reference path="../Game.ts" />
/// <reference path="../Basic.ts" />
/// <reference path="../Signal.ts" />
/**
* Phaser - GameObject
*
* This is the base GameObject on which all other game objects are derived. It contains all the logic required for position,
* motion, size, collision and input.
*/
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 MicroPoint(1, 1);
this.last = new MicroPoint(x, y);
this.origin = new MicroPoint(this.bounds.halfWidth, this.bounds.halfHeight);
this.align = GameObject.ALIGN_TOP_LEFT;
this.mass = 1;
this.elasticity = 0;
this.health = 1;
this.immovable = false;
this.moves = true;
this.worldBounds = null;
this.touching = Collision.NONE;
this.wasTouching = Collision.NONE;
this.allowCollisions = Collision.ANY;
this.velocity = new MicroPoint();
this.acceleration = new MicroPoint();
this.drag = new MicroPoint();
this.maxVelocity = new MicroPoint(10000, 10000);
this.angle = 0;
this.angularVelocity = 0;
this.angularAcceleration = 0;
this.angularDrag = 0;
this.maxAngular = 10000;
this.cameraBlacklist = [];
this.scrollFactor = new MicroPoint(1, 1);
}
private _angle: number = 0;
public static ALIGN_TOP_LEFT: number = 0;
public static ALIGN_TOP_CENTER: number = 1;
public static ALIGN_TOP_RIGHT: number = 2;
public static ALIGN_CENTER_LEFT: number = 3;
public static ALIGN_CENTER: number = 4;
public static ALIGN_CENTER_RIGHT: number = 5;
public static ALIGN_BOTTOM_LEFT: number = 6;
public static ALIGN_BOTTOM_CENTER: number = 7;
public static ALIGN_BOTTOM_RIGHT: number = 8;
public static OUT_OF_BOUNDS_STOP: number = 0;
public static OUT_OF_BOUNDS_KILL: number = 1;
public _point: MicroPoint;
public cameraBlacklist: number[];
public bounds: Rectangle;
public worldBounds: Quad;
public outOfBoundsAction: number = 0;
public align: number;
public facing: number;
public alpha: number;
public scale: MicroPoint;
public origin: MicroPoint;
public z: number = 0;
// This value is added to the angle of the GameObject.
// For example if you had a sprite drawn facing straight up then you could set
// rotationOffset to 90 and it would correspond correctly with Phasers rotation system
public rotationOffset: number = 0;
public renderRotation: bool = true;
// Physics properties
public immovable: bool;
// Velocity is given in pixels per second. Therefore a velocity of
// 100 will move at a rate of 100 pixels every 1000 ms (1sec). It's not balls-on
// accurate due to the way timers work, but it's pretty close. Expect tolerance
// of +- 10 px. Also that speed assumes no drag
public velocity: MicroPoint;
public mass: number;
public elasticity: number;
public acceleration: MicroPoint;
public drag: MicroPoint;
public maxVelocity: MicroPoint;
public angularVelocity: number;
public angularAcceleration: number;
public angularDrag: number;
public maxAngular: number;
public scrollFactor: MicroPoint;
public health: number;
public moves: bool = true;
public touching: number;
public wasTouching: number;
public allowCollisions: number;
public last: MicroPoint;
// Input
public inputEnabled: bool = false;
private _inputOver: bool = false;
public onInputOver: Phaser.Signal;
public onInputOut: Phaser.Signal;
public onInputDown: Phaser.Signal;
public onInputUp: Phaser.Signal;
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();
}
if (this.worldBounds != null)
{
if (this.outOfBoundsAction == GameObject.OUT_OF_BOUNDS_KILL)
{
if (this.x < this.worldBounds.x || this.x > this.worldBounds.right || this.y < this.worldBounds.y || this.y > this.worldBounds.bottom)
{
this.kill();
}
}
else
{
if (this.x < this.worldBounds.x)
{
this.x = this.worldBounds.x;
}
else if (this.x > this.worldBounds.right)
{
this.x = this.worldBounds.right;
}
if (this.y < this.worldBounds.y)
{
this.y = this.worldBounds.y;
}
else if (this.y > this.worldBounds.bottom)
{
this.y = this.worldBounds.bottom;
}
}
}
if (this.inputEnabled)
{
this.updateInput();
}
this.wasTouching = this.touching;
this.touching = Collision.NONE;
}
private updateInput() {
}
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>Group</code>.
* If the group has a LOT of things in it, it might be faster to use <code>Collision.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 (!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>Group</code>?
* This is distinct from overlapsPoint(), which just checks that point, 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 (!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 point in 2D world space overlaps this <code>GameObject</code>.
*
* @param Point The point 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 point 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>MicroPoint</code> object and assigns the post-scrolled X and Y values of this object to it.
*
* @return The <code>MicroPoint</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: MicroPoint = null, Camera: Camera = null): MicroPoint {
if (point == null)
{
point = new MicroPoint();
}
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 midpoint 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 midpoint of this object in world coordinates.
*/
public getMidpoint(point: MicroPoint = null): MicroPoint {
if (point == null)
{
point = new MicroPoint();
}
point.copyFrom(this.bounds.center);
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();
}
}
/**
* Set the world bounds that this GameObject can exist within. By default a GameObject can exist anywhere
* in the world. But by setting the bounds (which are given in world dimensions, not screen dimensions)
* it can be stopped from leaving the world, or a section of it.
*/
public setBounds(x: number, y: number, width: number, height: number) {
this.worldBounds = new Quad(x, y, width, height);
}
/**
* If you do not wish this object to be visible to a specific camera, pass the camera here.
*/
public hideFromCamera(camera: Camera) {
if (this.cameraBlacklist.indexOf(camera.ID) == -1)
{
this.cameraBlacklist.push(camera.ID);
}
}
public showToCamera(camera: Camera) {
if (this.cameraBlacklist.indexOf(camera.ID) !== -1)
{
this.cameraBlacklist.slice(this.cameraBlacklist.indexOf(camera.ID), 1);
}
}
public clearCameraList() {
this.cameraBlacklist.length = 0;
}
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 set width(value:number) {
this.bounds.width = value;
}
public set height(value:number) {
this.bounds.height = value;
}
public get width(): number {
return this.bounds.width;
}
public get height(): number {
return this.bounds.height;
}
}
}
+457
View File
@@ -0,0 +1,457 @@
/// <reference path="../Game.ts" />
/**
* Phaser - GeomSprite
*
* A GeomSprite is a special kind of GameObject that contains a base geometry class (Circle, Line, Point, Rectangle).
* They can be rendered in the game and used for collision just like any other game object. Display of them is controlled
* via the lineWidth / lineColor / fillColor and renderOutline / renderFill properties.
*/
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.intersects(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.cameraBlacklist.indexOf(camera.ID) !== -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 is disabled for now as I don't want it to be misleading re: collision
/*
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();
}
// And now the edge points
this._game.stage.context.fillStyle = 'rgb(255,255,255)';
this.renderPoint(this._dx, this._dy, this.rect.topLeft, 2);
this.renderPoint(this._dx, this._dy, this.rect.topCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.topRight, 2);
this.renderPoint(this._dx, this._dy, this.rect.leftCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.center, 2);
this.renderPoint(this._dx, this._dy, this.rect.rightCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomLeft, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomCenter, 2);
this.renderPoint(this._dx, this._dy, this.rect.bottomRight, 2);
}
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 renderPoint(offsetX, offsetY, point, size) {
offsetX = 0;
offsetY = 0;
this._game.stage.context.fillRect(offsetX + point.x, offsetY + point.y, 1, 1);
}
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.CIRCLE)
{
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.POINT)
{
return this.line.isPointOnLine(source.point.x, source.point.y);
}
return false;
}
}
}
+108
View File
@@ -0,0 +1,108 @@
/// <reference path="../Game.ts" />
/// <reference path="Sprite.ts" />
/**
* Phaser - Particle
*
* This is a simple particle class that extends a Sprite to have a slightly more
* specialised behaviour. It is used exclusively by the Emitter class and can be extended as required.
*/
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() {
}
}
}
@@ -1,4 +1,5 @@
/// <reference path="../_definitions.ts" /> /// <reference path="../Game.ts" />
/// <reference path="../geom/Quad.ts" />
/** /**
* Phaser - ScrollRegion * Phaser - ScrollRegion
@@ -9,61 +10,37 @@
module Phaser { module Phaser {
export class ScrollRegion { export class ScrollRegion{
/**
* ScrollRegion constructor
* Create a new <code>ScrollRegion</code>.
*
* @param x {number} X position in world coordinate.
* @param y {number} Y position in world coordinate.
* @param width {number} Width of this object.
* @param height {number} Height of this object.
* @param speedX {number} X-axis scrolling speed.
* @param speedY {number} Y-axis scrolling speed.
*/
constructor(x: number, y: number, width: number, height: number, speedX:number, speedY:number) { constructor(x: number, y: number, width: number, height: number, speedX:number, speedY:number) {
// Our seamless scrolling quads // Our seamless scrolling quads
this._A = new Rectangle(x, y, width, height); this._A = new Quad(x, y, width, height);
this._B = new Rectangle(x, y, width, height); this._B = new Quad(x, y, width, height);
this._C = new Rectangle(x, y, width, height); this._C = new Quad(x, y, width, height);
this._D = new Rectangle(x, y, width, height); this._D = new Quad(x, y, width, height);
this._scroll = new Vec2(); this._scroll = new MicroPoint();
this._bounds = new Rectangle(x, y, width, height); this._bounds = new Quad(x, y, width, height);
this.scrollSpeed = new Vec2(speedX, speedY); this.scrollSpeed = new MicroPoint(speedX, speedY);
} }
private _A: Rectangle; private _A: Quad;
private _B: Rectangle; private _B: Quad;
private _C: Rectangle; private _C: Quad;
private _D: Rectangle; private _D: Quad;
private _bounds: Rectangle; private _bounds: Quad;
private _scroll: Vec2; private _scroll: MicroPoint;
private _anchorWidth: number = 0; private _anchorWidth: number = 0;
private _anchorHeight: number = 0; private _anchorHeight: number = 0;
private _inverseWidth: number = 0; private _inverseWidth: number = 0;
private _inverseHeight: number = 0; private _inverseHeight: number = 0;
/**
* Will this region be rendered? (default to true)
* @type {bool}
*/
public visible: bool = true; public visible: bool = true;
public scrollSpeed: MicroPoint;
/**
* Region scrolling speed.
* @type {Vec2}
*/
public scrollSpeed: Vec2;
/**
* Update region scrolling with tick time.
* @param delta {number} Elapsed time since last update.
*/
public update(delta: number) { public update(delta: number) {
this._scroll.x += this.scrollSpeed.x; this._scroll.x += this.scrollSpeed.x;
@@ -106,34 +83,25 @@ module Phaser {
this._inverseWidth = this._bounds.width - this._anchorWidth; this._inverseWidth = this._bounds.width - this._anchorWidth;
this._inverseHeight = this._bounds.height - this._anchorHeight; this._inverseHeight = this._bounds.height - this._anchorHeight;
// Rectangle A // Quad A
this._A.setTo(this._scroll.x, this._scroll.y, this._anchorWidth, this._anchorHeight); this._A.setTo(this._scroll.x, this._scroll.y, this._anchorWidth, this._anchorHeight);
// Rectangle B // Quad B
this._B.y = this._scroll.y; this._B.y = this._scroll.y;
this._B.width = this._inverseWidth; this._B.width = this._inverseWidth;
this._B.height = this._anchorHeight; this._B.height = this._anchorHeight;
// Rectangle C // Quad C
this._C.x = this._scroll.x; this._C.x = this._scroll.x;
this._C.width = this._anchorWidth; this._C.width = this._anchorWidth;
this._C.height = this._inverseHeight; this._C.height = this._inverseHeight;
// Rectangle D // Quad D
this._D.width = this._inverseWidth; this._D.width = this._inverseWidth;
this._D.height = this._inverseHeight; this._D.height = this._inverseHeight;
} }
/**
* Render this region to specific context.
* @param context {CanvasRenderingContext2D} Canvas context this region will be rendered to.
* @param texture {object} The texture to be rendered.
* @param dx {number} X position in world coordinate.
* @param dy {number} Y position in world coordinate.
* @param width {number} Width of this region to be rendered.
* @param height {number} Height of this region to be rendered.
*/
public render(context:CanvasRenderingContext2D, texture, dx: number, dy: number, dw: number, dh: number) { public render(context:CanvasRenderingContext2D, texture, dx: number, dy: number, dw: number, dh: number) {
if (this.visible == false) if (this.visible == false)
@@ -151,28 +119,13 @@ module Phaser {
//context.fillStyle = 'rgb(255,255,255)'; //context.fillStyle = 'rgb(255,255,255)';
//context.font = '18px Arial'; //context.font = '18px Arial';
//context.fillText('RectangleA: ' + this._A.toString(), 32, 450); //context.fillText('QuadA: ' + this._A.toString(), 32, 450);
//context.fillText('RectangleB: ' + this._B.toString(), 32, 480); //context.fillText('QuadB: ' + this._B.toString(), 32, 480);
//context.fillText('RectangleC: ' + this._C.toString(), 32, 510); //context.fillText('QuadC: ' + this._C.toString(), 32, 510);
//context.fillText('RectangleD: ' + this._D.toString(), 32, 540); //context.fillText('QuadD: ' + this._D.toString(), 32, 540);
} }
/**
* Crop part of the texture and render it to the given context.
* @param context {CanvasRenderingContext2D} Canvas context the texture will be rendered to.
* @param texture {object} Texture to be rendered.
* @param srcX {number} Target region top-left x coordinate in the texture.
* @param srcX {number} Target region top-left y coordinate in the texture.
* @param srcW {number} Target region width in the texture.
* @param srcH {number} Target region height in the texture.
* @param destX {number} Render region top-left x coordinate in the context.
* @param destX {number} Render region top-left y coordinate in the context.
* @param destW {number} Target region width in the context.
* @param destH {number} Target region height in the context.
* @param offsetX {number} X offset to the context.
* @param offsetY {number} Y offset to the context.
*/
private crop(context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY) { private crop(context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY) {
offsetX += destX; offsetX += destX;
+208
View File
@@ -0,0 +1,208 @@
/// <reference path="../Game.ts" />
/// <reference path="../geom/Quad.ts" />
/// <reference path="ScrollRegion.ts" />
/**
* Phaser - ScrollZone
*
* Creates a scrolling region of the given width and height from an image in the cache.
* The ScrollZone can be positioned anywhere in-world like a normal game object, re-act to physics, collision, etc.
* The image within it is scrolled via ScrollRegions and their scrollSpeed.x/y properties.
* If you create a scroll zone larger than the given source image it will create a DynamicTexture and fill it with a pattern of the source image.
*/
module Phaser {
export class ScrollZone extends GameObject {
constructor(game: Game, key:string, x: number = 0, y: number = 0, width?: number = 0, height?: number = 0) {
super(game, x, y, width, height);
this.regions = [];
if (this._game.cache.getImage(key))
{
this._texture = this._game.cache.getImage(key);
this.width = this._texture.width;
this.height = this._texture.height;
if (width > this._texture.width || height > this._texture.height)
{
// Create our repeating texture (as the source image wasn't large enough for the requested size)
this.createRepeatingTexture(width, height);
this.width = width;
this.height = height;
}
// Create a default ScrollRegion at the requested size
this.addRegion(0, 0, this.width, this.height);
// If the zone is smaller than the image itself then shrink the bounds
if ((width < this._texture.width || height < this._texture.height) && width !== 0 && height !== 0)
{
this.width = width;
this.height = height;
}
}
}
private _texture;
private _dynamicTexture: DynamicTexture = null;
// 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 currentRegion: ScrollRegion;
public regions: ScrollRegion[];
public flipped: bool = false;
public addRegion(x: number, y: number, width: number, height: number, speedX?:number = 0, speedY?:number = 0):ScrollRegion {
if (x > this.width || y > this.height || x < 0 || y < 0 || (x + width) > this.width || (y + height) > this.height)
{
throw Error('Invalid ScrollRegion defined. Cannot be larger than parent ScrollZone');
return;
}
this.currentRegion = new ScrollRegion(x, y, width, height, speedX, speedY);
this.regions.push(this.currentRegion);
return this.currentRegion;
}
public setSpeed(x: number, y: number) {
if (this.currentRegion)
{
this.currentRegion.scrollSpeed.setTo(x, y);
}
return this;
}
public update() {
for (var i = 0; i < this.regions.length; i++)
{
this.regions[i].update(this._game.time.delta);
}
}
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.intersects(this.bounds, this.bounds.length);
}
}
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
// Render checks
if (this.visible == false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1 || this.cameraBlacklist.indexOf(camera.ID) !== -1 || this.inCamera(camera.worldView) == false)
{
return false;
}
// Alpha
if (this.alpha !== 1)
{
var globalAlpha = this._game.stage.context.globalAlpha;
this._game.stage.context.globalAlpha = this.alpha;
}
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
// Apply camera difference
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{
this._dx -= (camera.worldView.x * this.scrollFactor.x);
this._dy -= (camera.worldView.y * this.scrollFactor.y);
}
// Rotation - needs to work from origin point really, but for now from center
if (this.angle !== 0 || this.flipped == true)
{
this._game.stage.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
if (this.angle !== 0)
{
this._game.stage.context.rotate(this.angle * (Math.PI / 180));
}
this._dx = -(this._dw / 2);
this._dy = -(this._dh / 2);
if (this.flipped == true)
{
this._game.stage.context.scale(-1, 1);
}
}
this._dx = Math.round(this._dx);
this._dy = Math.round(this._dy);
this._dw = Math.round(this._dw);
this._dh = Math.round(this._dh);
for (var i = 0; i < this.regions.length; i++)
{
if (this._dynamicTexture)
{
this.regions[i].render(this._game.stage.context, this._dynamicTexture.canvas, this._dx, this._dy, this._dw, this._dh);
}
else
{
this.regions[i].render(this._game.stage.context, this._texture, this._dx, this._dy, this._dw, this._dh);
}
}
if (globalAlpha > -1)
{
this._game.stage.context.globalAlpha = globalAlpha;
}
return true;
}
private createRepeatingTexture(regionWidth: number, regionHeight: number) {
// Work out how many we'll need of the source image to make it tile properly
var tileWidth = Math.ceil(this._texture.width / regionWidth) * regionWidth;
var tileHeight = Math.ceil(this._texture.height / regionHeight) * regionHeight;
this._dynamicTexture = new DynamicTexture(this._game, tileWidth, tileHeight);
this._dynamicTexture.context.rect(0, 0, tileWidth, tileHeight);
this._dynamicTexture.context.fillStyle = this._dynamicTexture.context.createPattern(this._texture, "repeat");
this._dynamicTexture.context.fill();
}
}
}
+351
View File
@@ -0,0 +1,351 @@
/// <reference path="../Game.ts" />
/// <reference path="../AnimationManager.ts" />
/// <reference path="GameObject.ts" />
/// <reference path="../system/Camera.ts" />
/**
* Phaser - Sprite
*
* The Sprite GameObject is an extension of the core GameObject that includes support for animation and dynamic textures.
* It's probably the most used GameObject of all.
*/
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 AnimationManager(this._game, this);
if (key !== null)
{
this.loadGraphic(key);
}
else
{
this.bounds.width = 16;
this.bounds.height = 16;
}
}
private _texture;
private _dynamicTexture: bool = false;
// 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 animations: AnimationManager;
public renderDebug: bool = false;
public renderDebugColor: string = 'rgba(0,255,0,0.5)';
public renderDebugPointColor: string = 'rgba(255,255,255,1)';
public flipped: bool = false;
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.intersects(this.bounds, this.bounds.length);
}
}
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.cameraBlacklist.indexOf(camera.ID) !== -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._sx = 0;
this._sy = 0;
this._sw = this.bounds.width;
this._sh = this.bounds.height;
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y);
this._dw = this.bounds.width * this.scale.x;
this._dh = this.bounds.height * this.scale.y;
if (this.align == GameObject.ALIGN_TOP_CENTER)
{
this._dx -= this.bounds.halfWidth * this.scale.x;
}
else if (this.align == GameObject.ALIGN_TOP_RIGHT)
{
this._dx -= this.bounds.width * this.scale.x;
}
else if (this.align == GameObject.ALIGN_CENTER_LEFT)
{
this._dy -= this.bounds.halfHeight * this.scale.y;
}
else if (this.align == GameObject.ALIGN_CENTER)
{
this._dx -= this.bounds.halfWidth * this.scale.x;
this._dy -= this.bounds.halfHeight * this.scale.y;
}
else if (this.align == GameObject.ALIGN_CENTER_RIGHT)
{
this._dx -= this.bounds.width * this.scale.x;
this._dy -= this.bounds.halfHeight * this.scale.y;
}
else if (this.align == GameObject.ALIGN_BOTTOM_LEFT)
{
this._dy -= this.bounds.height * this.scale.y;
}
else if (this.align == GameObject.ALIGN_BOTTOM_CENTER)
{
this._dx -= this.bounds.halfWidth * this.scale.x;
this._dy -= this.bounds.height * this.scale.y;
}
else if (this.align == GameObject.ALIGN_BOTTOM_RIGHT)
{
this._dx -= this.bounds.width * this.scale.x;
this._dy -= 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 - needs to work from origin point really, but for now from center
if (this.angle !== 0 || this.rotationOffset !== 0 || this.flipped == true)
{
this._game.stage.context.save();
this._game.stage.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
if (this.renderRotation == true && (this.angle !== 0 || this.rotationOffset !== 0))
{
this._game.stage.context.rotate((this.rotationOffset + this.angle) * (Math.PI / 180));
}
this._dx = -(this._dw / 2);
this._dy = -(this._dh / 2);
if (this.flipped == true)
{
this._game.stage.context.scale(-1, 1);
}
}
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);
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.flipped === true || this.rotation !== 0 || this.rotationOffset !== 0)
{
//this._game.stage.context.translate(0, 0);
this._game.stage.context.restore();
}
if (this.renderDebug)
{
this.renderBounds(camera, cameraOffsetX, cameraOffsetY);
}
if (globalAlpha > -1)
{
this._game.stage.context.globalAlpha = globalAlpha;
}
return true;
}
// Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
private renderBounds(camera:Camera, cameraOffsetX:number, cameraOffsetY:number) {
this._dx = cameraOffsetX + (this.bounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.bounds.topLeft.y - camera.worldView.y);
this._game.stage.context.fillStyle = this.renderDebugColor;
this._game.stage.context.fillRect(this._dx, this._dy, this._dw, this._dh);
this._game.stage.context.fillStyle = this.renderDebugPointColor;
var hw = this.bounds.halfWidth * this.scale.x;
var hh = this.bounds.halfHeight * this.scale.y;
var sw = (this.bounds.width * this.scale.x) - 1;
var sh = (this.bounds.height * this.scale.y) - 1;
this._game.stage.context.fillRect(this._dx, this._dy, 1, 1); // top left
this._game.stage.context.fillRect(this._dx + hw, this._dy, 1, 1); // top center
this._game.stage.context.fillRect(this._dx + sw, this._dy, 1, 1); // top right
this._game.stage.context.fillRect(this._dx, this._dy + hh, 1, 1); // left center
this._game.stage.context.fillRect(this._dx + hw, this._dy + hh, 1, 1); // center
this._game.stage.context.fillRect(this._dx + sw, this._dy + hh, 1, 1); // right center
this._game.stage.context.fillRect(this._dx, this._dy + sh, 1, 1); // bottom left
this._game.stage.context.fillRect(this._dx + hw, this._dy + sh, 1, 1); // bottom center
this._game.stage.context.fillRect(this._dx + sw, this._dy + sh, 1, 1); // bottom right
}
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);
}
}
}
+265
View File
@@ -0,0 +1,265 @@
/// <reference path="../Game.ts" />
/// <reference path="GameObject.ts" />
/// <reference path="../system/TilemapLayer.ts" />
/// <reference path="../system/Tile.ts" />
/**
* Phaser - Tilemap
*
* This GameObject allows for the display of a tilemap within the game world. Tile maps consist of an image, tile data and a size.
* Internally it creates a TilemapLayer for each layer in the tilemap.
*/
module Phaser {
export class Tilemap extends GameObject {
constructor(game: Game, key: string, mapData: string, format: number, resizeWorld: bool = true, tileWidth?: number = 0, tileHeight?: number = 0) {
super(game);
this.isGroup = false;
this.tiles = [];
this.layers = [];
this.mapFormat = format;
switch (format)
{
case Tilemap.FORMAT_CSV:
this.parseCSV(game.cache.getText(mapData), key, tileWidth, tileHeight);
break;
case Tilemap.FORMAT_TILED_JSON:
this.parseTiledJSON(game.cache.getText(mapData), key);
break;
}
if (this.currentLayer && resizeWorld)
{
this._game.world.setSize(this.currentLayer.widthInPixels, this.currentLayer.heightInPixels, true);
}
}
public static FORMAT_CSV: number = 0;
public static FORMAT_TILED_JSON: number = 1;
public tiles : Tile[];
public layers : TilemapLayer[];
public currentLayer: TilemapLayer;
public collisionLayer: TilemapLayer;
public mapFormat: number;
public update() {
}
public render(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
if (this.cameraBlacklist.indexOf(camera.ID) == -1)
{
// Loop through the layers
for (var i = 0; i < this.layers.length; i++)
{
this.layers[i].render(camera, cameraOffsetX, cameraOffsetY);
}
}
}
private parseCSV(data: string, key: string, tileWidth: number, tileHeight: number) {
var layer: TilemapLayer = new TilemapLayer(this._game, this, key, Tilemap.FORMAT_CSV, 'TileLayerCSV' + this.layers.length.toString(), tileWidth, tileHeight);
// Trim any rogue whitespace from the data
data = data.trim();
var rows = data.split("\n");
for (var i = 0; i < rows.length; i++)
{
var column = rows[i].split(",");
if (column.length > 0)
{
layer.addColumn(column);
}
}
layer.updateBounds();
var tileQuantity = layer.parseTileOffsets();
this.currentLayer = layer;
this.collisionLayer = layer;
this.layers.push(layer);
this.generateTiles(tileQuantity);
}
private parseTiledJSON(data: string, key: string) {
// Trim any rogue whitespace from the data
data = data.trim();
var json = JSON.parse(data);
for (var i = 0; i < json.layers.length; i++)
{
var layer: TilemapLayer = new TilemapLayer(this._game, this, key, Tilemap.FORMAT_TILED_JSON, json.layers[i].name, json.tilewidth, json.tileheight);
layer.alpha = json.layers[i].opacity;
layer.visible = json.layers[i].visible;
layer.tileMargin = json.tilesets[0].margin;
layer.tileSpacing = json.tilesets[0].spacing;
var c = 0;
var row;
for (var t = 0; t < json.layers[i].data.length; t++)
{
if (c == 0)
{
row = [];
}
row.push(json.layers[i].data[t]);
c++;
if (c == json.layers[i].width)
{
layer.addColumn(row);
c = 0;
}
}
layer.updateBounds();
var tileQuantity = layer.parseTileOffsets();
this.currentLayer = layer;
this.collisionLayer = layer;
this.layers.push(layer);
}
this.generateTiles(tileQuantity);
}
private generateTiles(qty:number) {
for (var i = 0; i < qty; i++)
{
this.tiles.push(new Tile(this._game, this, i, this.currentLayer.tileWidth, this.currentLayer.tileHeight));
}
}
public get widthInPixels(): number {
return this.currentLayer.widthInPixels;
}
public get heightInPixels(): number {
return this.currentLayer.heightInPixels;
}
// Tile Collision
public setCollisionRange(start: number, end: number, collision?:number = Collision.ANY, resetCollisions: bool = false) {
for (var i = start; i < end; i++)
{
this.tiles[i].setCollision(collision, resetCollisions);
}
}
public setCollisionByIndex(values:number[], collision?:number = Collision.ANY, resetCollisions: bool = false) {
for (var i = 0; i < values.length; i++)
{
this.tiles[values[i]].setCollision(collision, resetCollisions);
}
}
// Tile Management
public getTile(x: number, y: number, layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileIndex(x, y)];
}
public getTileFromWorldXY(x: number, y: number, layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileFromWorldXY(x, y)];
}
public getTileFromInputXY(layer?: number = 0):Tile {
return this.tiles[this.layers[layer].getTileFromWorldXY(this._game.input.worldX, this._game.input.worldY)];
}
public getTileOverlaps(object: GameObject) {
return this.currentLayer.getTileOverlaps(object);
}
// COLLIDE
public collide(objectOrGroup = null, callback = null): bool {
if (objectOrGroup == null)
{
objectOrGroup = this._game.world.group;
}
// Group?
if (objectOrGroup.isGroup == false)
{
return this.collideGameObject(objectOrGroup);
}
else
{
objectOrGroup.forEachAlive(this, this.collideGameObject, true);
}
return true;
}
public collideGameObject(object: GameObject): bool {
if (object == this) { return false; }
if (object.immovable == false && object.exists == true && object.allowCollisions != Collision.NONE)
{
return this.collisionLayer.getTileOverlaps(object);
}
else
{
return false;
}
}
// Set current layer
// Set layer order?
// Get block of tiles
// Swap tiles around
// Delete tiles of certain type
// Erase tiles
}
}
@@ -1,4 +1,4 @@
/// <reference path="../_definitions.ts" /> /// <reference path="../Game.ts" />
/** /**
* Phaser - Circle * Phaser - Circle
@@ -14,9 +14,8 @@ 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. * 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 * @class Circle
* @constructor * @constructor
* @param {Number} [x] The x coordinate of the center of the circle. * @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} y The y coordinate of the center of the circle.
* @param {Number} [diameter] The diameter of the circle.
* @return {Circle} This circle object * @return {Circle} This circle object
**/ **/
constructor(x: number = 0, y: number = 0, diameter: number = 0) { constructor(x: number = 0, y: number = 0, diameter: number = 0) {
@@ -48,7 +47,9 @@ module Phaser {
* @return {Number} * @return {Number}
**/ **/
get diameter(): number { get diameter(): number {
return this._diameter; return this._diameter;
} }
/** /**
@@ -72,7 +73,9 @@ module Phaser {
* @return {Number} * @return {Number}
**/ **/
get radius(): number { get radius(): number {
return this._radius; return this._radius;
} }
/** /**
@@ -95,8 +98,10 @@ module Phaser {
* @method circumference * @method circumference
* @return {Number} * @return {Number}
**/ **/
circumference(): number { public circumference(): number {
return 2 * (Math.PI * this._radius); return 2 * (Math.PI * this._radius);
} }
/** /**
@@ -105,7 +110,9 @@ module Phaser {
* @return {Number} * @return {Number}
**/ **/
get bottom(): number { get bottom(): number {
return this.y + this._radius; return this.y + this._radius;
} }
/** /**
@@ -115,14 +122,18 @@ module Phaser {
**/ **/
set bottom(value: number) { set bottom(value: number) {
if (value < this.y) if (!isNaN(value))
{ {
this._radius = 0; if (value < this.y)
this._diameter = 0; {
} this._radius = 0;
else this._diameter = 0;
{ }
this.radius = value - this.y; else
{
this.radius = value - this.y;
}
} }
} }
@@ -133,7 +144,9 @@ module Phaser {
* @return {Number} The x coordinate of the leftmost point of the circle. * @return {Number} The x coordinate of the leftmost point of the circle.
**/ **/
get left(): number { get left(): number {
return this.x - this._radius; return this.x - this._radius;
} }
/** /**
@@ -143,14 +156,17 @@ module Phaser {
**/ **/
set left(value: number) { set left(value: number) {
if (value > this.x) if (!isNaN(value))
{ {
this._radius = 0; if (value < this.x)
this._diameter = 0; {
} this.radius = this.x - value;
else }
{ else
this.radius = this.x - value; {
this._radius = 0;
this._diameter = 0;
}
} }
} }
@@ -161,7 +177,9 @@ module Phaser {
* @return {Number} * @return {Number}
**/ **/
get right(): number { get right(): number {
return this.x + this._radius; return this.x + this._radius;
} }
/** /**
@@ -171,14 +189,17 @@ module Phaser {
**/ **/
set right(value: number) { set right(value: number) {
if (value < this.x) if (!isNaN(value))
{ {
this._radius = 0; if (value > this.x)
this._diameter = 0; {
} this.radius = value - this.x;
else }
{ else
this.radius = value - this.x; {
this._radius = 0;
this._diameter = 0;
}
} }
} }
@@ -189,7 +210,9 @@ module Phaser {
* @return {Number} * @return {Number}
**/ **/
get top(): number { get top(): number {
return this.y - this._radius; return this.y - this._radius;
} }
/** /**
@@ -199,14 +222,17 @@ module Phaser {
**/ **/
set top(value: number) { set top(value: number) {
if (value > this.y) if (!isNaN(value))
{ {
this._radius = 0; if (value > this.y)
this._diameter = 0; {
} this._radius = 0;
else this._diameter = 0;
{ }
this.radius = this.y - value; else
{
this.radius = this.y - value;
}
} }
} }
@@ -229,6 +255,219 @@ module Phaser {
} }
/**
* 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 {
if (this._diameter <= 0)
{
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
{
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 {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)
{
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;
}
/**
* 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. * Sets the members of Circle to the specified values.
* @method setTo * @method setTo
@@ -248,67 +487,15 @@ module Phaser {
} }
/**
* Copies the x, y and diameter properties from any given object to this Circle.
* @method copyFrom
* @param {any} source - The object to copy from.
* @return {Circle} This Circle object.
**/
public copyFrom(source: any): Circle {
return this.setTo(source.x, source.y, source.diameter);
}
/**
* Determines whether or not this Circle object is empty.
* @method empty
* @return {bool} A value of true if the Circle objects diameter is less than or equal to 0; otherwise false.
**/
get empty(): bool {
return (this._diameter == 0);
}
/**
* Sets all of the Circle objects properties to 0. A Circle object is empty if its diameter is less than or equal to 0.
* @method setEmpty
* @return {Circle} This Circle object
**/
set empty(value: bool) {
this.setTo(0, 0, 0);
}
/**
* 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 {
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);
}
/** /**
* Returns a string representation of this object. * Returns a string representation of this object.
* @method toString * @method toString
* @return {string} a string representation of the instance. * @return {string} a string representation of the instance.
**/ **/
public toString(): string { public toString(): string {
return "[{Circle (x=" + this.x + " y=" + this.y + " diameter=" + this.diameter + " radius=" + this.radius + ")}]"; return "[{Circle (x=" + this.x + " y=" + this.y + " diameter=" + this.diameter + " radius=" + this.radius + ")}]";
} }
} }
+96
View File
@@ -0,0 +1,96 @@
/// <reference path="../Game.ts" />
/**
* Phaser - IntersectResult
*
* A light-weight result object to hold the results of an intersection. For when you need more than just true/false.
*/
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;
}
}
}
@@ -1,4 +1,4 @@
/// <reference path="../_definitions.ts" /> /// <reference path="../Game.ts" />
/** /**
* Phaser - Line * Phaser - Line
@@ -28,28 +28,28 @@ module Phaser {
/** /**
* *
* @property x1 * @property x1
* @type {Number} * @type Number
*/ */
public x1: number = 0; public x1: number = 0;
/** /**
* *
* @property y1 * @property y1
* @type {Number} * @type Number
*/ */
public y1: number = 0; public y1: number = 0;
/** /**
* *
* @property x2 * @property x2
* @type {Number} * @type Number
*/ */
public x2: number = 0; public x2: number = 0;
/** /**
* *
* @property y2 * @property y2
* @type {Number} * @type Number
*/ */
public y2: number = 0; public y2: number = 0;
@@ -59,7 +59,7 @@ module Phaser {
* @param {Phaser.Line} [output] * @param {Phaser.Line} [output]
* @return {Phaser.Line} * @return {Phaser.Line}
*/ */
public clone(output: Line = new Line): Line { public clone(output?: Line = new Line): Line {
return output.setTo(this.x1, this.y1, this.x2, this.y2); return output.setTo(this.x1, this.y1, this.x2, this.y2);
@@ -193,7 +193,7 @@ module Phaser {
* @method isPointOnLine * @method isPointOnLine
* @param {Number} x * @param {Number} x
* @param {Number} y * @param {Number} y
* @return {bool} * @return {Boolean}
*/ */
public isPointOnLine(x: number, y: number): bool { public isPointOnLine(x: number, y: number): bool {
@@ -213,7 +213,7 @@ module Phaser {
* @method isPointOnLineSegment * @method isPointOnLineSegment
* @param {Number} x * @param {Number} x
* @param {Number} y * @param {Number} y
* @return {bool} * @return {Boolean}
*/ */
public isPointOnLineSegment(x: number, y: number): bool { public isPointOnLineSegment(x: number, y: number): bool {
@@ -239,7 +239,7 @@ module Phaser {
* @param {Any} line * @param {Any} line
* @return {Any} * @return {Any}
*/ */
public intersectLineLine(line) { public intersectLineLine(line): any {
//return Phaser.intersectLineLine(this,line); //return Phaser.intersectLineLine(this,line);
} }
@@ -251,8 +251,7 @@ module Phaser {
* @param {Phaser.Line} [output] * @param {Phaser.Line} [output]
* @return {Phaser.Line} * @return {Phaser.Line}
*/ */
/* public perp(x: number, y: number, output?: Line): Line {
public perp(x: number, y: number, output: Line): Line {
if (this.y1 === this.y2) if (this.y1 === this.y2)
{ {
@@ -268,7 +267,7 @@ module Phaser {
var yInt: number = (y - this.perpSlope * x); var yInt: number = (y - this.perpSlope * x);
var pt = this.intersectLineLine({ x1: x, y1: y, x2: 0, y2: yInt }); var pt: any = this.intersectLineLine({ x1: x, y1: y, x2: 0, y2: yInt });
if (output) if (output)
{ {
@@ -280,7 +279,6 @@ module Phaser {
} }
} }
*/
/* /*
intersectLineCircle (circle:Circle) intersectLineCircle (circle:Circle)
+170
View File
@@ -0,0 +1,170 @@
/// <reference path="../Game.ts" />
/**
* Phaser - MicroPoint
*
* The MicroPoint object represents a location in a two-dimensional coordinate system,
* where x represents the horizontal axis and y represents the vertical axis.
* It is different to the Point class in that it doesn't contain any of the help methods like add/substract/distanceTo, etc.
* Use a MicroPoint when all you literally need is a solid container for x and y (such as in the Rectangle class).
*/
module Phaser {
export class MicroPoint {
/**
* Creates a new point. If you pass no parameters to this method, a point is created at (0,0).
* @class MicroPoint
* @constructor
* @param {Number} x The horizontal position of this point (default 0)
* @param {Number} y The vertical position of this point (default 0)
**/
constructor(x: number = 0, y: number = 0, parent?:any = null) {
this._x = x;
this._y = y;
this.parent = parent;
}
private _x: number;
private _y: number;
public parent: any;
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
**/
public get x(): number {
return this._x;
}
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
**/
public get y(): number {
return this._y;
}
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
**/
public set x(value: number) {
this._x = value;
if (this.parent)
{
this.parent.updateBounds();
}
}
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
**/
public set y(value:number) {
this._y = value;
if (this.parent)
{
this.parent.updateBounds();
}
}
/**
* Copies the x and y values from any given object to this MicroPoint.
* @method copyFrom
* @param {any} source - The object to copy from.
* @return {MicroPoint} This MicroPoint object. Useful for chaining method calls.
**/
public copyFrom(source: any): MicroPoint {
return this.setTo(source.x, source.y);
}
/**
* Copies the x and y values from this MicroPoint to any given object.
* @method copyTo
* @param {any} target - The object to copy to.
* @return {any} The target object.
**/
public copyTo(target: any): MicroPoint {
target.x = this._x;
target.y = this._y;
return target;
}
/**
* Sets the x and y values of this MicroPoint object to the given coordinates.
* @method setTo
* @param {Number} x - The horizontal position of this point.
* @param {Number} y - The vertical position of this point.
* @return {MicroPoint} This MicroPoint object. Useful for chaining method calls.
**/
public setTo(x: number, y: number, callParent?:bool = true): MicroPoint {
this._x = x;
this._y = y;
if (this.parent != null && callParent == true)
{
this.parent.updateBounds();
}
return this;
}
/**
* Determines whether this MicroPoint object and the given object are equal. They are equal if they have the same x and y values.
* @method equals
* @param {any} point - The object to compare against. Must have x and y properties.
* @return {Boolean} A value of true if the object is equal to this MicroPoin object; false if it is not equal.
**/
public equals(toCompare): bool {
if (this._x === toCompare.x && this._y === toCompare.y)
{
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 '[{MicroPoint (x=' + this._x + ' y=' + this._y + ')}]';
}
}
}
+341
View File
@@ -0,0 +1,341 @@
/// <reference path="../Game.ts" />
/**
* Phaser - Point
*
* The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis.
*/
module Phaser {
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 The horizontal position of this point (default 0)
* @param {Number} y The vertical position of this point (default 0)
**/
constructor(x: number = 0, y: number = 0) {
this.setTo(x, y);
}
/**
* 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 setTo
* @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 + ')}]';
}
}
}
+106
View File
@@ -0,0 +1,106 @@
/// <reference path="../Game.ts" />
/**
* Phaser - Quad
*
* A Quad object is an area defined by its position, as indicated by its top-left corner (x,y) and width and height.
* Very much like a Rectangle only without all of the additional methods and properties of that class.
*/
module Phaser {
export class Quad {
/**
* Creates a new Quad object with the top-left corner specified by the x and y parameters and with the specified width and height parameters. If you call this function without parameters, a rectangle with x, y, width, and height properties set to 0 is created.
* @class Quad
* @constructor
* @param {Number} x The x coordinate of the top-left corner of the quad.
* @param {Number} y The y coordinate of the top-left corner of the quad.
* @param {Number} width The width of the quad.
* @param {Number} height The height of the quad.
* @return {Quad } This object
**/
constructor(x: number = 0, y: number = 0, width: number = 0, height: number = 0) {
this.setTo(x, y, width, height);
}
public x: number;
public y: number;
public width: number;
public height: number;
/**
* Sets the Quad to the specified size.
* @method setTo
* @param {Number} x The x coordinate of the top-left corner of the quad.
* @param {Number} y The y coordinate of the top-left corner of the quad.
* @param {Number} width The width of the quad.
* @param {Number} height The height of the quad.
* @return {Quad} This object
**/
public setTo(x: number, y: number, width: number, height: number): Quad {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
return this;
}
public get left(): number {
return this.x;
}
public get right(): number {
return this.x + this.width;
}
public get top(): number {
return this.y;
}
public get bottom(): number {
return this.y + this.height;
}
public get halfWidth(): number {
return this.width / 2;
}
public get halfHeight(): number {
return this.height / 2;
}
/**
* Determines whether the object specified intersects (overlaps) with this Quad object.
* This method checks the x, y, width, and height properties of the specified Quad object to see if it intersects with this Quad object.
* @method intersects
* @param {Object} q The object to check for intersection with this Quad. Must have left/right/top/bottom properties (Rectangle, Quad).
* @param {Number} t A tolerance value to allow for an intersection test with padding, default to 0
* @return {Boolean} A value of true if the specified object intersects with this Quad; otherwise false.
**/
public intersects(q, t?: number = 0): bool {
return !(q.left > this.right + t || q.right < this.left - t || q.top > this.bottom + t || q.bottom < this.top - t);
}
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the object.
**/
public toString(): string {
return "[{Quad (x=" + this.x + " y=" + this.y + " width=" + this.width + " height=" + this.height + ")}]";
}
}
}
+810
View File
@@ -0,0 +1,810 @@
/// <reference path="../Game.ts" />
/// <reference path="MicroPoint.ts" />
/**
* Phaser - Rectangle
*
* A Rectangle object is an area defined by its position, as indicated by its top-left corner (x,y) and width and height.
*/
module Phaser {
export class Rectangle {
/**
* Creates a new Rectangle object with the top-left corner specified by the x and y parameters and with the specified width and height parameters.
* If you call this function without parameters, a rectangle with x, y, width, and height properties set to 0 is created.
* @class Rectangle
* @constructor
* @param {Number} x The x coordinate of the top-left corner of the rectangle.
* @param {Number} y The y coordinate of the top-left corner of the rectangle.
* @param {Number} width The width of the rectangle.
* @param {Number} height The height of the rectangle.
* @return {Rectangle} This rectangle object
**/
constructor(x: number = 0, y: number = 0, width: number = 0, height: number = 0) {
this._width = width;
if (width > 0)
{
this._halfWidth = Math.round(width / 2);
}
this._height = height;
if (height > 0)
{
this._halfHeight = Math.round(height / 2);
}
this.length = Math.max(this._width, this._height);
this.topLeft = new MicroPoint(x, y, this);
this.topCenter = new MicroPoint(x + this._halfWidth, y, this);
this.topRight = new MicroPoint(x + this._width - 1, y, this);
this.leftCenter = new MicroPoint(x, y + this._halfHeight, this);
this.center = new MicroPoint(x + this._halfWidth, y + this._halfHeight, this);
this.rightCenter = new MicroPoint(x + this._width - 1, y + this._halfHeight, this);
this.bottomLeft = new MicroPoint(x, y + this._height - 1, this);
this.bottomCenter = new MicroPoint(x + this._halfWidth, y + this._height - 1, this);
this.bottomRight = new MicroPoint(x + this._width - 1, y + this._height - 1, this);
}
private _tempX: number = null;
private _tempY: number = null;
private _tempWidth: number = null;
private _tempHeight: number = null;
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
**/
public get x(): number {
return this.topLeft.x;
}
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
**/
public get y(): number {
return this.topLeft.y;
}
/**
* The x coordinate of the top-left corner of the rectangle
* @property x
* @type Number
**/
public set x(value: number) {
this.topLeft.x = value;
}
/**
* The y coordinate of the top-left corner of the rectangle
* @property y
* @type Number
**/
public set y(value:number) {
this.topLeft.y = value;
}
/**
* The x and y coordinate of the top-left corner of the rectangle (same as x/y)
* @property topLeft
* @type MicroPoint
**/
public topLeft: MicroPoint;
/**
* The x and y coordinate of the top-center of the rectangle
* @property topCenter
* @type MicroPoint
**/
public topCenter: MicroPoint;
/**
* The x and y coordinate of the top-right corner of the rectangle
* @property topRight
* @type MicroPoint
**/
public topRight: MicroPoint;
/**
* The x and y coordinate of the left-center of the rectangle
* @property leftCenter
* @type MicroPoint
**/
public leftCenter: MicroPoint;
/**
* The x and y coordinate of the center of the rectangle
* @property center
* @type MicroPoint
**/
public center: MicroPoint;
/**
* The x and y coordinate of the right-center of the rectangle
* @property rightCenter
* @type MicroPoint
**/
public rightCenter: MicroPoint;
/**
* The x and y coordinate of the bottom-left corner of the rectangle
* @property bottomLeft
* @type MicroPoint
**/
public bottomLeft: MicroPoint;
/**
* The x and y coordinate of the bottom-center of the rectangle
* @property bottomCenter
* @type MicroPoint
**/
public bottomCenter: MicroPoint;
/**
* The x and y coordinate of the bottom-right corner of the rectangle
* @property bottomRight
* @type MicroPoint
**/
public bottomRight: MicroPoint;
/**
* The width of the rectangle
* @property width
* @type Number
**/
private _width: number = 0;
/**
* The height of the rectangle
* @property height
* @type Number
**/
private _height: number = 0;
/**
* Half of the width of the rectangle
* @property halfWidth
* @type Number
**/
private _halfWidth: number = 0;
/**
* Half of the height of the rectangle
* @property halfHeight
* @type Number
**/
private _halfHeight: number = 0;
/**
* The size of the longest side (width or height)
* @property length
* @type Number
**/
public length: number = 0;
/**
* Updates all of the MicroPoints based on the values of width and height.
* You should not normally call this directly.
**/
public updateBounds() {
if (this._tempWidth !== null)
{
this._width = this._tempWidth;
this._halfWidth = 0;
if (this._width > 0)
{
this._halfWidth = Math.round(this._width / 2);
}
}
if (this._tempHeight !== null)
{
this._height = this._tempHeight;
this._halfHeight = 0;
if (this._height > 0)
{
this._halfHeight = Math.round(this._height / 2);
}
}
this.length = Math.max(this._width, this._height);
if (this._tempX !== null && this._tempY !== null)
{
this.topLeft.setTo(this._tempX, this._tempY, false);
}
else if (this._tempX !== null && this._tempY == null)
{
this.topLeft.setTo(this._tempX, this.topLeft.y, false);
}
else if (this._tempX == null && this._tempY !== null)
{
this.topLeft.setTo(this.topLeft.x, this._tempY, false);
}
else
{
this.topLeft.setTo(this.x, this.y, false);
}
this.topCenter.setTo(this.x + this._halfWidth, this.y, false);
this.topRight.setTo(this.x + this._width - 1, this.y, false);
this.leftCenter.setTo(this.x, this.y + this._halfHeight, false);
this.center.setTo(this.x + this._halfWidth, this.y + this._halfHeight, false);
this.rightCenter.setTo(this.x + this._width - 1, this.y + this._halfHeight, false);
this.bottomLeft.setTo(this.x, this.y + this._height - 1, false);
this.bottomCenter.setTo(this.x + this._halfWidth, this.y + this._height - 1, false);
this.bottomRight.setTo(this.x + this._width - 1, this.y + this._height - 1, false);
this._tempX = null;
this._tempY = null;
this._tempWidth = null;
this._tempHeight = null;
}
/**
* The width of the rectangle
* @property width
* @type Number
**/
public set width(value: number) {
this._width = value;
this._halfWidth = Math.round(value / 2);
this.updateBounds();
}
/**
* The height of the rectangle
* @property height
* @type Number
**/
public set height(value: number) {
this._height = value;
this._halfHeight = Math.round(value / 2);
this.updateBounds();
}
/**
* The width of the rectangle
* @property width
* @type Number
**/
public get width(): number {
return this._width;
}
/**
* The height of the rectangle
* @property height
* @type Number
**/
public get height(): number {
return this._height;
}
/**
* Half of the width of the rectangle
* @property halfWidth
* @type Number
**/
public get halfWidth(): number {
return this._halfWidth;
}
/**
* Half of the height of the rectangle
* @property halfHeight
* @type Number
**/
public get halfHeight(): number {
return this._halfHeight;
}
/**
* The sum of the y and height properties.
* Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property.
* @method bottom
* @return {Number}
**/
public get bottom(): number {
return this.bottomCenter.y;
}
/**
* The sum of the y and height properties.
* Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property.
* @method bottom
* @param {Number} value
**/
public set bottom(value: number) {
if (value < this.y)
{
this._tempHeight = 0;
}
else
{
this._tempHeight = this.y + value;
}
this.updateBounds();
}
/**
* The x coordinate of the top-left corner of the rectangle.
* Changing the left property of a Rectangle object has no effect on the y and height properties.
* However it does affect the width property, whereas changing the x value does not affect the width property.
* @method left
* @ return {number}
**/
public get left(): number {
return this.x;
}
/**
* The x coordinate of the top-left corner of the rectangle.
* Changing the left property of a Rectangle object has no effect on the y and height properties.
* However it does affect the width property, whereas changing the x value does not affect the width property.
* @method left
* @param {Number} value
**/
public set left(value: number) {
var diff = this.x - value;
if (this._width + diff < 0)
{
this._tempWidth = 0;
this._tempX = value;
}
else
{
this._tempWidth = this._width + diff;
this._tempX = value;
}
this.updateBounds();
}
/**
* The sum of the x and width properties.
* Changing the right property of a Rectangle object has no effect on the x, y and height properties.
* However it does affect the width property.
* @method right
* @return {Number}
**/
public get right(): number {
return this.rightCenter.x;
}
/**
* The sum of the x and width properties.
* Changing the right property of a Rectangle object has no effect on the x, y and height properties.
* However it does affect the width property.
* @method right
* @param {Number} value
**/
public set right(value: number) {
if (value < this.topLeft.x)
{
this._tempWidth = 0;
}
else
{
this._tempWidth = (value - this.topLeft.x);
}
this.updateBounds();
}
/**
* The size of the Rectangle object, expressed as a Point object with the values of the width and height properties.
* @method size
* @param {Point} output Optional Point object. If given the values will be set into the object, otherwise a brand new Point object will be created and returned.
* @return {Point} The size of the Rectangle object
**/
public size(output?: Point = new Point): Point {
return output.setTo(this._width, this._height);
}
/**
* The volume of the Rectangle object in pixels, derived from width * height
* @method volume
* @return {Number}
**/
public get volume(): number {
return this._width * this._height;
}
/**
* The perimeter size of the Rectangle object in pixels. This is the sum of all 4 sides.
* @method perimeter
* @return {Number}
**/
public get perimeter(): number {
return (this._width * 2) + (this._height * 2);
}
/**
* The y coordinate of the top-left corner of the rectangle.
* Changing the top property of a Rectangle object has no effect on the x and width properties.
* However it does affect the height property, whereas changing the y value does not affect the height property.
* @method top
* @return {Number}
**/
public get top(): number {
return this.topCenter.y;
}
/**
* The y coordinate of the top-left corner of the rectangle.
* Changing the top property of a Rectangle object has no effect on the x and width properties.
* However it does affect the height property, whereas changing the y value does not affect the height property.
* @method top
* @param {Number} value
**/
public set top(value: number) {
var diff = this.topCenter.y - value;
if (this._height + diff < 0)
{
this._tempHeight = 0;
this._tempY = value;
}
else
{
this._tempHeight = this._height + diff;
this._tempY = value;
}
this.updateBounds();
}
/**
* Returns a new Rectangle object with the same values for the x, y, width, and height properties as the original Rectangle object.
* @method clone
* @param {Rectangle} output Optional Rectangle object. If given the values will be set into the object, otherwise a brand new Rectangle object will be created and returned.
* @return {Rectangle}
**/
public clone(output?: Rectangle = new Rectangle): Rectangle {
return output.setTo(this.x, this.y, this.width, this.height);
}
/**
* Determines whether the specified coordinates are contained within the region defined by this Rectangle object.
* @method contains
* @param {Number} x The x coordinate of the point to test.
* @param {Number} y The y coordinate of the point to test.
* @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false.
**/
public contains(x: number, y: number): bool {
if (x >= this.topLeft.x && x <= this.topRight.x && y >= this.topLeft.y && y <= this.bottomRight.y)
{
return true;
}
return false;
}
/**
* Determines whether the specified point is contained within the rectangular region defined by this Rectangle object.
* This method is similar to the Rectangle.contains() method, except that it takes a Point object as a parameter.
* @method containsPoint
* @param {Point} point The point object being checked. Can be Point or any object with .x and .y values.
* @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false.
**/
public containsPoint(point: any): bool {
return this.contains(point.x, point.y);
}
/**
* Determines whether the Rectangle object specified by the rect parameter is contained within this Rectangle object.
* A Rectangle object is said to contain another if the second Rectangle object falls entirely within the boundaries of the first.
* @method containsRect
* @param {Rectangle} rect The rectangle object being checked.
* @return {Boolean} A value of true if the Rectangle object contains the specified point; otherwise false.
**/
public containsRect(rect: Rectangle): bool {
// If the given rect has a larger volume than this one then it can never contain it
if (rect.volume > this.volume)
{
return false;
}
if (rect.x >= this.topLeft.x && rect.y >= this.topLeft.y && rect.rightCenter.x <= this.rightCenter.x && rect.bottomCenter.y <= this.bottomCenter.y)
{
return true;
}
return false;
}
/**
* Copies all of rectangle data from the source Rectangle object into the calling Rectangle object.
* @method copyFrom
* @param {Rectangle} rect The source rectangle object to copy from
* @return {Rectangle} This rectangle object
**/
public copyFrom(source: Rectangle): Rectangle {
return this.setTo(source.x, source.y, source.width, source.height);
}
/**
* Copies all the rectangle data from this Rectangle object into the destination Rectangle object.
* @method copyTo
* @param {Rectangle} rect The destination rectangle object to copy in to
* @return {Rectangle} The destination rectangle object
**/
public copyTo(target: Rectangle): Rectangle {
return target.copyFrom(this);
}
/**
* Determines whether the object specified in the toCompare parameter is equal to this Rectangle object.
* This method compares the x, y, width, and height properties of an object against the same properties of this Rectangle object.
* @method equals
* @param {Rectangle} toCompare The rectangle to compare to this Rectangle object.
* @return {Boolean} A value of true if the object has exactly the same values for the x, y, width, and height properties as this Rectangle object; otherwise false.
**/
public equals(toCompare: Rectangle): bool {
if (this.topLeft.equals(toCompare.topLeft) && this.bottomRight.equals(toCompare.bottomRight))
{
return true;
}
return false;
}
/**
* Increases the size of the Rectangle object by the specified amounts.
* The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value,
* and to the top and the bottom by the dy value.
* @method inflate
* @param {Number} dx The amount to be added to the left side of this Rectangle.
* @param {Number} dy The amount to be added to the bottom side of this Rectangle.
* @return {Rectangle} This Rectangle object.
**/
public inflate(dx: number, dy: number): Rectangle {
this._tempX = this.topLeft.x - dx;
this._tempWidth = this._width + (2 * dx);
this._tempY = this.topLeft.y - dy;
this._tempHeight = this._height + (2 * dy);
this.updateBounds();
return this;
}
/**
* Increases the size of the Rectangle object.
* This method is similar to the Rectangle.inflate() method except it takes a Point object as a parameter.
* @method inflatePoint
* @param {Point} point The x property of this Point object is used to increase the horizontal dimension of the Rectangle object. The y property is used to increase the vertical dimension of the Rectangle object.
* @return {Rectangle} This Rectangle object.
**/
public inflatePoint(point: Point): Rectangle {
return this.inflate(point.x, point.y);
}
/**
* If the Rectangle object specified in the toIntersect parameter intersects with this Rectangle object,
* returns the area of intersection as a Rectangle object. If the rectangles do not intersect, this method
* returns an empty Rectangle object with its properties set to 0.
* @method intersection
* @param {Rectangle} toIntersect The Rectangle object to compare against to see if it intersects with this Rectangle object.
* @param {Rectangle} output Optional Rectangle object. If given the intersection values will be set into this object, otherwise a brand new Rectangle object will be created and returned.
* @return {Rectangle} A Rectangle object that equals the area of intersection. If the rectangles do not intersect, this method returns an empty Rectangle object; that is, a rectangle with its x, y, width, and height properties set to 0.
**/
public intersection(toIntersect: Rectangle, output?: Rectangle = new Rectangle): Rectangle {
if (this.intersects(toIntersect) === true)
{
output.x = Math.max(toIntersect.topLeft.x, this.topLeft.x);
output.y = Math.max(toIntersect.topLeft.y, this.topLeft.y);
output.width = Math.min(toIntersect.rightCenter.x, this.rightCenter.x) - output.x;
output.height = Math.min(toIntersect.bottomCenter.y, this.bottomCenter.y) - output.y;
}
return output;
}
/**
* Determines whether the object specified intersects (overlaps) with this Rectangle object.
* This method checks the x, y, width, and height properties of the specified Rectangle object to see if it intersects with this Rectangle object.
* @method intersects
* @param {Rectangle} r2 The Rectangle object to compare against to see if it intersects with this Rectangle object.
* @param {Number} t A tolerance value to allow for an intersection test with padding, default to 0
* @return {Boolean} A value of true if the specified object intersects with this Rectangle object; otherwise false.
**/
public intersects(r2: Rectangle, t?: number = 0): bool {
return !(r2.left > this.right + t || r2.right < this.left - t || r2.top > this.bottom + t || r2.bottom < this.top - t);
}
/**
* Determines whether or not this Rectangle object is empty.
* @method isEmpty
* @return {Boolean} A value of true if the Rectangle object's width or height is less than or equal to 0; otherwise false.
**/
public get isEmpty(): bool {
if (this.width < 1 || this.height < 1)
{
return true;
}
return false;
}
/**
* Adjusts the location of the Rectangle object, as determined by its top-left corner, by the specified amounts.
* @method offset
* @param {Number} dx Moves the x value of the Rectangle object by this amount.
* @param {Number} dy Moves the y value of the Rectangle object by this amount.
* @return {Rectangle} This Rectangle object.
**/
public offset(dx: number, dy: number): Rectangle {
if (!isNaN(dx) && !isNaN(dy))
{
this.x += dx;
this.y += dy;
}
return this;
}
/**
* Adjusts the location of the Rectangle object using a Point object as a parameter. This method is similar to the Rectangle.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 Rectangle object.
* @return {Rectangle} This Rectangle object.
**/
public offsetPoint(point: Point): Rectangle {
return this.offset(point.x, point.y);
}
/**
* Sets all of the Rectangle object's properties to 0. A Rectangle object is empty if its width or height is less than or equal to 0.
* @method setEmpty
* @return {Rectangle} This rectangle object
**/
public setEmpty() {
return this.setTo(0, 0, 0, 0);
}
/**
* Sets the members of Rectangle to the specified values.
* @method setTo
* @param {Number} x The x coordinate of the top-left corner of the rectangle.
* @param {Number} y The y coordinate of the top-left corner of the rectangle.
* @param {Number} width The width of the rectangle in pixels.
* @param {Number} height The height of the rectangle in pixels.
* @return {Rectangle} This rectangle object
**/
public setTo(x: number, y: number, width: number, height: number): Rectangle {
this._tempX = x;
this._tempY = y;
this._tempWidth = width;
this._tempHeight = height;
this.updateBounds();
return this;
}
/**
* Adds two rectangles together to create a new Rectangle object, by filling in the horizontal and vertical space between the two rectangles.
* @method union
* @param {Rectangle} toUnion A Rectangle object to add to this Rectangle object.
* @param {Rectangle} output Optional Rectangle object. If given the new values will be set into this object, otherwise a brand new Rectangle object will be created and returned.
* @return {Rectangle} A Rectangle object that is the union of the two rectangles.
**/
public union(toUnion: Rectangle, output?: Rectangle = new Rectangle): Rectangle {
return output.setTo(
Math.min(toUnion.x, this.x),
Math.min(toUnion.y, this.y),
Math.max(toUnion.right, this.right),
Math.max(toUnion.bottom, this.bottom)
);
}
/**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the instance.
**/
public toString(): string {
return "[{Rectangle (x=" + this.x + " y=" + this.y + " width=" + this.width + " height=" + this.height + " empty=" + this.isEmpty + ")}]";
}
}
}
+3
View File
@@ -0,0 +1,3 @@
node_modules
.npm-debug.log
tmp
+5
View File
@@ -0,0 +1,5 @@
language: node_js
node_js:
- 0.8
before_script:
- npm install -g grunt-cli
+4
View File
@@ -0,0 +1,4 @@
"Cowboy" Ben Alman (http://benalman.com/)
Kyle Robinson Young (http://dontkry.com/)
Tyler Kellen (http://goingslowly.com)
Sindre Sorhus (http://sindresorhus.com)
+23
View File
@@ -0,0 +1,23 @@
v0.4.1:
date: 2013-03-13
changes:
- Fix path.join thrown errors with expandMapping rename. Closes gh-725.
- Update copyright date to 2013. Closes gh-660.
- Remove some side effects from manually requiring Grunt. Closes gh-605.
- grunt.log: add formatting support and implicitly cast msg to a string. Closes gh-703.
- Update js-yaml to version 2. Closes gh-683.
- The grunt.util.spawn method now falls back to stdout when the `grunt` option is set. Closes gh-691.
- Making --verbose "Files:" warnings less scary. Closes gh-657.
- Fixing typo: the grunt.fatal method now defaults to FATAL_ERROR. Closes gh-656, gh-707.
- Removed a duplicate line. Closes gh-702.
- Gruntfile name should no longer be case sensitive. Closes gh-685.
- The grunt.file.delete method warns and returns false if file doesn't exist. Closes gh-635, gh-714.
- The grunt.package property is now resolved via require(). Closes gh-704.
- The grunt.util.spawn method no longer breaks on multibyte stdio. Closes gh-710.
- Fix "path.join arguments must be strings" error in file.expand/recurse when options.cwd is not set. Closes gh-722.
- Adding a fairly relevant keyword to package.json (task).
v0.4.0:
date: 2013-02-18
changes:
- Initial release of 0.4.0.
- See http://gruntjs.com/upgrading-from-0.3-to-0.4 for a list of changes / migration guide.
+1
View File
@@ -0,0 +1 @@
Please see the [Contributing to grunt](http://gruntjs.com/contributing) guide for information on contributing to this project.
@@ -1,4 +1,4 @@
Copyright (c) 2012-13 Terry Weiss. All rights reserved. Copyright (c) 2013 "Cowboy" Ben Alman
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation obtaining a copy of this software and associated documentation
+13
View File
@@ -0,0 +1,13 @@
# Grunt: The JavaScript Task Runner [![Build Status](https://secure.travis-ci.org/gruntjs/grunt.png?branch=master)](http://travis-ci.org/gruntjs/grunt)
### Documentation
Visit the [gruntjs.com](http://gruntjs.com/) website for all the things.
### Support / Contributing
Before you make an issue, please read our [Contributing](http://gruntjs.com/contributing) guide.
You can find the grunt team in [#grunt on irc.freenode.net](irc://irc.freenode.net/#grunt).
### Release History
See the [CHANGELOG](CHANGELOG).
+1
View File
@@ -0,0 +1 @@
Visit the [gruntjs.com](http://gruntjs.com/) website for all the things.
+1
View File
@@ -0,0 +1 @@
../coffee-script/bin/cake
+1
View File
@@ -0,0 +1 @@
../coffee-script/bin/coffee
+1
View File
@@ -0,0 +1 @@
../js-yaml/bin/js-yaml.js
+1
View File
@@ -0,0 +1 @@
../lodash/build.js
+1
View File
@@ -0,0 +1 @@
../nopt/bin/nopt.js
+1
View File
@@ -0,0 +1 @@
../which/bin/which
@@ -0,0 +1,9 @@
[submodule "deps/nodeunit"]
path = deps/nodeunit
url = git://github.com/caolan/nodeunit.git
[submodule "deps/UglifyJS"]
path = deps/UglifyJS
url = https://github.com/mishoo/UglifyJS.git
[submodule "deps/nodelint"]
path = deps/nodelint
url = https://github.com/tav/nodelint.git
+4
View File
@@ -0,0 +1,4 @@
deps
dist
test
nodelint.cfg
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2010 Caolan McMahon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+25
View File
@@ -0,0 +1,25 @@
PACKAGE = asyncjs
NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node)
CWD := $(shell pwd)
NODEUNIT = $(CWD)/node_modules/nodeunit/bin/nodeunit
UGLIFY = $(CWD)/node_modules/uglify-js/bin/uglifyjs
NODELINT = $(CWD)/node_modules/nodelint/nodelint
BUILDDIR = dist
all: clean test build
build: $(wildcard lib/*.js)
mkdir -p $(BUILDDIR)
$(UGLIFY) lib/async.js > $(BUILDDIR)/async.min.js
test:
$(NODEUNIT) test
clean:
rm -rf $(BUILDDIR)
lint:
$(NODELINT) --config nodelint.cfg lib/async.js
.PHONY: test build all
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
*.coffee
*.html
.DS_Store
.git*
Cakefile
documentation/
examples/
extras/coffee-script.js
raw/
src/
test/
+1
View File
@@ -0,0 +1 @@
coffeescript.org
+22
View File
@@ -0,0 +1,22 @@
Copyright (c) 2009-2012 Jeremy Ashkenas
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
+51
View File
@@ -0,0 +1,51 @@
{
} } {
{ { } }
} }{ {
{ }{ } } _____ __ __
( }{ }{ { ) / ____| / _|/ _|
.- { { } { }} -. | | ___ | |_| |_ ___ ___
( ( } { } { } } ) | | / _ \| _| _/ _ \/ _ \
|`-..________ ..-'| | |___| (_) | | | || __/ __/
| | \_____\___/|_| |_| \___|\___|
| ;--.
| (__ \ _____ _ _
| | ) ) / ____| (_) | |
| |/ / | (___ ___ _ __ _ _ __ | |_
| ( / \___ \ / __| '__| | '_ \| __|
| |/ ____) | (__| | | | |_) | |_
| | |_____/ \___|_| |_| .__/ \__|
`-.._________..-' | |
|_|
CoffeeScript is a little language that compiles into JavaScript.
Install Node.js, and then the CoffeeScript compiler:
sudo bin/cake install
Or, if you have the Node Package Manager installed:
npm install -g coffee-script
(Leave off the -g if you don't wish to install globally.)
Execute a script:
coffee /path/to/script.coffee
Compile a script:
coffee -c /path/to/script.coffee
For documentation, usage, and examples, see:
http://coffeescript.org/
To suggest a feature, report a bug, or general discussion:
http://github.com/jashkenas/coffee-script/issues/
If you'd like to chat, drop by #coffeescript on Freenode IRC,
or on webchat.freenode.net.
The source repository:
git://github.com/jashkenas/coffee-script.git
All contributors are listed here:
http://github.com/jashkenas/coffee-script/contributors
+78
View File
@@ -0,0 +1,78 @@
require 'rubygems'
require 'erb'
require 'fileutils'
require 'rake/testtask'
require 'json'
desc "Build the documentation page"
task :doc do
source = 'documentation/index.html.erb'
child = fork { exec "bin/coffee -bcw -o documentation/js documentation/coffee/*.coffee" }
at_exit { Process.kill("INT", child) }
Signal.trap("INT") { exit }
loop do
mtime = File.stat(source).mtime
if !@mtime || mtime > @mtime
rendered = ERB.new(File.read(source)).result(binding)
File.open('index.html', 'w+') {|f| f.write(rendered) }
end
@mtime = mtime
sleep 1
end
end
desc "Build coffee-script-source gem"
task :gem do
require 'rubygems'
require 'rubygems/package'
gemspec = Gem::Specification.new do |s|
s.name = 'coffee-script-source'
s.version = JSON.parse(File.read('package.json'))["version"]
s.date = Time.now.strftime("%Y-%m-%d")
s.homepage = "http://jashkenas.github.com/coffee-script/"
s.summary = "The CoffeeScript Compiler"
s.description = <<-EOS
CoffeeScript is a little language that compiles into JavaScript.
Underneath all of those embarrassing braces and semicolons,
JavaScript has always had a gorgeous object model at its heart.
CoffeeScript is an attempt to expose the good parts of JavaScript
in a simple way.
EOS
s.files = [
'lib/coffee_script/coffee-script.js',
'lib/coffee_script/source.rb'
]
s.authors = ['Jeremy Ashkenas']
s.email = 'jashkenas@gmail.com'
s.rubyforge_project = 'coffee-script-source'
end
file = File.open("coffee-script-source.gem", "w")
Gem::Package.open(file, 'w') do |pkg|
pkg.metadata = gemspec.to_yaml
path = "lib/coffee_script/source.rb"
contents = <<-ERUBY
module CoffeeScript
module Source
def self.bundled_path
File.expand_path("../coffee-script.js", __FILE__)
end
end
end
ERUBY
pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
tar_io.write(contents)
end
contents = File.read("extras/coffee-script.js")
path = "lib/coffee_script/coffee-script.js"
pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
tar_io.write(contents)
end
end
end
+44
View File
@@ -0,0 +1,44 @@
# JavaScriptLint configuration file for CoffeeScript.
+no_return_value # function {0} does not always return a value
+duplicate_formal # duplicate formal argument {0}
-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
+var_hides_arg # variable {0} hides argument
+redeclared_var # redeclaration of {0} {1}
-anon_no_return_value # anonymous function does not always return a value
+missing_semicolon # missing semicolon
+meaningless_block # meaningless block; curly braces have no impact
-comma_separated_stmts # multiple statements separated by commas (use semicolons?)
+unreachable_code # unreachable code
+missing_break # missing break statement
-missing_break_for_last_case # missing break statement for last case in switch
-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
-useless_void # use of the void type may be unnecessary (void is always undefined)
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
+use_of_label # use of label
-block_without_braces # block statement without curly braces
+leading_decimal_point # leading decimal point may indicate a number or an object member
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
+octal_number # leading zeros make an octal number
+nested_comment # nested comment
+misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
+empty_statement # empty statement or extra semicolon
-missing_option_explicit # the "option explicit" control comment is missing
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
+dup_option_explicit # duplicate "option explicit" control comment
+useless_assign # useless assignment
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
-missing_default_case # missing default case in switch statement
+duplicate_case_in_switch # duplicate case in switch statements
+default_not_at_end # the default case is not at the end of the switch statement
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
+useless_comparison # useless comparison; comparing identical expressions
+with_statement # with statement hides undeclared variables; use temporary variable instead
+trailing_comma_in_array # extra comma is not recommended in array initializers
+assign_to_function_call # assignment to a function call
+parseint_missing_radix # parseInt missing radix parameter
+lambda_assign_requires_semicolon
+49
View File
@@ -0,0 +1,49 @@
{
"name": "coffee-script",
"description": "Unfancy JavaScript",
"keywords": [
"javascript",
"language",
"coffeescript",
"compiler"
],
"author": {
"name": "Jeremy Ashkenas"
},
"version": "1.3.3",
"licenses": [
{
"type": "MIT",
"url": "https://raw.github.com/jashkenas/coffee-script/master/LICENSE"
}
],
"engines": {
"node": ">=0.4.0"
},
"directories": {
"lib": "./lib/coffee-script"
},
"main": "./lib/coffee-script/coffee-script",
"bin": {
"coffee": "./bin/coffee",
"cake": "./bin/cake"
},
"homepage": "http://coffeescript.org",
"bugs": "https://github.com/jashkenas/coffee-script/issues",
"repository": {
"type": "git",
"url": "git://github.com/jashkenas/coffee-script.git"
},
"devDependencies": {
"uglify-js": ">=1.0.0",
"jison": ">=0.2.0"
},
"readme": "\n {\n } } {\n { { } }\n } }{ {\n { }{ } } _____ __ __\n ( }{ }{ { ) / ____| / _|/ _|\n .- { { } { }} -. | | ___ | |_| |_ ___ ___\n ( ( } { } { } } ) | | / _ \\| _| _/ _ \\/ _ \\\n |`-..________ ..-'| | |___| (_) | | | || __/ __/\n | | \\_____\\___/|_| |_| \\___|\\___|\n | ;--.\n | (__ \\ _____ _ _\n | | ) ) / ____| (_) | |\n | |/ / | (___ ___ _ __ _ _ __ | |_\n | ( / \\___ \\ / __| '__| | '_ \\| __|\n | |/ ____) | (__| | | | |_) | |_\n | | |_____/ \\___|_| |_| .__/ \\__|\n `-.._________..-' | |\n |_|\n\n\n CoffeeScript is a little language that compiles into JavaScript.\n\n Install Node.js, and then the CoffeeScript compiler:\n sudo bin/cake install\n\n Or, if you have the Node Package Manager installed:\n npm install -g coffee-script\n (Leave off the -g if you don't wish to install globally.)\n\n Execute a script:\n coffee /path/to/script.coffee\n\n Compile a script:\n coffee -c /path/to/script.coffee\n\n For documentation, usage, and examples, see:\n http://coffeescript.org/\n\n To suggest a feature, report a bug, or general discussion:\n http://github.com/jashkenas/coffee-script/issues/\n\n If you'd like to chat, drop by #coffeescript on Freenode IRC,\n or on webchat.freenode.net.\n\n The source repository:\n git://github.com/jashkenas/coffee-script.git\n\n All contributors are listed here:\n http://github.com/jashkenas/coffee-script/contributors\n",
"readmeFilename": "README",
"_id": "coffee-script@1.3.3",
"dist": {
"shasum": "d41e076292bcf98fbb2753e76e1a07a8be5db9b7"
},
"_from": "coffee-script@~1.3.3",
"_resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz"
}
+22
View File
@@ -0,0 +1,22 @@
Copyright (c) 2010
Marak Squires
Alexis Sellier (cloudhead)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+77
View File
@@ -0,0 +1,77 @@
# colors.js - get color and style in your node.js console ( and browser ) like what
<img src="http://i.imgur.com/goJdO.png" border = "0"/>
## Installation
npm install colors
## colors and styles!
- bold
- italic
- underline
- inverse
- yellow
- cyan
- white
- magenta
- green
- red
- grey
- blue
- rainbow
- zebra
- random
## Usage
``` js
var colors = require('./colors');
console.log('hello'.green); // outputs green text
console.log('i like cake and pies'.underline.red) // outputs red underlined text
console.log('inverse the color'.inverse); // inverses the color
console.log('OMG Rainbows!'.rainbow); // rainbow (ignores spaces)
```
# Creating Custom themes
```js
var require('colors');
colors.setTheme({
silly: 'rainbow',
input: 'grey',
verbose: 'cyan',
prompt: 'grey',
info: 'green',
data: 'grey',
help: 'cyan',
warn: 'yellow',
debug: 'blue',
error: 'red'
});
// outputs red text
console.log("this is an error".error);
// outputs yellow text
console.log("this is a warning".warn);
```
### Contributors
Marak (Marak Squires)
Alexis Sellier (cloudhead)
mmalecki (Maciej Małecki)
nicoreed (Nico Reed)
morganrallen (Morgan Allen)
JustinCampbell (Justin Campbell)
ded (Dustin Diaz)
#### , Marak Squires , Justin Campbell, Dustin Diaz (@ded)
+74
View File
@@ -0,0 +1,74 @@
<!DOCTYPE HTML>
<html lang="en-us">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Colors Example</title>
<script src="colors.js"></script>
</head>
<body>
<script>
var test = colors.red("hopefully colorless output");
document.write('Rainbows are fun!'.rainbow + '<br/>');
document.write('So '.italic + 'are'.underline + ' styles! '.bold + 'inverse'.inverse); // styles not widely supported
document.write('Chains are also cool.'.bold.italic.underline.red); // styles not widely supported
//document.write('zalgo time!'.zalgo);
document.write(test.stripColors);
document.write("a".grey + " b".black);
document.write("Zebras are so fun!".zebra);
document.write(colors.rainbow('Rainbows are fun!'));
document.write(colors.italic('So ') + colors.underline('are') + colors.bold(' styles! ') + colors.inverse('inverse')); // styles not widely supported
document.write(colors.bold(colors.italic(colors.underline(colors.red('Chains are also cool.'))))); // styles not widely supported
//document.write(colors.zalgo('zalgo time!'));
document.write(colors.stripColors(test));
document.write(colors.grey("a") + colors.black(" b"));
colors.addSequencer("america", function(letter, i, exploded) {
if(letter === " ") return letter;
switch(i%3) {
case 0: return letter.red;
case 1: return letter.white;
case 2: return letter.blue;
}
});
colors.addSequencer("random", (function() {
var available = ['bold', 'underline', 'italic', 'inverse', 'grey', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta'];
return function(letter, i, exploded) {
return letter === " " ? letter : letter[available[Math.round(Math.random() * (available.length - 1))]];
};
})());
document.write("AMERICA! F--K YEAH!".america);
document.write("So apparently I've been to Mars, with all the little green men. But you know, I don't recall.".random);
//
// Custom themes
//
colors.setTheme({
silly: 'rainbow',
input: 'grey',
verbose: 'cyan',
prompt: 'grey',
info: 'green',
data: 'grey',
help: 'cyan',
warn: 'yellow',
debug: 'blue',
error: 'red'
});
// outputs red text
document.write("this is an error".error);
// outputs yellow text
document.write("this is a warning".warn);
</script>
</body>
</html>
+24
View File
@@ -0,0 +1,24 @@
{
"name": "colors",
"description": "get colors in your node.js console like what",
"version": "0.6.0-1",
"author": {
"name": "Marak Squires"
},
"repository": {
"type": "git",
"url": "http://github.com/Marak/colors.js.git"
},
"engines": {
"node": ">=0.1.90"
},
"main": "colors",
"readme": "# colors.js - get color and style in your node.js console ( and browser ) like what\n\n<img src=\"http://i.imgur.com/goJdO.png\" border = \"0\"/>\n\n\n## Installation\n\n npm install colors\n\n## colors and styles!\n\n- bold\n- italic\n- underline\n- inverse\n- yellow\n- cyan\n- white\n- magenta\n- green\n- red\n- grey\n- blue\n- rainbow\n- zebra\n- random\n\n## Usage\n\n``` js\nvar colors = require('./colors');\n\nconsole.log('hello'.green); // outputs green text\nconsole.log('i like cake and pies'.underline.red) // outputs red underlined text\nconsole.log('inverse the color'.inverse); // inverses the color\nconsole.log('OMG Rainbows!'.rainbow); // rainbow (ignores spaces)\n```\n\n# Creating Custom themes\n\n```js\n\nvar require('colors');\n\ncolors.setTheme({\n silly: 'rainbow',\n input: 'grey',\n verbose: 'cyan',\n prompt: 'grey',\n info: 'green',\n data: 'grey',\n help: 'cyan',\n warn: 'yellow',\n debug: 'blue',\n error: 'red'\n});\n\n// outputs red text\nconsole.log(\"this is an error\".error);\n\n// outputs yellow text\nconsole.log(\"this is a warning\".warn);\n```\n\n\n### Contributors \n\nMarak (Marak Squires)\nAlexis Sellier (cloudhead)\nmmalecki (Maciej Małecki)\nnicoreed (Nico Reed)\nmorganrallen (Morgan Allen)\nJustinCampbell (Justin Campbell)\nded (Dustin Diaz)\n\n\n#### , Marak Squires , Justin Campbell, Dustin Diaz (@ded)\n",
"readmeFilename": "ReadMe.md",
"_id": "colors@0.6.0-1",
"dist": {
"shasum": "322d52c6f629babb21b1713e6365d1b6ec1937bd"
},
"_from": "colors@~0.6.0-1",
"_resolved": "https://registry.npmjs.org/colors/-/colors-0.6.0-1.tgz"
}
+67
View File
@@ -0,0 +1,67 @@
# node-dateformat
A node.js package for Steven Levithan's excellent [dateFormat()][dateformat] function.
## Modifications
* Removed the `Date.prototype.format` method. Sorry folks, but extending native prototypes is for suckers.
* Added a `module.exports = dateFormat;` statement at the bottom
## Usage
As taken from Steven's post, modified to match the Modifications listed above:
var dateFormat = require('dateformat');
var now = new Date();
// Basic usage
dateFormat(now, "dddd, mmmm dS, yyyy, h:MM:ss TT");
// Saturday, June 9th, 2007, 5:46:21 PM
// You can use one of several named masks
dateFormat(now, "isoDateTime");
// 2007-06-09T17:46:21
// ...Or add your own
dateFormat.masks.hammerTime = 'HH:MM! "Can\'t touch this!"';
dateFormat(now, "hammerTime");
// 17:46! Can't touch this!
// When using the standalone dateFormat function,
// you can also provide the date as a string
dateFormat("Jun 9 2007", "fullDate");
// Saturday, June 9, 2007
// Note that if you don't include the mask argument,
// dateFormat.masks.default is used
dateFormat(now);
// Sat Jun 09 2007 17:46:21
// And if you don't include the date argument,
// the current date and time is used
dateFormat();
// Sat Jun 09 2007 17:46:22
// You can also skip the date argument (as long as your mask doesn't
// contain any numbers), in which case the current date/time is used
dateFormat("longTime");
// 5:46:22 PM EST
// And finally, you can convert local time to UTC time. Simply pass in
// true as an additional argument (no argument skipping allowed in this case):
dateFormat(now, "longTime", true);
// 10:46:21 PM UTC
// ...Or add the prefix "UTC:" to your mask.
dateFormat(now, "UTC:h:MM:ss TT Z");
// 10:46:21 PM UTC
// You can also get the ISO 8601 week of the year:
dateFormat(now, "W");
// 42
## License
(c) 2007-2009 Steven Levithan [stevenlevithan.com][stevenlevithan], MIT license.
[dateformat]: http://blog.stevenlevithan.com/archives/date-time-format
[stevenlevithan]: http://stevenlevithan.com/
+24
View File
@@ -0,0 +1,24 @@
{
"name": "dateformat",
"description": "A node.js package for Steven Levithan's excellent dateFormat() function.",
"maintainers": "Felix Geisendörfer <felix@debuggable.com>",
"homepage": "https://github.com/felixge/node-dateformat",
"author": {
"name": "Steven Levithan"
},
"version": "1.0.2-1.2.3",
"main": "./lib/dateformat",
"dependencies": {},
"devDependencies": {},
"engines": {
"node": "*"
},
"readme": "# node-dateformat\n\nA node.js package for Steven Levithan's excellent [dateFormat()][dateformat] function.\n\n## Modifications\n\n* Removed the `Date.prototype.format` method. Sorry folks, but extending native prototypes is for suckers.\n* Added a `module.exports = dateFormat;` statement at the bottom\n\n## Usage\n\nAs taken from Steven's post, modified to match the Modifications listed above:\n\n var dateFormat = require('dateformat');\n var now = new Date();\n\n // Basic usage\n dateFormat(now, \"dddd, mmmm dS, yyyy, h:MM:ss TT\");\n // Saturday, June 9th, 2007, 5:46:21 PM\n\n // You can use one of several named masks\n dateFormat(now, \"isoDateTime\");\n // 2007-06-09T17:46:21\n\n // ...Or add your own\n dateFormat.masks.hammerTime = 'HH:MM! \"Can\\'t touch this!\"';\n dateFormat(now, \"hammerTime\");\n // 17:46! Can't touch this!\n\n // When using the standalone dateFormat function,\n // you can also provide the date as a string\n dateFormat(\"Jun 9 2007\", \"fullDate\");\n // Saturday, June 9, 2007\n\n // Note that if you don't include the mask argument,\n // dateFormat.masks.default is used\n dateFormat(now);\n // Sat Jun 09 2007 17:46:21\n\n // And if you don't include the date argument,\n // the current date and time is used\n dateFormat();\n // Sat Jun 09 2007 17:46:22\n\n // You can also skip the date argument (as long as your mask doesn't\n // contain any numbers), in which case the current date/time is used\n dateFormat(\"longTime\");\n // 5:46:22 PM EST\n\n // And finally, you can convert local time to UTC time. Simply pass in\n // true as an additional argument (no argument skipping allowed in this case):\n dateFormat(now, \"longTime\", true);\n // 10:46:21 PM UTC\n\n // ...Or add the prefix \"UTC:\" to your mask.\n dateFormat(now, \"UTC:h:MM:ss TT Z\");\n // 10:46:21 PM UTC\n\n // You can also get the ISO 8601 week of the year:\n dateFormat(now, \"W\");\n // 42\n## License\n\n(c) 2007-2009 Steven Levithan [stevenlevithan.com][stevenlevithan], MIT license.\n\n[dateformat]: http://blog.stevenlevithan.com/archives/date-time-format\n[stevenlevithan]: http://stevenlevithan.com/\n",
"readmeFilename": "Readme.md",
"_id": "dateformat@1.0.2-1.2.3",
"dist": {
"shasum": "692290ea53102d50a82968882eab448a048a7f23"
},
"_from": "dateformat@1.0.2-1.2.3",
"_resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz"
}
@@ -0,0 +1,27 @@
#!/bin/bash
# this just takes php's date() function as a reference to check if week of year
# is calculated correctly in the range from 1970 .. 2038 by brute force...
SEQ="seq"
SYSTEM=`uname`
if [ "$SYSTEM" = "Darwin" ]; then
SEQ="jot"
fi
for YEAR in {1970..2038}; do
for MONTH in {1..12}; do
DAYS=$(cal $MONTH $YEAR | egrep "28|29|30|31" |tail -1 |awk '{print $NF}')
for DAY in $( $SEQ $DAYS ); do
DATE=$YEAR-$MONTH-$DAY
echo -n $DATE ...
NODEVAL=$(node test_weekofyear.js $DATE)
PHPVAL=$(php -r "echo intval(date('W', strtotime('$DATE')));")
if [ "$NODEVAL" -ne "$PHPVAL" ]; then
echo "MISMATCH: node: $NODEVAL vs php: $PHPVAL for date $DATE"
else
echo " OK"
fi
done
done
done
+13
View File
@@ -0,0 +1,13 @@
#ignore these files
*.swp
*~
*.lock
*.DS_Store
node_modules
npm-debug.log
*.out
*.o
*.tmp
+212
View File
@@ -0,0 +1,212 @@
# EventEmitter2
EventEmitter2 is a an implementation of the EventEmitter found in Node.js
## Features
- Namespaces/Wildcards.
- Times To Listen (TTL), extends the `once` concept with `many`.
- Browser environment compatibility.
- Demonstrates good performance in benchmarks
```
EventEmitterHeatUp x 3,728,965 ops/sec \302\2610.68% (60 runs sampled)
EventEmitter x 2,822,904 ops/sec \302\2610.74% (63 runs sampled)
EventEmitter2 x 7,251,227 ops/sec \302\2610.55% (58 runs sampled)
EventEmitter2 (wild) x 3,220,268 ops/sec \302\2610.44% (65 runs sampled)
Fastest is EventEmitter2
```
## Differences (Non breaking, compatible with existing EventEmitter)
- The constructor takes a configuration object.
```javascript
var EventEmitter2 = require('eventemitter2').EventEmitter2;
var server = new EventEmitter2({
wildcard: true, // should the event emitter use wildcards.
delimiter: '::', // the delimiter used to segment namespaces, defaults to `.`.
newListener: false, // if you want to emit the newListener event set to true.
maxListeners: 20, // the max number of listeners that can be assigned to an event, defaults to 10.
});
```
- Getting the actual event that fired.
```javascript
server.on('foo.*', function(value1, value2) {
console.log(this.event, value1, value2);
});
```
- Fire an event N times and then remove it, an extension of the `once` concept.
```javascript
server.many('foo', 4, function() {
console.log('hello');
});
```
- Pass in a namespaced event as an array rather than a delimited string.
```javascript
server.many(['foo', 'bar', 'bazz'], function() {
console.log('hello');
});
```
## API
When an `EventEmitter` instance experiences an error, the typical action is
to emit an `error` event. Error events are treated as a special case.
If there is no listener for it, then the default action is to print a stack
trace and exit the program.
All EventEmitters emit the event `newListener` when new listeners are
added.
**Namespaces** with **Wildcards**
To use namespaces/wildcards, pass the `wildcard` option into the EventEmitter constructor.
When namespaces/wildcards are enabled, events can either be strings (`foo.bar`) separated
by a delimiter or arrays (`['foo', 'bar']`). The delimiter is also configurable as a
constructor option.
An event name passed to any event emitter method can contain a wild card (the `*` character).
If the event name is a string, a wildcard may appear as `foo.*`. If the event name is an array,
the wildcard may appear as `['foo', '*']`.
If either of the above described events were passed to the `on` method, subsequent emits such
as the following would be observed...
```javascript
emitter.emit('foo.bazz');
emitter.emit(['foo', 'bar']);
```
#### emitter.addListener(event, listener)
#### emitter.on(event, listener)
Adds a listener to the end of the listeners array for the specified event.
```javascript
server.on('data', function(value1, value2, value3 /* accepts any number of expected values... */) {
console.log('The event was raised!');
});
```
```javascript
server.on('data', function(value) {
console.log('The event was raised!');
});
```
#### emitter.onAny(listener)
Adds a listener that will be fired when any event is emitted.
```javascript
server.onAny(function(value) {
console.log('All events trigger this.');
});
```
#### emitter.offAny(listener)
Removes the listener that will be fired when any event is emitted.
```javascript
server.offAny(function(value) {
console.log('The event was raised!');
});
```
#### emitter.once(event, listener)
Adds a **one time** listener for the event. The listener is invoked only the first time the event is fired, after which it is removed.
```javascript
server.once('get', function (value) {
console.log('Ah, we have our first value!');
});
```
#### emitter.many(event, timesToListen, listener)
Adds a listener that will execute **n times** for the event before being removed. The listener is invoked only the first time the event is fired, after which it is removed.
```javascript
server.many('get', 4, function (value) {
console.log('This event will be listened to exactly four times.');
});
```
#### emitter.removeListener(event, listener)
#### emitter.off(event, listener)
Remove a listener from the listener array for the specified event. **Caution**: changes array indices in the listener array behind the listener.
```javascript
var callback = function(value) {
console.log('someone connected!');
};
server.on('get', callback);
// ...
server.removeListener('get', callback);
```
#### emitter.removeAllListeners([event])
Removes all listeners, or those of the specified event.
#### emitter.setMaxListeners(n)
By default EventEmitters will print a warning if more than 10 listeners are added to it. This is a useful default which helps finding memory leaks. Obviously not all Emitters should be limited to 10. This function allows that to be increased. Set to zero for unlimited.
#### emitter.listeners(event)
Returns an array of listeners for the specified event. This array can be manipulated, e.g. to remove listeners.
```javascript
server.on('get', function(value) {
console.log('someone connected!');
});
console.log(console.log(server.listeners('get')); // [ [Function] ]
```
#### emitter.listenersAny()
Returns an array of listeners that are listening for any event that is specified. This array can be manipulated, e.g. to remove listeners.
```javascript
server.onAny(function(value) {
console.log('someone connected!');
});
console.log(console.log(server.listenersAny()[0]); // [ [Function] ] // someone connected!
```
#### emitter.emit(event, [arg1], [arg2], [...])
Execute each of the listeners that may be listening for the specified event name in order with the list of arguments.
## Test coverage
There is a test suite that tries to cover each use case, it can be found <a href="https://github.com/hij1nx/EventEmitter2/tree/master/test">here</a>.
## Licence
(The MIT License)
Copyright (c) 2011 hij1nx <http://www.twitter.com/hij1nx>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
File diff suppressed because one or more lines are too long
+16
View File
@@ -0,0 +1,16 @@
{
"loopfunc": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"latedef": true,
"newcap": true,
"noarg": true,
"sub": true,
"undef": true,
"unused": true,
"boss": true,
"eqnull": true,
"node": true,
"es5": true
}
+22
View File
@@ -0,0 +1,22 @@
Copyright (c) 2013 "Cowboy" Ben Alman
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
+44
View File
@@ -0,0 +1,44 @@
# findup-sync
Find the first file matching a given pattern in the current directory or the nearest ancestor directory.
## Getting Started
Install the module with: `npm install findup-sync`
```js
var findup = require('findup-sync');
// Start looking in the CWD.
var filepath1 = findup('{a,b}*.txt');
// Start looking somewhere else, and ignore case (probably a good idea).
var filepath2 = findup('{a,b}*.txt', {cwd: '/some/path', nocase: true});
```
## Usage
```js
findup(patternOrPatterns [, minimatchOptions])
```
### patternOrPatterns
Type: `String` or `Array`
Default: none
One or more wildcard glob patterns. Or just filenames.
### minimatchOptions
Type: `Object`
Default: `{}`
Options to be passed to [minimatch](https://github.com/isaacs/minimatch).
Note that if you want to start in a different directory than the current working directory, specify a `cwd` property here.
## Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).
## Release History
2013-03-08 - v0.1.2 - Updated dependencies. Fixed a Node 0.9.x bug. Updated unit tests to work cross-platform.
2012-11-15 - v0.1.1 - Now works without an options object.
2012-11-01 - v0.1.0 - Initial release.
+1
View File
@@ -0,0 +1 @@
../lodash/build.js
@@ -0,0 +1,22 @@
Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
Based on Underscore.js 1.4.3, copyright 2009-2013 Jeremy Ashkenas,
DocumentCloud Inc. <http://underscorejs.org/>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,276 @@
# Lo-Dash <sup>v1.0.1</sup>
[![build status](https://secure.travis-ci.org/bestiejs/lodash.png)](http://travis-ci.org/bestiejs/lodash)
An alternative to Underscore.js, delivering consistency, [customization](https://github.com/bestiejs/lodash#custom-builds), [performance](http://lodash.com/benchmarks), and [extra features](https://github.com/bestiejs/lodash#features).
## Download
* Lo-Dash builds (for modern environments):<br>
[Development](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.js) and
[Production](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.min.js)
* Lo-Dash compatibility builds (for legacy and modern environments):<br>
[Development](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.compat.js) and
[Production](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.compat.min.js)
* Underscore compatibility builds:<br>
[Development](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.underscore.js) and
[Production](https://raw.github.com/bestiejs/lodash/v1.0.1/dist/lodash.underscore.min.js)
* CDN copies of ≤ v1.0.1s builds are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/):<br>
[Lo-Dash dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.js),
[Lo-Dash prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.min.js),<br>
[Lo-Dash compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.compat.js),
[Lo-Dash compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.compat.min.js),<br>
[Underscore compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.underscore.js), and
[Underscore compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.underscore.min.js)
* For optimal file size, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need
## Dive in
Weve got [API docs](http://lodash.com/docs), [benchmarks](http://lodash.com/benchmarks), and [unit tests](http://lodash.com/tests).
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/lodash/wiki/Roadmap).
## Resources
For more information check out these articles, screencasts, and other videos over Lo-Dash:
* Posts
- [Say “Hello” to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/)
* Videos
- [Introducing Lo-Dash](https://vimeo.com/44154599)
- [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601)
- [Lo-Dashs origin and why its a better utility belt](https://vimeo.com/44154600)
- [Unit testing in Lo-Dash](https://vimeo.com/45865290)
- [Lo-Dashs approach to native method use](https://vimeo.com/48576012)
- [CascadiaJS: Lo-Dash for a better utility belt](http://www.youtube.com/watch?v=dpPy4f_SeEk)
## Features
* AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)
* [_(…)](http://lodash.com/docs#_) supports intuitive chaining
* [_.at](http://lodash.com/docs#at) for cherry-picking collection values
* [_.bindKey](http://lodash.com/docs#bindKey) for binding [*“lazy”* defined](http://michaux.ca/articles/lazy-function-definition-pattern) methods
* [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays and objects
* [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` argument
* [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early
* [_.forIn](http://lodash.com/docs#forIn) for iterating over an objects own and inherited properties
* [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an objects own properties
* [_.isPlainObject](http://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor
* [_.merge](http://lodash.com/docs#merge) for a deep [_.extend](http://lodash.com/docs#extend)
* [_.partial](http://lodash.com/docs#partial) and [_.partialRight](http://lodash.com/docs#partialRight) for partial application without `this` binding
* [_.template](http://lodash.com/docs#template) supports [*“imports”* options](http://lodash.com/docs#templateSettings_imports), [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6), and [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
* [_.where](http://lodash.com/docs#where) supports deep object comparisons
* [_.clone](http://lodash.com/docs#clone), [_.omit](http://lodash.com/docs#omit), [_.pick](http://lodash.com/docs#pick),
[and more…](http://lodash.com/docs "_.assign, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest") accept `callback` and `thisArg` arguments
* [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray),
[and more…](http://lodash.com/docs "_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.some, _.sortBy, _.where") accept strings
* [_.filter](http://lodash.com/docs#filter), [_.find](http://lodash.com/docs#find), [_.map](http://lodash.com/docs#map),
[and more…](http://lodash.com/docs "_.countBy, _.every, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq") support *“_.pluck”* and *“_.where”* `callback` shorthands
## Support
Lo-Dash has been tested in at least Chrome 5~24, Firefox 1~18, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.20, Narwhal 0.3.2, PhantomJS 1.8.1, RingoJS 0.9, and Rhino 1.7RC5.
## Custom builds
Custom builds make it easy to create lightweight versions of Lo-Dash containing only the methods you need.
To top it off, we handle all method dependency and alias mapping for you.
* Backbone builds, with only methods required by Backbone, may be created using the `backbone` modifier argument.
```bash
lodash backbone
```
* CSP builds, supporting default [Content Security Policy](https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html) restrictions, may be created using the `csp` modifier argument.
The `csp` modifier is an alais of the `mobile` modifier. Lo-Dash may be used in Chrome extensions by using either the `csp`, `mobile`, or `underscore` build and using precompiled templates, or loading Lo-Dash in a [sandbox](http://developer.chrome.com/stable/extensions/sandboxingEval.html).
```bash
lodash csp
```
* Legacy builds, tailored for older environments without [ES5 support](http://es5.github.com/), may be created using the `legacy` modifier argument.
```bash
lodash legacy
```
* Modern builds, tailored for newer environments with ES5 support, may be created using the `modern` modifier argument.
```bash
lodash modern
```
* Mobile builds, without method compilation and most bug fixes for old browsers, may be created using the `mobile` modifier argument.
```bash
lodash mobile
```
* Strict builds, with `_.bindAll`, `_.defaults`, and `_.extend` in [strict mode](http://es5.github.com/#C), may be created using the `strict` modifier argument.
```bash
lodash strict
```
* Underscore builds, tailored for projects already using Underscore, may be created using the `underscore` modifier argument.
```bash
lodash underscore
```
Custom builds may be created using the following commands:
* Use the `category` argument to pass comma separated categories of methods to include in the build.<br>
Valid categories (case-insensitive) are *“arrays”*, *“chaining”*, *“collections”*, *“functions”*, *“objects”*, and *“utilities”*.
```bash
lodash category=collections,functions
lodash category="collections, functions"
```
* Use the `exports` argument to pass comma separated names of ways to export the `LoDash` function.<br>
Valid exports are *“amd”*, *“commonjs”*, *“global”*, *“node”*, and *“none”*.
```bash
lodash exports=amd,commonjs,node
lodash exports="amd, commonjs, node"
```
* Use the `iife` argument to specify code to replace the immediately-invoked function expression that wraps Lo-Dash.
```bash
lodash iife="!function(window,undefined){%output%}(this)"
```
* Use the `include` argument to pass comma separated method/category names to include in the build.
```bash
lodash include=each,filter,map
lodash include="each, filter, map"
```
* Use the `minus` argument to pass comma separated method/category names to remove from those included in the build.
```bash
lodash underscore minus=result,shuffle
lodash underscore minus="result, shuffle"
```
* Use the `plus` argument to pass comma separated method/category names to add to those included in the build.
```bash
lodash backbone plus=random,template
lodash backbone plus="random, template"
```
* Use the `template` argument to pass the file path pattern used to match template files to precompile.
```bash
lodash template="./*.jst"
```
* Use the `settings` argument to pass the template settings used when precompiling templates.
```bash
lodash settings="{interpolate:/\{\{([\s\S]+?)\}\}/g}"
```
* Use the `moduleId` argument to specify the AMD module ID of Lo-Dash, which defaults to “lodash”, used by precompiled templates.
```bash
lodash moduleId="underscore"
```
All arguments, except `legacy` with `csp`, `mobile`, `modern`, or `underscore`, may be combined.<br>
Unless specified by `-o` or `--output`, all files created are saved to the current working directory.
The following options are also supported:
* `-c`, `--stdout` ......... Write output to standard output
* `-d`, `--debug` ........... Write only the non-minified development output
* `-h`, `--help` ............. Display help information
* `-m`, `--minify` ......... Write only the minified production output
* `-o`, `--output` ......... Write output to a given path/filename
* `-p`, `--source-map` .. Generate a source map for the minified output, using an optional source map URL
* `-s`, `--silent` ......... Skip status updates normally logged to the console
* `-V`, `--version` ....... Output current version of Lo-Dash
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
## Installation and usage
In browsers:
```html
<script src="lodash.js"></script>
```
Using [`npm`](http://npmjs.org/):
```bash
npm install lodash
npm install -g lodash
npm link lodash
```
To avoid potential issues, update `npm` before installing Lo-Dash:
```bash
npm install npm -g
```
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
```js
var _ = require('lodash');
// or as a drop-in replacement for Underscore
var _ = require('lodash/lodash.underscore');
```
**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your projects root directory before requiring it.
In [RingoJS v0.7.0-](http://ringojs.org/):
```js
var _ = require('lodash')._;
```
In [Rhino](http://www.mozilla.org/rhino/):
```js
load('lodash.js');
```
In an AMD loader like [RequireJS](http://requirejs.org/):
```js
require({
'paths': {
'underscore': 'path/to/lodash'
}
},
['underscore'], function(_) {
console.log(_.VERSION);
});
```
## Release Notes
### <sup>v1.0.1</sup>
* Add support for specifying source map URLs in `-p`/`--source-map` build options
* Ensured the second argument passed to `_.assign` is not treated as a `callback`
* Ensured `-p`/`--source-map` build options correctly set the `sourceMappingURL`
* Made `-p`/`--source-map` build options set source map *“sources”* keys based on the builds performed
* Made `_.defer` use `setImmediate`, in Node.js, when available
* Made `_.where` search arrays for values regardless of their index position
* Removed dead code from `_.template`
The full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog).
## BestieJS
Lo-Dash is part of the BestieJS *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.
## Author
* [John-David Dalton](http://allyoucanleet.com/)
[![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter")
## Contributors
* [Kit Cambridge](http://kitcambridge.github.com/)
[![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter")
* [Mathias Bynens](http://mathiasbynens.be/)
[![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter")
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
<ul>
<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>
</ul>
@@ -0,0 +1 @@
<% print("Hello " + epithet); %>.
@@ -0,0 +1 @@
Hello ${ name }!

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