mirror of
https://github.com/photonstorm/phaser
synced 2024-11-10 15:14:47 +00:00
Merge branch 'photonstorm/097'
This commit is contained in:
commit
727a06cd9b
258 changed files with 23278 additions and 662 deletions
|
@ -14,6 +14,7 @@
|
|||
/// <reference path="cameras/CameraManager.ts" />
|
||||
/// <reference path="gameobjects/GameObjectFactory.ts" />
|
||||
/// <reference path="sound/SoundManager.ts" />
|
||||
/// <reference path="sound/Sound.ts" />
|
||||
/// <reference path="Stage.ts" />
|
||||
/// <reference path="Time.ts" />
|
||||
/// <reference path="tweens/TweenManager.ts" />
|
||||
|
@ -298,12 +299,12 @@ module Phaser {
|
|||
this.stage = new Stage(this, parent, width, height);
|
||||
this.world = new World(this, width, height);
|
||||
this.add = new GameObjectFactory(this);
|
||||
this.sound = new SoundManager(this);
|
||||
this.cache = new Cache(this);
|
||||
this.load = new Loader(this, this.loadComplete);
|
||||
this.time = new Time(this);
|
||||
this.tweens = new TweenManager(this);
|
||||
this.input = new Input(this);
|
||||
this.sound = new SoundManager(this);
|
||||
this.rnd = new RandomDataGenerator([(Date.now() * Math.random()).toString()]);
|
||||
this.physics = new Physics.Manager(this);
|
||||
|
||||
|
@ -391,6 +392,7 @@ module Phaser {
|
|||
this.tweens.update();
|
||||
this.input.update();
|
||||
this.stage.update();
|
||||
this.sound.update();
|
||||
|
||||
if (this.onPausedCallback !== null)
|
||||
{
|
||||
|
@ -407,6 +409,7 @@ module Phaser {
|
|||
this.tweens.update();
|
||||
this.input.update();
|
||||
this.stage.update();
|
||||
this.sound.update();
|
||||
this.physics.update();
|
||||
this.world.update();
|
||||
|
||||
|
@ -636,6 +639,7 @@ module Phaser {
|
|||
if (value == true && this._paused == false)
|
||||
{
|
||||
this._paused = true;
|
||||
this.sound.pauseAll();
|
||||
this._raf.callback = this.pausedLoop;
|
||||
}
|
||||
else if (value == false && this._paused == true)
|
||||
|
@ -643,6 +647,7 @@ module Phaser {
|
|||
this._paused = false;
|
||||
//this.time.time = window.performance.now ? (performance.now() + performance.timing.navigationStart) : Date.now();
|
||||
this.input.reset();
|
||||
this.sound.resumeAll();
|
||||
|
||||
if (this.isRunning == false)
|
||||
{
|
||||
|
|
|
@ -61,6 +61,8 @@ module Phaser {
|
|||
|
||||
document.addEventListener('visibilitychange', (event) => this.visibilityChange(event), false);
|
||||
document.addEventListener('webkitvisibilitychange', (event) => this.visibilityChange(event), false);
|
||||
document.addEventListener('pagehide', (event) => this.visibilityChange(event), false);
|
||||
document.addEventListener('pageshow', (event) => this.visibilityChange(event), false);
|
||||
window.onblur = (event) => this.visibilityChange(event);
|
||||
window.onfocus = (event) => this.visibilityChange(event);
|
||||
|
||||
|
@ -211,24 +213,27 @@ module Phaser {
|
|||
*/
|
||||
private visibilityChange(event) {
|
||||
|
||||
if (this.disablePauseScreen)
|
||||
if (event.type == 'pagehide' || event.type == 'blur' || document['hidden'] == true || document['webkitHidden'] == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.type == 'blur' || document['hidden'] == true || document['webkitHidden'] == true)
|
||||
{
|
||||
if (this._game.paused == false)
|
||||
if (this._game.paused == false && this.disablePauseScreen == false)
|
||||
{
|
||||
this.pauseGame();
|
||||
}
|
||||
else
|
||||
{
|
||||
this._game.paused = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this._game.paused == true)
|
||||
if (this._game.paused == true && this.disablePauseScreen == false)
|
||||
{
|
||||
this.resumeGame();
|
||||
}
|
||||
else
|
||||
{
|
||||
this._game.paused = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,10 @@ module Phaser {
|
|||
static BODY_KINETIC: number = 2;
|
||||
static BODY_DYNAMIC: number = 3;
|
||||
|
||||
static OUT_OF_BOUNDS_KILL: number = 0;
|
||||
static OUT_OF_BOUNDS_DESTROY: number = 1;
|
||||
static OUT_OF_BOUNDS_PERSIST: number = 2;
|
||||
|
||||
/**
|
||||
* Flag used to allow GameObjects to collide on their left side
|
||||
* @type {number}
|
||||
|
|
|
@ -23,6 +23,7 @@ module Phaser.Components.Sprite {
|
|||
this.onRemovedFromGroup = new Phaser.Signal;
|
||||
this.onKilled = new Phaser.Signal;
|
||||
this.onRevived = new Phaser.Signal;
|
||||
this.onOutOfBounds = new Phaser.Signal;
|
||||
|
||||
}
|
||||
|
||||
|
@ -101,6 +102,9 @@ module Phaser.Components.Sprite {
|
|||
*/
|
||||
public onAnimationLoop: Phaser.Signal;
|
||||
|
||||
/**
|
||||
* Dispatched by the Sprite when it first leaves the world bounds
|
||||
*/
|
||||
public onOutOfBounds: Phaser.Signal;
|
||||
|
||||
}
|
||||
|
|
|
@ -19,9 +19,14 @@ module Phaser {
|
|||
* Create a new <code>Button</code> object.
|
||||
*
|
||||
* @param game {Phaser.Game} Current game instance.
|
||||
* @param [x] {number} the initial x position of the button.
|
||||
* @param [y] {number} the initial y position of the button.
|
||||
* @param [key] {string} Key of the graphic you want to load for this button.
|
||||
* @param [x] {number} X position of the button.
|
||||
* @param [y] {number} Y position of the button.
|
||||
* @param [key] {string} The image key as defined in the Game.Cache to use as the texture for this button.
|
||||
* @param [callback] {function} The function to call when this button is pressed
|
||||
* @param [callbackContext] {object} The context in which the callback will be called (usually 'this')
|
||||
* @param [overFrame] {string|number} This is the frame or frameName that will be set when this button is in an over state. Give either a number to use a frame ID or a string for a frame name.
|
||||
* @param [outFrame] {string|number} This is the frame or frameName that will be set when this button is in an out state. Give either a number to use a frame ID or a string for a frame name.
|
||||
* @param [downFrame] {string|number} This is the frame or frameName that will be set when this button is in a down state. Give either a number to use a frame ID or a string for a frame name.
|
||||
*/
|
||||
constructor(game: Game, x?: number = 0, y?: number = 0, key?: string = null, callback? = null, callbackContext? = null, overFrame? = null, outFrame? = null, downFrame? = null) {
|
||||
|
||||
|
|
|
@ -94,6 +94,10 @@ module Phaser {
|
|||
return <Sprite> this._world.group.add(new Sprite(this._game, x, y, key, frame, bodyType));
|
||||
}
|
||||
|
||||
public audio(key: string, volume?: number = 1, loop?: bool = false) {
|
||||
return <Sound> this._game.sound.add(key, volume, loop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Sprite with the physics automatically created and set to DYNAMIC. The Sprite position offset is set to its center.
|
||||
*
|
||||
|
@ -182,13 +186,14 @@ module Phaser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a tween object for a specific object.
|
||||
* Create a tween object for a specific object. The object can be any JavaScript object or Phaser object such as Sprite.
|
||||
*
|
||||
* @param obj Object you wish the tween will affect.
|
||||
* @param obj {object} Object the tween will be run on.
|
||||
* @param [localReference] {bool} If true the tween will be stored in the object.tween property so long as it exists. If already set it'll be over-written.
|
||||
* @return {Phaser.Tween} The newly created tween object.
|
||||
*/
|
||||
public tween(obj): Tween {
|
||||
return this._game.tweens.create(obj);
|
||||
public tween(obj, localReference?:bool = false): Tween {
|
||||
return this._game.tweens.create(obj, localReference);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -202,6 +207,17 @@ module Phaser {
|
|||
return this._world.group.add(sprite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an existing Button to the current world.
|
||||
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
|
||||
*
|
||||
* @param button The Button to add to the Game World
|
||||
* @return {Phaser.Button} The Button object
|
||||
*/
|
||||
public existingButton(button: Button): Button {
|
||||
return this._world.group.add(button);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an existing GeomSprite to the current world.
|
||||
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
|
||||
|
|
|
@ -81,6 +81,9 @@ module Phaser {
|
|||
|
||||
this.transform.setCache();
|
||||
|
||||
this.outOfBounds = false;
|
||||
this.outOfBoundsAction = Phaser.Types.OUT_OF_BOUNDS_PERSIST;
|
||||
|
||||
// Handy proxies
|
||||
this.scale = this.transform.scale;
|
||||
this.alpha = this.texture.alpha;
|
||||
|
@ -128,6 +131,17 @@ module Phaser {
|
|||
*/
|
||||
public alive: bool;
|
||||
|
||||
/**
|
||||
* Is the Sprite out of the world bounds or not?
|
||||
*/
|
||||
public outOfBounds: bool;
|
||||
|
||||
/**
|
||||
* The action to be taken when the sprite is fully out of the world bounds
|
||||
* Defaults to Phaser.Types.OUT_OF_BOUNDS_KILL
|
||||
*/
|
||||
public outOfBoundsAction: number;
|
||||
|
||||
/**
|
||||
* Sprite physics body.
|
||||
*/
|
||||
|
@ -171,6 +185,11 @@ module Phaser {
|
|||
*/
|
||||
public cameraView: Phaser.Rectangle;
|
||||
|
||||
/**
|
||||
* A local tween variable. Used by the TweenManager when setting a tween on this sprite or a property of it.
|
||||
*/
|
||||
public tween: Phaser.Tween;
|
||||
|
||||
/**
|
||||
* A boolean representing if the Sprite has been modified in any way via a scale, rotate, flip or skew.
|
||||
*/
|
||||
|
@ -314,44 +333,34 @@ module Phaser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Automatically called after update() by the game loop.
|
||||
* Automatically called after update() by the game loop for all 'alive' objects.
|
||||
*/
|
||||
public postUpdate() {
|
||||
|
||||
this.animations.update();
|
||||
|
||||
/*
|
||||
if (this.worldBounds != null)
|
||||
if (Phaser.RectangleUtils.intersects(this.worldView, this.game.world.bounds))
|
||||
{
|
||||
if (this.outOfBoundsAction == GameObject.OUT_OF_BOUNDS_KILL)
|
||||
this.outOfBounds = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.outOfBounds == false)
|
||||
{
|
||||
if (this.x < this.worldBounds.x || this.x > this.worldBounds.right || this.y < this.worldBounds.y || this.y > this.worldBounds.bottom)
|
||||
{
|
||||
this.kill();
|
||||
}
|
||||
this.events.onOutOfBounds.dispatch(this);
|
||||
}
|
||||
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;
|
||||
}
|
||||
this.outOfBounds = true;
|
||||
|
||||
if (this.outOfBoundsAction == Phaser.Types.OUT_OF_BOUNDS_KILL)
|
||||
{
|
||||
this.kill();
|
||||
}
|
||||
else if (this.outOfBoundsAction == Phaser.Types.OUT_OF_BOUNDS_DESTROY)
|
||||
{
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (this.modified == true && this.transform.scale.equals(1) && this.transform.skew.equals(0) && this.transform.rotation == 0 && this.transform.rotationOffset == 0 && this.texture.flippedX == false && this.texture.flippedY == false)
|
||||
{
|
||||
|
|
|
@ -275,7 +275,7 @@ module Phaser {
|
|||
* @property recordPointerHistory
|
||||
* @type {Boolean}
|
||||
**/
|
||||
public recordPointerHistory: bool = true;
|
||||
public recordPointerHistory: bool = false;
|
||||
|
||||
/**
|
||||
* The rate in milliseconds at which the Pointer objects should update their tracking history
|
||||
|
@ -286,7 +286,7 @@ module Phaser {
|
|||
|
||||
/**
|
||||
* The total number of entries that can be recorded into the Pointer objects tracking history.
|
||||
* The the Pointer is tracking one event every 100ms, then a trackLimit of 100 would store the last 10 seconds worth of history.
|
||||
* If the Pointer is tracking one event every 100ms, then a trackLimit of 100 would store the last 10 seconds worth of history.
|
||||
* @property recordLimit
|
||||
* @type {Number}
|
||||
*/
|
||||
|
|
|
@ -33,6 +33,10 @@ module Phaser {
|
|||
|
||||
}
|
||||
|
||||
private _highestRenderOrderID: number;
|
||||
private _highestRenderObject: number;
|
||||
private _highestInputPriorityID: number;
|
||||
|
||||
/**
|
||||
* Local private reference to game.
|
||||
* @property game
|
||||
|
@ -239,6 +243,13 @@ module Phaser {
|
|||
**/
|
||||
public totalTouches: number = 0;
|
||||
|
||||
/**
|
||||
* The number of miliseconds since the last click
|
||||
* @property msSinceLastClick
|
||||
* @type {Number}
|
||||
**/
|
||||
public msSinceLastClick: number = Number.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* How long the Pointer has been depressed on the touchscreen. If not currently down it returns -1.
|
||||
* @property duration
|
||||
|
@ -306,7 +317,12 @@ module Phaser {
|
|||
this.withinGame = true;
|
||||
this.isDown = true;
|
||||
this.isUp = false;
|
||||
|
||||
// Work out how long it has been since the last click
|
||||
this.msSinceLastClick = this.game.time.now - this.timeDown;
|
||||
|
||||
this.timeDown = this.game.time.now;
|
||||
|
||||
this._holdSent = false;
|
||||
|
||||
// This sets the x/y and other local values
|
||||
|
@ -371,10 +387,6 @@ module Phaser {
|
|||
|
||||
}
|
||||
|
||||
private _highestRenderOrderID: number;
|
||||
private _highestRenderObject: number;
|
||||
private _highestInputPriorityID: number;
|
||||
|
||||
/**
|
||||
* Called when the Pointer is moved on the touchscreen
|
||||
* @method move
|
||||
|
|
|
@ -79,9 +79,7 @@ module Phaser {
|
|||
* @param {Any} event
|
||||
**/
|
||||
private consumeTouchMove(event) {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -122,22 +122,68 @@ module Phaser {
|
|||
* @param url {string} URL of this sound file.
|
||||
* @param data {object} Extra sound data.
|
||||
*/
|
||||
public addSound(key: string, url: string, data) {
|
||||
public addSound(key: string, url: string, data, webAudio: bool = true, audioTag: bool = false) {
|
||||
|
||||
this._sounds[key] = { url: url, data: data, decoded: false };
|
||||
console.log('Cache addSound: ' + key + ' url: ' + url, webAudio, audioTag);
|
||||
|
||||
var locked: bool = this._game.sound.touchLocked;
|
||||
var decoded: bool = false;
|
||||
|
||||
if (audioTag) {
|
||||
decoded = true;
|
||||
}
|
||||
|
||||
this._sounds[key] = { url: url, data: data, locked: locked, isDecoding: false, decoded: decoded, webAudio: webAudio, audioTag: audioTag };
|
||||
|
||||
}
|
||||
|
||||
public reloadSound(key: string) {
|
||||
|
||||
console.log('reloadSound', key);
|
||||
|
||||
if (this._sounds[key])
|
||||
{
|
||||
this._sounds[key].data.src = this._sounds[key].url;
|
||||
this._sounds[key].data.addEventListener('canplaythrough', () => this.reloadSoundComplete(key), false);
|
||||
this._sounds[key].data.load();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public onSoundUnlock: Phaser.Signal = new Phaser.Signal;
|
||||
|
||||
public reloadSoundComplete(key: string) {
|
||||
|
||||
console.log('reloadSoundComplete', key);
|
||||
|
||||
if (this._sounds[key])
|
||||
{
|
||||
this._sounds[key].locked = false;
|
||||
this.onSoundUnlock.dispatch(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public updateSound(key: string, property: string, value) {
|
||||
|
||||
if (this._sounds[key])
|
||||
{
|
||||
this._sounds[key][property] = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new decoded sound.
|
||||
* @param key {string} Asset key for the sound.
|
||||
* @param url {string} URL of this sound file.
|
||||
* @param data {object} Extra sound data.
|
||||
*/
|
||||
public decodedSound(key: string, data) {
|
||||
|
||||
console.log('decoded sound', key);
|
||||
this._sounds[key].data = data;
|
||||
this._sounds[key].decoded = true;
|
||||
this._sounds[key].isDecoding = false;
|
||||
|
||||
}
|
||||
|
||||
|
@ -201,12 +247,28 @@ module Phaser {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sound by key.
|
||||
* @param key Asset key of the sound you want.
|
||||
* @return {object} The sound you want.
|
||||
*/
|
||||
public getSound(key: string) {
|
||||
|
||||
if (this._sounds[key])
|
||||
{
|
||||
return this._sounds[key];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sound data by key.
|
||||
* @param key Asset key of the sound you want.
|
||||
* @return {object} The sound data you want.
|
||||
*/
|
||||
public getSound(key: string) {
|
||||
public getSoundData(key: string) {
|
||||
|
||||
if (this._sounds[key])
|
||||
{
|
||||
|
@ -231,6 +293,22 @@ module Phaser {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an asset is decoded sound.
|
||||
* @param key Asset key of the sound you want.
|
||||
* @return {object} The sound data you want.
|
||||
*/
|
||||
public isSoundReady(key: string): bool {
|
||||
|
||||
if (this._sounds[key] && this._sounds[key].decoded == true && this._sounds[key].locked == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an asset is sprite sheet.
|
||||
* @param key Asset key of the sprite sheet you want.
|
||||
|
|
|
@ -218,14 +218,15 @@ module Phaser {
|
|||
/**
|
||||
* Add a new audio file loading request.
|
||||
* @param key {string} Unique asset key of the audio file.
|
||||
* @param url {string} URL of audio file.
|
||||
* @param urls {Array} An array containing the URLs of the audio files, i.e.: [ 'jump.mp3', 'jump.ogg', 'jump.m4a' ]
|
||||
* @param autoDecode {boolean} When using Web Audio the audio files can either be decoded at load time or run-time. They can't be played until they are decoded, but this let's you control when that happens. Decoding is a non-blocking async process.
|
||||
*/
|
||||
public audio(key: string, url: string) {
|
||||
public audio(key: string, urls: string[], autoDecode: bool = true) {
|
||||
|
||||
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._fileList[key] = { type: 'audio', key: key, url: urls, data: null, buffer: null, error: false, loaded: false, autoDecode: autoDecode };
|
||||
this._keys.push(key);
|
||||
}
|
||||
|
||||
|
@ -327,11 +328,48 @@ module Phaser {
|
|||
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();
|
||||
|
||||
file.url = this.getAudioURL(file.url);
|
||||
console.log('Loader audio');
|
||||
console.log(file.url);
|
||||
|
||||
if (file.url !== null)
|
||||
{
|
||||
// WebAudio or Audio Tag?
|
||||
if (this._game.sound.usingWebAudio)
|
||||
{
|
||||
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();
|
||||
}
|
||||
else if (this._game.sound.usingAudioTag)
|
||||
{
|
||||
if (this._game.sound.touchLocked)
|
||||
{
|
||||
// If audio is locked we can't do this yet, so need to queue this load request somehow. Bum.
|
||||
console.log('Audio is touch locked');
|
||||
file.data = new Audio();
|
||||
file.data.name = file.key;
|
||||
file.data.preload = 'auto';
|
||||
file.data.src = file.url;
|
||||
this.fileComplete(file.key);
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log('Audio not touch locked');
|
||||
file.data = new Audio();
|
||||
file.data.name = file.key;
|
||||
file.data.onerror = () => this.fileError(file.key);
|
||||
file.data.preload = 'auto';
|
||||
file.data.src = file.url;
|
||||
file.data.addEventListener('canplaythrough', () => this.fileComplete(file.key), false);
|
||||
file.data.load();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'text':
|
||||
|
@ -345,6 +383,28 @@ module Phaser {
|
|||
|
||||
}
|
||||
|
||||
private getAudioURL(urls): string {
|
||||
|
||||
var extension: string;
|
||||
|
||||
for (var i = 0; i < urls.length; i++)
|
||||
{
|
||||
extension = urls[i].toLowerCase();
|
||||
extension = extension.substr((Math.max(0, extension.lastIndexOf(".")) || Infinity) + 1);
|
||||
|
||||
if (this._game.device.canPlayAudio(extension))
|
||||
{
|
||||
console.log('getAudioURL', urls[i]);
|
||||
console.log(urls[i]);
|
||||
return urls[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Error occured when load a file.
|
||||
* @param key {string} Key of the error loading file.
|
||||
|
@ -406,8 +466,32 @@ module Phaser {
|
|||
break;
|
||||
|
||||
case 'audio':
|
||||
file.data = this._xhr.response;
|
||||
this._game.cache.addSound(file.key, file.url, file.data);
|
||||
|
||||
if (this._game.sound.usingWebAudio)
|
||||
{
|
||||
file.data = this._xhr.response;
|
||||
|
||||
this._game.cache.addSound(file.key, file.url, file.data, true, false);
|
||||
|
||||
if (file.autoDecode)
|
||||
{
|
||||
this._game.cache.updateSound(key, 'isDecoding', true);
|
||||
|
||||
var that = this;
|
||||
var key = file.key;
|
||||
|
||||
this._game.sound.context.decodeAudioData(file.data, function (buffer) {
|
||||
if (buffer)
|
||||
{
|
||||
that._game.cache.decodedSound(key, buffer);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this._game.cache.addSound(file.key, file.url, file.data, false, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'text':
|
||||
|
|
|
@ -340,6 +340,16 @@ module Phaser.Physics {
|
|||
|
||||
}
|
||||
|
||||
private _newPosition: Phaser.Vec2 = new Phaser.Vec2;
|
||||
|
||||
public setPosition(x: number, y: number) {
|
||||
|
||||
this._newPosition.setTo(this.game.physics.pixelsToMeters(x), this.game.physics.pixelsToMeters(y));
|
||||
|
||||
this.setTransform(this._newPosition, this.angle);
|
||||
|
||||
}
|
||||
|
||||
public setTransform(pos:Phaser.Vec2, angle:number) {
|
||||
|
||||
// inject the transform into this.position
|
||||
|
|
|
@ -13,100 +13,376 @@ module Phaser {
|
|||
|
||||
/**
|
||||
* Sound constructor
|
||||
* @param context {object} The AudioContext instance.
|
||||
* @param gainNode {object} Gain node instance.
|
||||
* @param data {object} Sound data.
|
||||
* @param [volume] {number} volume of this sound when playing.
|
||||
* @param [loop] {boolean} loop this sound when playing? (Default to false)
|
||||
*/
|
||||
constructor(context, gainNode, data, volume?: number = 1, loop?: bool = false) {
|
||||
constructor(game: Phaser.Game, key: string, volume?: number = 1, loop?: bool = false) {
|
||||
|
||||
this._context = context;
|
||||
this._gainNode = gainNode;
|
||||
this._buffer = data;
|
||||
this._volume = volume;
|
||||
this.loop = loop;
|
||||
this.game = game;
|
||||
|
||||
// Local volume control
|
||||
if (this._context !== null)
|
||||
this.usingWebAudio = this.game.sound.usingWebAudio;
|
||||
this.usingAudioTag = this.game.sound.usingAudioTag;
|
||||
this.key = key;
|
||||
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
this._localGainNode = this._context.createGainNode();
|
||||
this._localGainNode.connect(this._gainNode);
|
||||
this._localGainNode.gain.value = this._volume;
|
||||
}
|
||||
this.context = this.game.sound.context;
|
||||
this.masterGainNode = this.game.sound.masterGain;
|
||||
|
||||
if (this._buffer === null)
|
||||
{
|
||||
this.isDecoding = true;
|
||||
if (typeof this.context.createGain === 'undefined')
|
||||
{
|
||||
this.gainNode = this.context.createGainNode();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.gainNode = this.context.createGain();
|
||||
}
|
||||
|
||||
this.gainNode.gain.value = volume * this.game.sound.volume;
|
||||
this.gainNode.connect(this.masterGainNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.play();
|
||||
if (this.game.cache.getSound(key).locked == false)
|
||||
{
|
||||
this._sound = this.game.cache.getSoundData(key);
|
||||
this.totalDuration = this._sound.duration;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.game.cache.onSoundUnlock.add(this.soundHasUnlocked, this);
|
||||
}
|
||||
}
|
||||
|
||||
this._volume = volume;
|
||||
this.loop = loop;
|
||||
this.markers = {};
|
||||
|
||||
this.onDecoded = new Phaser.Signal;
|
||||
this.onPlay = new Phaser.Signal;
|
||||
this.onPause = new Phaser.Signal;
|
||||
this.onResume = new Phaser.Signal;
|
||||
this.onLoop = new Phaser.Signal;
|
||||
this.onStop = new Phaser.Signal;
|
||||
this.onMute = new Phaser.Signal;
|
||||
|
||||
}
|
||||
|
||||
private soundHasUnlocked(key:string) {
|
||||
|
||||
if (key == this.key)
|
||||
{
|
||||
this._sound = this.game.cache.getSoundData(this.key);
|
||||
this.totalDuration = this._sound.duration;
|
||||
console.log('sound has unlocked', this._sound);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Local private reference to AudioContext.
|
||||
* Local reference to the current Phaser.Game.
|
||||
*/
|
||||
private _context;
|
||||
public game: Game;
|
||||
|
||||
/**
|
||||
* Reference to AudioContext instance.
|
||||
*/
|
||||
public context = null;
|
||||
|
||||
/**
|
||||
* Reference to gain node of SoundManager.
|
||||
*/
|
||||
private _gainNode;
|
||||
public masterGainNode;
|
||||
|
||||
/**
|
||||
* GainNode of this sound.
|
||||
*/
|
||||
private _localGainNode;
|
||||
public gainNode;
|
||||
|
||||
/**
|
||||
* Decoded data buffer.
|
||||
* Decoded data buffer / Audio tag.
|
||||
*/
|
||||
private _buffer;
|
||||
|
||||
/**
|
||||
* Volume of this sound.
|
||||
*/
|
||||
private _volume: number;
|
||||
|
||||
/**
|
||||
* The real sound object (buffer source).
|
||||
*/
|
||||
private _sound;
|
||||
|
||||
private _muteVolume: number;
|
||||
private _muted: bool = false;
|
||||
private _tempPosition: number;
|
||||
private _tempVolume: number;
|
||||
private _tempLoop: bool;
|
||||
private _tempMarker: string;
|
||||
|
||||
public usingWebAudio: bool = false;
|
||||
public usingAudioTag: bool = false;
|
||||
|
||||
public name: string = '';
|
||||
|
||||
autoplay: bool = false;
|
||||
totalDuration: number = 0;
|
||||
startTime: number = 0;
|
||||
currentTime: number = 0;
|
||||
duration: number = 0;
|
||||
stopTime: number = 0;
|
||||
position: number;
|
||||
paused: bool = false;
|
||||
loop: bool = false;
|
||||
duration: number;
|
||||
isPlaying: bool = false;
|
||||
isDecoding: bool = false;
|
||||
key: string;
|
||||
markers;
|
||||
currentMarker: string = '';
|
||||
|
||||
public setDecodedBuffer(data) {
|
||||
// events
|
||||
public onDecoded: Phaser.Signal;
|
||||
public onPlay: Phaser.Signal;
|
||||
public onPause: Phaser.Signal;
|
||||
public onResume: Phaser.Signal;
|
||||
public onLoop: Phaser.Signal;
|
||||
public onStop: Phaser.Signal;
|
||||
public onMute: Phaser.Signal;
|
||||
|
||||
this._buffer = data;
|
||||
this.isDecoding = false;
|
||||
//this.play();
|
||||
public pendingPlayback: bool = false;
|
||||
|
||||
public get isDecoding(): bool {
|
||||
return this.game.cache.getSound(this.key).isDecoding;
|
||||
}
|
||||
|
||||
public get isDecoded(): bool {
|
||||
return this.game.cache.isSoundDecoded(this.key);
|
||||
}
|
||||
|
||||
public addMarker(name: string, start: number, stop: number, volume: number = 1, loop: bool = false) {
|
||||
this.markers[name] = { name: name, start: start, stop: stop, volume: volume, duration: stop - start, loop: loop };
|
||||
}
|
||||
|
||||
public removeMarker(name: string) {
|
||||
delete this.markers[name];
|
||||
}
|
||||
|
||||
public update() {
|
||||
|
||||
if (this.pendingPlayback && this.game.cache.isSoundReady(this.key))
|
||||
{
|
||||
console.log('pending over');
|
||||
this.pendingPlayback = false;
|
||||
this.play(this._tempMarker, this._tempPosition, this._tempVolume, this._tempLoop);
|
||||
}
|
||||
|
||||
if (this.isPlaying)
|
||||
{
|
||||
this.currentTime = this.game.time.now - this.startTime;
|
||||
|
||||
if (this.currentTime >= this.duration)
|
||||
{
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
if (this.loop)
|
||||
{
|
||||
this.onLoop.dispatch(this);
|
||||
this.currentTime = 0;
|
||||
this.startTime = this.game.time.now;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.loop)
|
||||
{
|
||||
this.onLoop.dispatch(this);
|
||||
this.play(this.currentMarker, 0, this.volume, true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Play this sound.
|
||||
* Play this sound, or a marked section of it.
|
||||
* @param marker {string} Assets key of the sound you want to play.
|
||||
* @param [volume] {number} volume of the sound you want to play.
|
||||
* @param [loop] {boolean} loop when it finished playing? (Default to false)
|
||||
* @return {Sound} The playing sound object.
|
||||
*/
|
||||
public play() {
|
||||
public play(marker: string = '', position?: number = 0, volume?: number = 1, loop?: bool = false, forceRestart: bool = false) {
|
||||
|
||||
if (this._buffer === null || this.isDecoding === true)
|
||||
if (this.isPlaying == true && forceRestart == false)
|
||||
{
|
||||
// Use Restart instead
|
||||
return;
|
||||
}
|
||||
|
||||
this._sound = this._context.createBufferSource();
|
||||
this._sound.buffer = this._buffer;
|
||||
this._sound.connect(this._localGainNode);
|
||||
this.currentMarker = marker;
|
||||
|
||||
if (this.loop)
|
||||
if (marker !== '' && this.markers[marker])
|
||||
{
|
||||
this._sound.loop = true;
|
||||
this.position = this.markers[marker].start;
|
||||
this.volume = this.markers[marker].volume;
|
||||
this.loop = this.markers[marker].loop;
|
||||
this.duration = this.markers[marker].duration * 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.position = position;
|
||||
this.volume = volume;
|
||||
this.loop = loop;
|
||||
this.duration = 0;
|
||||
}
|
||||
|
||||
this._sound.noteOn(0); // the zero is vitally important, crashes iOS6 without it
|
||||
this._tempMarker = marker;
|
||||
this._tempPosition = position;
|
||||
this._tempVolume = volume;
|
||||
this._tempLoop = loop;
|
||||
|
||||
this.duration = this._sound.buffer.duration;
|
||||
this.isPlaying = true;
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
// Does the sound need decoding?
|
||||
if (this.game.cache.isSoundDecoded(this.key))
|
||||
{
|
||||
// Do we need to do this every time we play? How about just if the buffer is empty?
|
||||
this._buffer = this.game.cache.getSoundData(this.key);
|
||||
this._sound = this.context.createBufferSource();
|
||||
this._sound.buffer = this._buffer;
|
||||
this._sound.connect(this.gainNode);
|
||||
this.totalDuration = this._sound.buffer.duration;
|
||||
|
||||
if (this.duration == 0)
|
||||
{
|
||||
this.duration = this.totalDuration * 1000;
|
||||
}
|
||||
|
||||
if (this.loop)
|
||||
{
|
||||
this._sound.loop = true;
|
||||
}
|
||||
|
||||
// Useful to cache this somewhere perhaps?
|
||||
if (typeof this._sound.start === 'undefined')
|
||||
{
|
||||
this._sound.noteGrainOn(0, this.position, this.duration / 1000);
|
||||
//this._sound.noteOn(0); // the zero is vitally important, crashes iOS6 without it
|
||||
}
|
||||
else
|
||||
{
|
||||
this._sound.start(0, this.position, this.duration / 1000);
|
||||
}
|
||||
|
||||
this.isPlaying = true;
|
||||
this.startTime = this.game.time.now;
|
||||
this.currentTime = 0;
|
||||
this.stopTime = this.startTime + this.duration;
|
||||
this.onPlay.dispatch(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.pendingPlayback = true;
|
||||
|
||||
if (this.game.cache.getSound(this.key).isDecoding == false)
|
||||
{
|
||||
this.game.sound.decode(this.key, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log('Sound play Audio');
|
||||
|
||||
if (this.game.cache.getSound(this.key).locked)
|
||||
{
|
||||
console.log('tried playing locked sound, pending set, reload started');
|
||||
this.game.cache.reloadSound(this.key);
|
||||
this.pendingPlayback = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log('sound not locked, state?', this._sound.readyState);
|
||||
if (this._sound && this._sound.readyState == 4)
|
||||
{
|
||||
if (this.duration == 0)
|
||||
{
|
||||
this.duration = this.totalDuration * 1000;
|
||||
}
|
||||
|
||||
console.log('playing', this._sound);
|
||||
this._sound.currentTime = this.position;
|
||||
this._sound.muted = this._muted;
|
||||
this._sound.volume = this._volume;
|
||||
this._sound.play();
|
||||
|
||||
this.isPlaying = true;
|
||||
this.startTime = this.game.time.now;
|
||||
this.currentTime = 0;
|
||||
this.stopTime = this.startTime + this.duration;
|
||||
this.onPlay.dispatch(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.pendingPlayback = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public restart(marker: string = '', position?: number = 0, volume?: number = 1, loop?: bool = false) {
|
||||
this.play(marker, position, volume, loop, true);
|
||||
}
|
||||
|
||||
public pause() {
|
||||
|
||||
if (this.isPlaying && this._sound)
|
||||
{
|
||||
this.stop();
|
||||
this.isPlaying = false;
|
||||
this.paused = true;
|
||||
this.onPause.dispatch(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public resume() {
|
||||
|
||||
//if (this.isPlaying == false && this._sound)
|
||||
if (this.paused && this._sound)
|
||||
{
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
if (typeof this._sound.start === 'undefined')
|
||||
{
|
||||
this._sound.noteGrainOn(0, this.position, this.duration);
|
||||
//this._sound.noteOn(0); // the zero is vitally important, crashes iOS6 without it
|
||||
}
|
||||
else
|
||||
{
|
||||
this._sound.start(0, this.position, this.duration);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this._sound.play();
|
||||
}
|
||||
|
||||
this.isPlaying = true;
|
||||
this.paused = false;
|
||||
this.onResume.dispatch(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -115,37 +391,87 @@ module Phaser {
|
|||
*/
|
||||
public stop() {
|
||||
|
||||
if (this.isPlaying === true)
|
||||
if (this.isPlaying && this._sound)
|
||||
{
|
||||
this.isPlaying = false;
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
if (typeof this._sound.stop === 'undefined')
|
||||
{
|
||||
this._sound.noteOff(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
this._sound.stop(0);
|
||||
}
|
||||
}
|
||||
else if (this.usingAudioTag)
|
||||
{
|
||||
this._sound.pause();
|
||||
this._sound.currentTime = 0;
|
||||
}
|
||||
|
||||
this.isPlaying = false;
|
||||
this.currentMarker = '';
|
||||
this.onStop.dispatch(this);
|
||||
|
||||
this._sound.noteOff(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Mute the sound.
|
||||
* Mute sounds.
|
||||
*/
|
||||
public mute() {
|
||||
|
||||
this._localGainNode.gain.value = 0;
|
||||
|
||||
public get mute(): bool {
|
||||
return this._muted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the sound.
|
||||
*/
|
||||
public unmute() {
|
||||
public set mute(value: bool) {
|
||||
|
||||
this._localGainNode.gain.value = this._volume;
|
||||
if (value)
|
||||
{
|
||||
this._muted = true;
|
||||
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
this._muteVolume = this.gainNode.gain.value;
|
||||
this.gainNode.gain.value = 0;
|
||||
}
|
||||
else if (this.usingAudioTag && this._sound)
|
||||
{
|
||||
this._muteVolume = this._sound.volume;
|
||||
this._sound.volume = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this._muted = false;
|
||||
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
this.gainNode.gain.value = this._muteVolume;
|
||||
}
|
||||
else if (this.usingAudioTag && this._sound)
|
||||
{
|
||||
this._sound.volume = this._muteVolume;
|
||||
}
|
||||
}
|
||||
|
||||
this.onMute.dispatch(this);
|
||||
|
||||
}
|
||||
|
||||
public set volume(value: number) {
|
||||
|
||||
this._volume = value;
|
||||
this._localGainNode.gain.value = this._volume;
|
||||
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
this.gainNode.gain.value = value;
|
||||
}
|
||||
else if (this.usingAudioTag && this._sound)
|
||||
{
|
||||
this._sound.volume = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -153,6 +479,30 @@ module Phaser {
|
|||
return this._volume;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the Pointer.circle object onto the stage in green if down or red if up.
|
||||
* @method renderDebug
|
||||
*/
|
||||
public renderDebug(x: number, y: number) {
|
||||
|
||||
this.game.stage.context.fillStyle = 'rgb(255,255,255)';
|
||||
this.game.stage.context.font = '16px Courier';
|
||||
this.game.stage.context.fillText('Sound: ' + this.key + ' Locked: ' + this.game.sound.touchLocked + ' Pending Playback: ' + this.pendingPlayback, x, y);
|
||||
this.game.stage.context.fillText('Decoded: ' + this.isDecoded + ' Decoding: ' + this.isDecoding, x, y + 20);
|
||||
this.game.stage.context.fillText('Total Duration: ' + this.totalDuration + ' Playing: ' + this.isPlaying, x, y + 40);
|
||||
this.game.stage.context.fillText('Time: ' + this.currentTime, x, y + 60);
|
||||
this.game.stage.context.fillText('Volume: ' + this.volume + ' Muted: ' + this.mute, x, y + 80);
|
||||
this.game.stage.context.fillText('WebAudio: ' + this.usingWebAudio + ' Audio: ' + this.usingAudioTag, x, y + 100);
|
||||
|
||||
if (this.currentMarker !== '')
|
||||
{
|
||||
this.game.stage.context.fillText('Marker: ' + this.currentMarker + ' Duration: ' + this.duration, x, y + 120);
|
||||
this.game.stage.context.fillText('Start: ' + this.markers[this.currentMarker].start + ' Stop: ' + this.markers[this.currentMarker].stop, x, y + 140);
|
||||
this.game.stage.context.fillText('Position: ' + this.position, x, y + 160);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -17,48 +17,110 @@ module Phaser {
|
|||
*/
|
||||
constructor(game: Game) {
|
||||
|
||||
this._game = game;
|
||||
this.game = game;
|
||||
|
||||
if (window['PhaserGlobal'] && window['PhaserGlobal'].disableAudio == true)
|
||||
this._volume = 1;
|
||||
this._muted = false;
|
||||
this._sounds = [];
|
||||
|
||||
if (this.game.device.iOS && this.game.device.webAudio == false)
|
||||
{
|
||||
return;
|
||||
this.channels = 1;
|
||||
}
|
||||
|
||||
if (game.device.webaudio == true)
|
||||
if (this.game.device.iOS || (window['PhaserGlobal'] && window['PhaserGlobal'].fakeiOSTouchLock))
|
||||
{
|
||||
if (!!window['AudioContext'])
|
||||
console.log('iOS Touch Locked');
|
||||
this.game.input.touch.callbackContext = this;
|
||||
this.game.input.touch.touchStartCallback = this.unlock;
|
||||
this.game.input.mouse.callbackContext = this;
|
||||
this.game.input.mouse.mouseDownCallback = this.unlock;
|
||||
this.touchLocked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// What about iOS5?
|
||||
this.touchLocked = false;
|
||||
}
|
||||
|
||||
if (window['PhaserGlobal'])
|
||||
{
|
||||
// Check to see if all audio playback is disabled (i.e. handled by a 3rd party class)
|
||||
if (window['PhaserGlobal'].disableAudio == true)
|
||||
{
|
||||
this._context = new window['AudioContext']();
|
||||
}
|
||||
else if (!!window['webkitAudioContext'])
|
||||
{
|
||||
this._context = new window['webkitAudioContext']();
|
||||
this.usingWebAudio = false;
|
||||
this.noAudio = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._context !== null)
|
||||
// Check if the Web Audio API is disabled (for testing Audio Tag playback during development)
|
||||
if (window['PhaserGlobal'].disableWebAudio == true)
|
||||
{
|
||||
this._gainNode = this._context.createGainNode();
|
||||
this._gainNode.connect(this._context.destination);
|
||||
this._volume = 1;
|
||||
this.usingWebAudio = false;
|
||||
this.usingAudioTag = true;
|
||||
this.noAudio = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.usingWebAudio = true;
|
||||
this.noAudio = false;
|
||||
|
||||
if (!!window['AudioContext'])
|
||||
{
|
||||
this.context = new window['AudioContext']();
|
||||
}
|
||||
else if (!!window['webkitAudioContext'])
|
||||
{
|
||||
this.context = new window['webkitAudioContext']();
|
||||
}
|
||||
else if (!!window['Audio'])
|
||||
{
|
||||
this.usingWebAudio = false;
|
||||
this.usingAudioTag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.usingWebAudio = false;
|
||||
this.noAudio = true;
|
||||
}
|
||||
|
||||
if (this.context !== null)
|
||||
{
|
||||
if (typeof this.context.createGain === 'undefined')
|
||||
{
|
||||
this.masterGain = this.context.createGainNode();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.masterGain = this.context.createGain();
|
||||
}
|
||||
|
||||
this.masterGain.gain.value = 1;
|
||||
this.masterGain.connect(this.context.destination);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public usingWebAudio: bool = false;
|
||||
public usingAudioTag: bool = false;
|
||||
public noAudio: bool = false;
|
||||
|
||||
/**
|
||||
* Local private reference to game.
|
||||
* Local reference to the current Phaser.Game.
|
||||
*/
|
||||
private _game: Game;
|
||||
public game: Game;
|
||||
|
||||
/**
|
||||
* Reference to AudioContext instance.
|
||||
*/
|
||||
private _context = null;
|
||||
public context = null;
|
||||
|
||||
/**
|
||||
* Gain node created from audio context.
|
||||
* The Master Gain node through which all sounds
|
||||
*/
|
||||
private _gainNode;
|
||||
public masterGain;
|
||||
|
||||
/**
|
||||
* Volume of sounds.
|
||||
|
@ -66,100 +128,247 @@ module Phaser {
|
|||
*/
|
||||
private _volume: number;
|
||||
|
||||
/**
|
||||
* Mute sounds.
|
||||
*/
|
||||
public mute() {
|
||||
private _sounds: Phaser.Sound[];
|
||||
|
||||
this._gainNode.gain.value = 0;
|
||||
private _muteVolume: number;
|
||||
private _muted: bool = false;
|
||||
|
||||
public channels: number;
|
||||
|
||||
public touchLocked: bool = false;
|
||||
|
||||
private _unlockSource = null;
|
||||
|
||||
public unlock() {
|
||||
|
||||
if (this.touchLocked == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('SoundManager touch unlocked');
|
||||
|
||||
if (this.game.device.webAudio && (window['PhaserGlobal'] && window['PhaserGlobal'].disableWebAudio == false))
|
||||
{
|
||||
console.log('create empty buffer');
|
||||
// Create empty buffer and play it
|
||||
var buffer = this.context.createBuffer(1, 1, 22050);
|
||||
this._unlockSource = this.context.createBufferSource();
|
||||
this._unlockSource.buffer = buffer;
|
||||
this._unlockSource.connect(this.context.destination);
|
||||
this._unlockSource.noteOn(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create an Audio tag?
|
||||
console.log('create audio tag');
|
||||
this.touchLocked = false;
|
||||
this._unlockSource = null;
|
||||
this.game.input.touch.callbackContext = null;
|
||||
this.game.input.touch.touchStartCallback = null;
|
||||
this.game.input.mouse.callbackContext = null;
|
||||
this.game.input.mouse.mouseDownCallback = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable sounds.
|
||||
* A global audio mute toggle.
|
||||
*/
|
||||
public unmute() {
|
||||
public get mute():bool {
|
||||
return this._muted;
|
||||
}
|
||||
|
||||
this._gainNode.gain.value = this._volume;
|
||||
public set mute(value: bool) {
|
||||
|
||||
if (value)
|
||||
{
|
||||
if (this._muted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this._muted = true;
|
||||
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
this._muteVolume = this.masterGain.gain.value;
|
||||
this.masterGain.gain.value = 0;
|
||||
}
|
||||
|
||||
// Loop through sounds
|
||||
for (var i = 0; i < this._sounds.length; i++)
|
||||
{
|
||||
if (this._sounds[i])
|
||||
{
|
||||
this._sounds[i].mute = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this._muted == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this._muted = false;
|
||||
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
this.masterGain.gain.value = this._muteVolume;
|
||||
}
|
||||
|
||||
// Loop through sounds
|
||||
for (var i = 0; i < this._sounds.length; i++)
|
||||
{
|
||||
if (this._sounds[i])
|
||||
{
|
||||
this._sounds[i].mute = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The global audio volume. A value between 0 (silence) and 1 (full volume)
|
||||
*/
|
||||
public set volume(value: number) {
|
||||
|
||||
value = this.game.math.clamp(value, 1, 0);
|
||||
|
||||
this._volume = value;
|
||||
this._gainNode.gain.value = this._volume;
|
||||
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
this.masterGain.gain.value = value;
|
||||
}
|
||||
|
||||
// Loop through the sound cache and change the volume of all html audio tags
|
||||
for (var i = 0; i < this._sounds.length; i++)
|
||||
{
|
||||
if (this._sounds[i].usingAudioTag)
|
||||
{
|
||||
this._sounds[i].volume = this._sounds[i].volume * value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public get volume(): number {
|
||||
return this._volume;
|
||||
|
||||
if (this.usingWebAudio)
|
||||
{
|
||||
return this.masterGain.gain.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this._volume;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public stopAll() {
|
||||
|
||||
for (var i = 0; i < this._sounds.length; i++)
|
||||
{
|
||||
if (this._sounds[i])
|
||||
{
|
||||
this._sounds[i].stop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public pauseAll() {
|
||||
|
||||
for (var i = 0; i < this._sounds.length; i++)
|
||||
{
|
||||
if (this._sounds[i])
|
||||
{
|
||||
this._sounds[i].pause();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public resumeAll() {
|
||||
|
||||
for (var i = 0; i < this._sounds.length; i++)
|
||||
{
|
||||
if (this._sounds[i])
|
||||
{
|
||||
this._sounds[i].resume();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a sound with its assets key.
|
||||
* @param key {string} Assets key of the sound to be decoded.
|
||||
* @param callback {function} This will be invoked when finished decoding.
|
||||
* @param [sound] {Sound} its bufer will be set to decoded data.
|
||||
*/
|
||||
public decode(key: string, callback = null, sound?: Sound = null) {
|
||||
public decode(key: string, sound?: Sound = null) {
|
||||
|
||||
var soundData = this._game.cache.getSound(key);
|
||||
var soundData = this.game.cache.getSoundData(key);
|
||||
|
||||
if (soundData)
|
||||
{
|
||||
if (this._game.cache.isSoundDecoded(key) === false)
|
||||
if (this.game.cache.isSoundDecoded(key) === false)
|
||||
{
|
||||
this.game.cache.updateSound(key, 'isDecoding', true);
|
||||
|
||||
var that = this;
|
||||
|
||||
this._context.decodeAudioData(soundData, function (buffer) {
|
||||
that._game.cache.decodedSound(key, buffer);
|
||||
this.context.decodeAudioData(soundData, function (buffer) {
|
||||
|
||||
that.game.cache.decodedSound(key, buffer);
|
||||
|
||||
if (sound)
|
||||
{
|
||||
sound.setDecodedBuffer(buffer);
|
||||
that.onSoundDecode.dispatch(sound);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Play a sound with its assets key.
|
||||
* @param key {string} Assets key of the sound you want to play.
|
||||
* @param [volume] {number} volume of the sound you want to play.
|
||||
* @param [loop] {boolean} loop when it finished playing? (Default to false)
|
||||
* @return {Sound} The playing sound object.
|
||||
*/
|
||||
public play(key: string, volume?: number = 1, loop?: bool = false): Sound {
|
||||
public onSoundDecode: Phaser.Signal = new Phaser.Signal;
|
||||
|
||||
if (this._context === null)
|
||||
public update() {
|
||||
|
||||
if (this.touchLocked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var soundData = this._game.cache.getSound(key);
|
||||
|
||||
if (soundData)
|
||||
{
|
||||
// Does the sound need decoding?
|
||||
if (this._game.cache.isSoundDecoded(key) === true)
|
||||
if (this.game.device.webAudio && this._unlockSource !== null)
|
||||
{
|
||||
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, () => tempSound.play(), tempSound);
|
||||
|
||||
return tempSound;
|
||||
if ((this._unlockSource.playbackState === this._unlockSource.PLAYING_STATE || this._unlockSource.playbackState === this._unlockSource.FINISHED_STATE))
|
||||
{
|
||||
this.touchLocked = false;
|
||||
this._unlockSource = null;
|
||||
this.game.input.touch.callbackContext = null;
|
||||
this.game.input.touch.touchStartCallback = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < this._sounds.length; i++)
|
||||
{
|
||||
this._sounds[i].update();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public add(key: string, volume?: number = 1, loop?: bool = false): Sound {
|
||||
|
||||
var sound: Phaser.Sound = new Sound(this.game, key, volume, loop);
|
||||
|
||||
this._sounds.push(sound);
|
||||
|
||||
return sound;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -191,41 +191,53 @@ module Phaser {
|
|||
// Audio
|
||||
|
||||
/**
|
||||
* Is audioData available?
|
||||
* Are Audio tags available?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public audioData: bool = false;
|
||||
|
||||
/**
|
||||
* Is webaudio available?
|
||||
* Is the WebAudio API available?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public webaudio: bool = false;
|
||||
public webAudio: bool = false;
|
||||
|
||||
/**
|
||||
* Is ogg available?
|
||||
* Can this device play ogg files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public ogg: bool = false;
|
||||
|
||||
/**
|
||||
* Is mp3 available?
|
||||
* Can this device play opus files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public opus: bool = false;
|
||||
|
||||
/**
|
||||
* Can this device play mp3 files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public mp3: bool = false;
|
||||
|
||||
/**
|
||||
* Is wav available?
|
||||
* Can this device play wav files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public wav: bool = false;
|
||||
|
||||
/**
|
||||
* Is m4a available?
|
||||
* Can this device play m4a files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public m4a: bool = false;
|
||||
|
||||
/**
|
||||
* Can this device play webm files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public webm: bool = false;
|
||||
|
||||
// Device
|
||||
|
||||
/**
|
||||
|
@ -355,7 +367,7 @@ module Phaser {
|
|||
this.mobileSafari = true;
|
||||
}
|
||||
else if (/MSIE (\d+\.\d+);/.test(ua))
|
||||
{
|
||||
{
|
||||
this.ie = true;
|
||||
this.ieVersion = parseInt(RegExp.$1);
|
||||
}
|
||||
|
@ -380,6 +392,33 @@ module Phaser {
|
|||
|
||||
}
|
||||
|
||||
public canPlayAudio(type: string): bool {
|
||||
|
||||
if (type == 'mp3' && this.mp3)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (type == 'ogg' && (this.ogg || this.opus))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (type == 'm4a' && this.m4a)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (type == 'wav' && this.wav)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (type == 'webm' && this.webm)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check audio support.
|
||||
* @private
|
||||
|
@ -387,7 +426,7 @@ module Phaser {
|
|||
private _checkAudio() {
|
||||
|
||||
this.audioData = !!(window['Audio']);
|
||||
this.webaudio = !!(window['webkitAudioContext'] || window['AudioContext']);
|
||||
this.webAudio = !!(window['webkitAudioContext'] || window['AudioContext']);
|
||||
|
||||
var audioElement: HTMLAudioElement = <HTMLAudioElement> document.createElement('audio');
|
||||
var result = false;
|
||||
|
@ -401,6 +440,11 @@ module Phaser {
|
|||
this.ogg = true;
|
||||
}
|
||||
|
||||
if (audioElement.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/, ''))
|
||||
{
|
||||
this.opus = true;
|
||||
}
|
||||
|
||||
if (audioElement.canPlayType('audio/mpeg;').replace(/^no$/, ''))
|
||||
{
|
||||
this.mp3 = true;
|
||||
|
@ -418,6 +462,11 @@ module Phaser {
|
|||
{
|
||||
this.m4a = true;
|
||||
}
|
||||
|
||||
if (audioElement.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/, ''))
|
||||
{
|
||||
this.webm = true;
|
||||
}
|
||||
}
|
||||
} catch (e) { }
|
||||
|
||||
|
|
|
@ -56,19 +56,28 @@ module Phaser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a tween object for a specific object.
|
||||
* Create a tween object for a specific object. The object can be any JavaScript object or Phaser object such as Sprite.
|
||||
*
|
||||
* @param object {object} Object you wish the tween will affect.
|
||||
* @param obj {object} Object the tween will be run on.
|
||||
* @param [localReference] {bool} If true the tween will be stored in the object.tween property so long as it exists. If already set it'll be over-written.
|
||||
* @return {Phaser.Tween} The newly created tween object.
|
||||
*/
|
||||
public create(object): Phaser.Tween {
|
||||
public create(object, localReference?:bool = false): Phaser.Tween {
|
||||
|
||||
return new Phaser.Tween(object, this._game);
|
||||
if (localReference)
|
||||
{
|
||||
object['tween'] = new Phaser.Tween(object, this._game);
|
||||
return object['tween'];
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Phaser.Tween(object, this._game);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an exist tween object to the manager.
|
||||
* Add a new tween into the TweenManager.
|
||||
*
|
||||
* @param tween {Phaser.Tween} The tween object you want to add.
|
||||
* @return {Phaser.Tween} The tween object you added to the manager.
|
||||
|
|
|
@ -58,13 +58,11 @@ module Phaser {
|
|||
|
||||
if (body.shapes[0].verts.length > 0)
|
||||
{
|
||||
|
||||
DebugUtils.context.fillText('Vert 1 x: ' + (body.shapes[0].verts[0].x * 50) + ' y: ' + (body.shapes[0].verts[0].y * 50), x, y + 56);
|
||||
DebugUtils.context.fillText('Vert 2 x: ' + (body.shapes[0].verts[1].x * 50) + ' y: ' + (body.shapes[0].verts[1].y * 50), x, y + 70);
|
||||
DebugUtils.context.fillText('Vert 3 x: ' + (body.shapes[0].tverts[2].x * 50) + ' y: ' + (body.shapes[0].tverts[2].y * 50), x, y + 84);
|
||||
DebugUtils.context.fillText('Vert 4 x: ' + (body.shapes[0].tverts[3].x * 50) + ' y: ' + (body.shapes[0].tverts[3].y * 50), x, y + 98);
|
||||
|
||||
|
||||
/*
|
||||
DebugUtils.context.fillText('Vert 1 x: ' + body.shapes[0].verts[0].x.toFixed(1) + ' y: ' + body.shapes[0].verts[0].y.toFixed(1), x, y + 56);
|
||||
DebugUtils.context.fillText('Vert 2 x: ' + body.shapes[0].verts[1].x.toFixed(1) + ' y: ' + body.shapes[0].verts[1].y.toFixed(1), x, y + 70);
|
||||
|
|
17
README.md
17
README.md
|
@ -57,6 +57,16 @@ TODO:
|
|||
* Camera control method (touch/keyboard)
|
||||
* Tilemap.destroy needs doing
|
||||
* Look at the input targetObject - it doesn't seem to get cleared down all the time, maybe just a priority/alpha issue (check vis/alpha?)
|
||||
* Sprite.transform.bottomRight/Left doesn't seem to take origin into account
|
||||
* When you toggle visible of a button that is over, it doesn't disable that 'over' state (should it? probably yes)
|
||||
* Stage.opaqueBackground = 'rgb()' or null, alpha, blendMode, filters, mask, rotation+XYZ,scaleXYZ,visible
|
||||
|
||||
* Need a way for Input event to redirect to audio to unlock playback
|
||||
* AudioSprite object?
|
||||
* How to get web audio to playback from an offset
|
||||
* Stage lost to mute
|
||||
|
||||
|
||||
|
||||
V1.0.0
|
||||
|
||||
|
@ -142,6 +152,13 @@ V1.0.0
|
|||
* Fixed bug where Sprite.alpha wasn't properly reflecting Sprite.texture.alpha.
|
||||
* Fixed bug where the hand cursor would be reset on input up, even if the mouse was still over the sprite.
|
||||
* Fixed bug where pressing down then moving out of the sprite area wouldn't properly reset the input state next time you moved over the sprite.
|
||||
* Added the Sprite.tween property, really useful to avoid creating new tween vars in your local scope if you don't need them.
|
||||
* Added support for pagehide and pageshow events to Stage, hooked in to the pause/resume game methods.
|
||||
* Extended Device audio checks to include opus and webm.
|
||||
* Updated Loader and Cache so they now support loading of Audio() tags as well as Web Audio.
|
||||
* Set Input.recordPointerHistory to false, you now need to enable the pointer tracking if you wish to use it.
|
||||
* SoundManager will now automatically handle iOS touch unlocking.
|
||||
|
||||
|
||||
|
||||
V0.9.6
|
||||
|
|
|
@ -56,6 +56,14 @@
|
|||
<TypeScriptCompile Include="cameras\basic camera 1.ts" />
|
||||
<TypeScriptCompile Include="buttons\basic button.ts" />
|
||||
<TypeScriptCompile Include="buttons\basic button 2.ts" />
|
||||
<TypeScriptCompile Include="audio\play sound 1.ts" />
|
||||
<TypeScriptCompile Include="audio\audio sprites 1.ts" />
|
||||
<Content Include="audio\audio sprites 1.js">
|
||||
<DependentUpon>audio sprites 1.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="audio\play sound 1.js">
|
||||
<DependentUpon>play sound 1.ts</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="buttons\basic button 2.js">
|
||||
<DependentUpon>basic button 2.ts</DependentUpon>
|
||||
</Content>
|
||||
|
|
BIN
Tests/assets/mp3/oedipus_wizball_highscore.ogg
Normal file
BIN
Tests/assets/mp3/oedipus_wizball_highscore.ogg
Normal file
Binary file not shown.
84
Tests/assets/mp3/oedipus_wizball_highscore.xmp
Normal file
84
Tests/assets/mp3/oedipus_wizball_highscore.xmp
Normal file
|
@ -0,0 +1,84 @@
|
|||
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
|
||||
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27 ">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:xmpDM="http://ns.adobe.com/xmp/1.0/DynamicMedia/">
|
||||
<xmpDM:Tracks>
|
||||
<rdf:Bag>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpDM:trackName>CuePoint Markers</xmpDM:trackName>
|
||||
<xmpDM:trackType>Cue</xmpDM:trackType>
|
||||
<xmpDM:frameRate>f44100</xmpDM:frameRate>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<xmpDM:trackName>Subclip Markers</xmpDM:trackName>
|
||||
<xmpDM:trackType>InOut</xmpDM:trackType>
|
||||
<xmpDM:frameRate>f44100</xmpDM:frameRate>
|
||||
</rdf:li>
|
||||
</rdf:Bag>
|
||||
</xmpDM:Tracks>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:xmp="http://ns.adobe.com/xap/1.0/">
|
||||
<xmp:MetadataDate>2013-07-16T02:39:59+01:00</xmp:MetadataDate>
|
||||
<xmp:ModifyDate>2013-07-16T02:39:59+01:00</xmp:ModifyDate>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
|
||||
xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#"
|
||||
xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#">
|
||||
<xmpMM:InstanceID>xmp.iid:CF0377343CEDE211B46AA47009D9EF1D</xmpMM:InstanceID>
|
||||
<xmpMM:DocumentID>xmp.did:CF0377343CEDE211B46AA47009D9EF1D</xmpMM:DocumentID>
|
||||
<xmpMM:OriginalDocumentID>xmp.did:CE0377343CEDE211B46AA47009D9EF1D</xmpMM:OriginalDocumentID>
|
||||
<xmpMM:History>
|
||||
<rdf:Seq>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<stEvt:action>saved</stEvt:action>
|
||||
<stEvt:instanceID>xmp.iid:CE0377343CEDE211B46AA47009D9EF1D</stEvt:instanceID>
|
||||
<stEvt:when>2013-07-16T02:39:59+01:00</stEvt:when>
|
||||
<stEvt:softwareAgent>Adobe Audition CS6 (Windows)</stEvt:softwareAgent>
|
||||
<stEvt:changed>/metadata</stEvt:changed>
|
||||
</rdf:li>
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<stEvt:action>saved</stEvt:action>
|
||||
<stEvt:instanceID>xmp.iid:CF0377343CEDE211B46AA47009D9EF1D</stEvt:instanceID>
|
||||
<stEvt:when>2013-07-16T02:39:59+01:00</stEvt:when>
|
||||
<stEvt:softwareAgent>Adobe Audition CS6 (Windows)</stEvt:softwareAgent>
|
||||
<stEvt:changed>/</stEvt:changed>
|
||||
</rdf:li>
|
||||
</rdf:Seq>
|
||||
</xmpMM:History>
|
||||
<xmpMM:DerivedFrom rdf:parseType="Resource">
|
||||
<stRef:instanceID>xmp.iid:CE0377343CEDE211B46AA47009D9EF1D</stRef:instanceID>
|
||||
<stRef:documentID>xmp.did:CE0377343CEDE211B46AA47009D9EF1D</stRef:documentID>
|
||||
<stRef:originalDocumentID>xmp.did:CE0377343CEDE211B46AA47009D9EF1D</stRef:originalDocumentID>
|
||||
</xmpMM:DerivedFrom>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<dc:format>audio/ogg; codec="vorbis"</dc:format>
|
||||
</rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<?xpacket end="w"?>
|
44
Tests/audio/audio sprites 1.js
Normal file
44
Tests/audio/audio sprites 1.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../Phaser/sound/SoundManager.ts" />
|
||||
/// <reference path="../../Phaser/sound/Sound.ts" />
|
||||
//var PhaserGlobal = { disableWebAudio: true };
|
||||
(function () {
|
||||
var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render);
|
||||
function init() {
|
||||
game.load.audio('rabbit', [
|
||||
'assets/mp3/peter_rabbit.m4a',
|
||||
'assets/mp3/peter_rabbit.mp3',
|
||||
'assets/mp3/peter_rabbit.ogg'
|
||||
]);
|
||||
game.load.spritesheet('button', 'assets/buttons/button_sprite_sheet.png', 193, 71);
|
||||
game.load.start();
|
||||
}
|
||||
audioSprite:
|
||||
Phaser.Sound
|
||||
button:
|
||||
Phaser.Button
|
||||
pause:
|
||||
Phaser.Button
|
||||
function create() {
|
||||
this.audioSprite = game.add.audio('rabbit');
|
||||
this.audioSprite.addMarker('title', 3.00, 5.00, 1, true);
|
||||
this.audioSprite.addMarker('help', 6.00, 12.00);
|
||||
this.audioSprite.addMarker('intro', 14.00, 19.00);
|
||||
this.audioSprite.addMarker('peter', 20.00, 21.50);
|
||||
this.button = game.add.button(game.stage.centerX, 400, 'button', playMusic, this, 2, 1, 0);
|
||||
//this.pause = game.add.button(200, 200, 'button', togglePause, this, 2, 1, 0);
|
||||
}
|
||||
function playMusic() {
|
||||
this.audioSprite.play('help');
|
||||
}
|
||||
function render() {
|
||||
this.audioSprite.renderDebug(32, 32);
|
||||
}
|
||||
function togglePause() {
|
||||
if(this.music.paused) {
|
||||
this.music.resume();
|
||||
} else {
|
||||
this.music.pause();
|
||||
}
|
||||
}
|
||||
})();
|
58
Tests/audio/audio sprites 1.ts
Normal file
58
Tests/audio/audio sprites 1.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../Phaser/sound/SoundManager.ts" />
|
||||
/// <reference path="../../Phaser/sound/Sound.ts" />
|
||||
|
||||
//var PhaserGlobal = { disableWebAudio: true };
|
||||
|
||||
(function () {
|
||||
|
||||
var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render);
|
||||
|
||||
function init() {
|
||||
|
||||
game.load.audio('rabbit', ['assets/mp3/peter_rabbit.m4a', 'assets/mp3/peter_rabbit.mp3', 'assets/mp3/peter_rabbit.ogg']);
|
||||
game.load.spritesheet('button', 'assets/buttons/button_sprite_sheet.png', 193, 71);
|
||||
game.load.start();
|
||||
|
||||
}
|
||||
|
||||
audioSprite: Phaser.Sound;
|
||||
button: Phaser.Button;
|
||||
pause: Phaser.Button;
|
||||
|
||||
function create() {
|
||||
|
||||
this.audioSprite = game.add.audio('rabbit');
|
||||
this.audioSprite.addMarker('title', 3.00, 5.00, 1, true);
|
||||
this.audioSprite.addMarker('help', 6.00, 12.00);
|
||||
this.audioSprite.addMarker('intro', 14.00, 19.00);
|
||||
this.audioSprite.addMarker('peter', 20.00, 21.50);
|
||||
|
||||
this.button = game.add.button(game.stage.centerX, 400, 'button', playMusic, this, 2, 1, 0);
|
||||
//this.pause = game.add.button(200, 200, 'button', togglePause, this, 2, 1, 0);
|
||||
|
||||
}
|
||||
|
||||
function playMusic() {
|
||||
this.audioSprite.play('help');
|
||||
}
|
||||
|
||||
function render() {
|
||||
this.audioSprite.renderDebug(32, 32);
|
||||
}
|
||||
|
||||
function togglePause() {
|
||||
|
||||
if (this.music.paused)
|
||||
{
|
||||
this.music.resume();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.music.pause();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
})();
|
55
Tests/audio/play sound 1.js
Normal file
55
Tests/audio/play sound 1.js
Normal file
|
@ -0,0 +1,55 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../Phaser/sound/SoundManager.ts" />
|
||||
/// <reference path="../../Phaser/sound/Sound.ts" />
|
||||
//var PhaserGlobal = { fakeiOSTouchLock: true, disableWebAudio: true };
|
||||
(function () {
|
||||
var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render);
|
||||
function init() {
|
||||
//game.load.audio('wizball', ['assets/mp3/oedipus_wizball_highscore.ogg', 'assets/mp3/oedipus_wizball_highscore.mp3']);
|
||||
game.load.audio('boden', [
|
||||
'assets/mp3/bodenstaendig_2000_in_rock_4bit.mp3'
|
||||
]);
|
||||
game.load.spritesheet('button', 'assets/buttons/button_sprite_sheet.png', 193, 71);
|
||||
game.load.start();
|
||||
}
|
||||
button:
|
||||
Phaser.Button
|
||||
music:
|
||||
Phaser.Sound
|
||||
volumeUp:
|
||||
Phaser.Button
|
||||
volumeDown:
|
||||
Phaser.Button
|
||||
pause:
|
||||
Phaser.Button
|
||||
function create() {
|
||||
this.music = game.add.audio('boden');
|
||||
this.button = game.add.button(game.stage.centerX, 400, 'button', playMusic, this, 2, 1, 0);
|
||||
//this.volumeUp = game.add.button(0, 0, 'button', volUp, this, 2, 1, 0);
|
||||
//this.volumeDown = game.add.button(700, 0, 'button', volDown, this, 2, 1, 0);
|
||||
//this.pause = game.add.button(200, 200, 'button', togglePause, this, 2, 1, 0);
|
||||
}
|
||||
function render() {
|
||||
this.music.renderDebug(0, 300);
|
||||
}
|
||||
function togglePause() {
|
||||
if(this.music.paused) {
|
||||
this.music.resume();
|
||||
} else {
|
||||
this.music.pause();
|
||||
}
|
||||
}
|
||||
function volUp() {
|
||||
//game.sound.volume += 0.1;
|
||||
this.music.volume += 0.1;
|
||||
console.log('vol up', game.sound.volume);
|
||||
}
|
||||
function volDown() {
|
||||
//game.sound.volume -= 0.1;
|
||||
this.music.volume -= 0.1;
|
||||
console.log('vol down', game.sound.volume);
|
||||
}
|
||||
function playMusic() {
|
||||
this.music.play();
|
||||
}
|
||||
})();
|
70
Tests/audio/play sound 1.ts
Normal file
70
Tests/audio/play sound 1.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../Phaser/sound/SoundManager.ts" />
|
||||
/// <reference path="../../Phaser/sound/Sound.ts" />
|
||||
|
||||
//var PhaserGlobal = { fakeiOSTouchLock: true, disableWebAudio: true };
|
||||
|
||||
(function () {
|
||||
|
||||
var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render);
|
||||
|
||||
function init() {
|
||||
|
||||
//game.load.audio('wizball', ['assets/mp3/oedipus_wizball_highscore.ogg', 'assets/mp3/oedipus_wizball_highscore.mp3']);
|
||||
game.load.audio('boden', ['assets/mp3/bodenstaendig_2000_in_rock_4bit.mp3']);
|
||||
game.load.spritesheet('button', 'assets/buttons/button_sprite_sheet.png', 193, 71);
|
||||
game.load.start();
|
||||
|
||||
}
|
||||
|
||||
button: Phaser.Button;
|
||||
music: Phaser.Sound;
|
||||
volumeUp: Phaser.Button;
|
||||
volumeDown: Phaser.Button;
|
||||
pause: Phaser.Button;
|
||||
|
||||
function create() {
|
||||
|
||||
this.music = game.add.audio('boden');
|
||||
|
||||
this.button = game.add.button(game.stage.centerX, 400, 'button', playMusic, this, 2, 1, 0);
|
||||
//this.volumeUp = game.add.button(0, 0, 'button', volUp, this, 2, 1, 0);
|
||||
//this.volumeDown = game.add.button(700, 0, 'button', volDown, this, 2, 1, 0);
|
||||
//this.pause = game.add.button(200, 200, 'button', togglePause, this, 2, 1, 0);
|
||||
|
||||
}
|
||||
|
||||
function render() {
|
||||
this.music.renderDebug(0, 300);
|
||||
}
|
||||
|
||||
function togglePause() {
|
||||
|
||||
if (this.music.paused)
|
||||
{
|
||||
this.music.resume();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.music.pause();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function volUp() {
|
||||
//game.sound.volume += 0.1;
|
||||
this.music.volume += 0.1;
|
||||
console.log('vol up', game.sound.volume);
|
||||
}
|
||||
|
||||
function volDown() {
|
||||
//game.sound.volume -= 0.1;
|
||||
this.music.volume -= 0.1;
|
||||
console.log('vol down', game.sound.volume);
|
||||
}
|
||||
|
||||
function playMusic() {
|
||||
this.music.play();
|
||||
}
|
||||
|
||||
})();
|
956
Tests/phaser.js
956
Tests/phaser.js
File diff suppressed because it is too large
Load diff
|
@ -16,15 +16,26 @@
|
|||
atari = game.add.physicsSprite(300, 450, 'atari', null, Phaser.Types.BODY_STATIC);
|
||||
//atari.rotation = 10;
|
||||
//atari.body.transform.setRotation(1);
|
||||
atari.body.angle = 1;
|
||||
//atari.body.angle = 1;
|
||||
atari.body.setTransform(atari.body.position, 1);
|
||||
atari.body.syncTransform();
|
||||
// atari = 220px width (110 = center x)
|
||||
// ball = 32px width (16 = center x)
|
||||
// Ball will be a dynamic body and fall based on gravity
|
||||
ball = game.add.physicsSprite(300 - 20, 0, 'ball');
|
||||
ball.body.angle = 1;
|
||||
//ball.body.angle = 1;
|
||||
//ball.body.transform.setRotation(1);
|
||||
//ball.body.fixedRotation = true;
|
||||
}
|
||||
// limit the velocity or things can go nuts
|
||||
ball.body.linearDamping = 0.5;
|
||||
ball.body.angularDamping = 0.5;
|
||||
// when the ball bounces out of the game world, call the resetBall function
|
||||
ball.outOfBoundsAction = Phaser.Types.OUT_OF_BOUNDS_PERSIST;
|
||||
ball.events.onOutOfBounds.add(resetBall, this);
|
||||
}
|
||||
function resetBall() {
|
||||
ball.body.setPosition(300, 0);
|
||||
}
|
||||
function render() {
|
||||
Phaser.DebugUtils.renderPhysicsBodyInfo(atari.body, 32, 32);
|
||||
Phaser.DebugUtils.renderPhysicsBodyInfo(ball.body, 320, 32);
|
||||
|
|
|
@ -25,17 +25,31 @@
|
|||
atari = game.add.physicsSprite(300, 450, 'atari', null, Phaser.Types.BODY_STATIC);
|
||||
//atari.rotation = 10;
|
||||
//atari.body.transform.setRotation(1);
|
||||
atari.body.angle = 1;
|
||||
//atari.body.angle = 1;
|
||||
atari.body.setTransform(atari.body.position, 1);
|
||||
atari.body.syncTransform();
|
||||
|
||||
// atari = 220px width (110 = center x)
|
||||
// ball = 32px width (16 = center x)
|
||||
|
||||
// Ball will be a dynamic body and fall based on gravity
|
||||
ball = game.add.physicsSprite(300-20, 0, 'ball');
|
||||
ball.body.angle = 1;
|
||||
//ball.body.angle = 1;
|
||||
//ball.body.transform.setRotation(1);
|
||||
//ball.body.fixedRotation = true;
|
||||
|
||||
// limit the velocity or things can go nuts
|
||||
ball.body.linearDamping = 0.5;
|
||||
ball.body.angularDamping = 0.5;
|
||||
|
||||
// when the ball bounces out of the game world, call the resetBall function
|
||||
ball.outOfBoundsAction = Phaser.Types.OUT_OF_BOUNDS_PERSIST;
|
||||
ball.events.onOutOfBounds.add(resetBall, this);
|
||||
|
||||
}
|
||||
|
||||
function resetBall() {
|
||||
ball.body.setPosition(300, 0);
|
||||
}
|
||||
|
||||
function render() {
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
game.load.image('bunny', 'assets/sprites/bunny.png');
|
||||
game.load.start();
|
||||
}
|
||||
var bunny;
|
||||
function create() {
|
||||
// Here we'll assign the new sprite to the local smallBunny variable
|
||||
bunny = game.add.sprite(0, 0, 'bunny');
|
||||
// Here we'll assign the new sprite to the local bunny variable
|
||||
var bunny = game.add.sprite(0, 0, 'bunny');
|
||||
// And this sets the alpha of the sprite to 0.5, which is 50% opaque
|
||||
bunny.alpha = 0.5;
|
||||
}
|
||||
})();
|
||||
|
|
249
build/phaser.d.ts
vendored
249
build/phaser.d.ts
vendored
|
@ -856,6 +856,9 @@ module Phaser {
|
|||
static BODY_STATIC: number;
|
||||
static BODY_KINETIC: number;
|
||||
static BODY_DYNAMIC: number;
|
||||
static OUT_OF_BOUNDS_KILL: number;
|
||||
static OUT_OF_BOUNDS_DESTROY: number;
|
||||
static OUT_OF_BOUNDS_PERSIST: number;
|
||||
/**
|
||||
* Flag used to allow GameObjects to collide on their left side
|
||||
* @type {number}
|
||||
|
@ -2384,6 +2387,9 @@ module Phaser.Components.Sprite {
|
|||
* Dispatched by the Animation component when the Sprite animation loops
|
||||
*/
|
||||
public onAnimationLoop: Signal;
|
||||
/**
|
||||
* Dispatched by the Sprite when it first leaves the world bounds
|
||||
*/
|
||||
public onOutOfBounds: Signal;
|
||||
}
|
||||
}
|
||||
|
@ -3176,6 +3182,8 @@ module Phaser.Physics {
|
|||
public removeShape(shape): void;
|
||||
private setMass(mass);
|
||||
private setInertia(inertia);
|
||||
private _newPosition;
|
||||
public setPosition(x: number, y: number): void;
|
||||
public setTransform(pos: Vec2, angle: number): void;
|
||||
public syncTransform(): void;
|
||||
public getWorldPoint(p: Vec2): Vec2;
|
||||
|
@ -3252,6 +3260,15 @@ module Phaser {
|
|||
*/
|
||||
public alive: bool;
|
||||
/**
|
||||
* Is the Sprite out of the world bounds or not?
|
||||
*/
|
||||
public outOfBounds: bool;
|
||||
/**
|
||||
* The action to be taken when the sprite is fully out of the world bounds
|
||||
* Defaults to Phaser.Types.OUT_OF_BOUNDS_KILL
|
||||
*/
|
||||
public outOfBoundsAction: number;
|
||||
/**
|
||||
* Sprite physics body.
|
||||
*/
|
||||
public body: Physics.Body;
|
||||
|
@ -3287,6 +3304,10 @@ module Phaser {
|
|||
*/
|
||||
public cameraView: Rectangle;
|
||||
/**
|
||||
* A local tween variable. Used by the TweenManager when setting a tween on this sprite or a property of it.
|
||||
*/
|
||||
public tween: Tween;
|
||||
/**
|
||||
* A boolean representing if the Sprite has been modified in any way via a scale, rotate, flip or skew.
|
||||
*/
|
||||
public modified: bool;
|
||||
|
@ -3356,7 +3377,7 @@ module Phaser {
|
|||
*/
|
||||
public update(): void;
|
||||
/**
|
||||
* Automatically called after update() by the game loop.
|
||||
* Automatically called after update() by the game loop for all 'alive' objects.
|
||||
*/
|
||||
public postUpdate(): void;
|
||||
/**
|
||||
|
@ -4278,9 +4299,10 @@ module Phaser {
|
|||
/**
|
||||
* Add a new audio file loading request.
|
||||
* @param key {string} Unique asset key of the audio file.
|
||||
* @param url {string} URL of audio file.
|
||||
* @param urls {Array} An array containing the URLs of the audio files, i.e.: [ 'jump.mp3', 'jump.ogg', 'jump.m4a' ]
|
||||
* @param autoDecode {boolean} When using Web Audio the audio files can either be decoded at load time or run-time. They can't be played until they are decoded, but this let's you control when that happens. Decoding is a non-blocking async process.
|
||||
*/
|
||||
public audio(key: string, url: string): void;
|
||||
public audio(key: string, urls: string[], autoDecode?: bool): void;
|
||||
/**
|
||||
* Add a new text file loading request.
|
||||
* @param key {string} Unique asset key of the text file.
|
||||
|
@ -4306,6 +4328,7 @@ module Phaser {
|
|||
* Load files. Private method ONLY used by loader.
|
||||
*/
|
||||
private loadFile();
|
||||
private getAudioURL(urls);
|
||||
/**
|
||||
* Error occured when load a file.
|
||||
* @param key {string} Key of the error loading file.
|
||||
|
@ -4415,11 +4438,14 @@ module Phaser {
|
|||
* @param url {string} URL of this sound file.
|
||||
* @param data {object} Extra sound data.
|
||||
*/
|
||||
public addSound(key: string, url: string, data): void;
|
||||
public addSound(key: string, url: string, data, webAudio?: bool, audioTag?: bool): void;
|
||||
public reloadSound(key: string): void;
|
||||
public onSoundUnlock: Signal;
|
||||
public reloadSoundComplete(key: string): void;
|
||||
public updateSound(key: string, property: string, value): void;
|
||||
/**
|
||||
* Add a new decoded sound.
|
||||
* @param key {string} Asset key for the sound.
|
||||
* @param url {string} URL of this sound file.
|
||||
* @param data {object} Extra sound data.
|
||||
*/
|
||||
public decodedSound(key: string, data): void;
|
||||
|
@ -4449,11 +4475,17 @@ module Phaser {
|
|||
*/
|
||||
public getFrameData(key: string): FrameData;
|
||||
/**
|
||||
* Get sound by key.
|
||||
* @param key Asset key of the sound you want.
|
||||
* @return {object} The sound you want.
|
||||
*/
|
||||
public getSound(key: string);
|
||||
/**
|
||||
* Get sound data by key.
|
||||
* @param key Asset key of the sound you want.
|
||||
* @return {object} The sound data you want.
|
||||
*/
|
||||
public getSound(key: string);
|
||||
public getSoundData(key: string);
|
||||
/**
|
||||
* Check whether an asset is decoded sound.
|
||||
* @param key Asset key of the sound you want.
|
||||
|
@ -4461,6 +4493,12 @@ module Phaser {
|
|||
*/
|
||||
public isSoundDecoded(key: string): bool;
|
||||
/**
|
||||
* Check whether an asset is decoded sound.
|
||||
* @param key Asset key of the sound you want.
|
||||
* @return {object} The sound data you want.
|
||||
*/
|
||||
public isSoundReady(key: string): bool;
|
||||
/**
|
||||
* Check whether an asset is sprite sheet.
|
||||
* @param key Asset key of the sprite sheet you want.
|
||||
* @return {object} The sprite sheet data you want.
|
||||
|
@ -5998,9 +6036,14 @@ module Phaser {
|
|||
* Create a new <code>Button</code> object.
|
||||
*
|
||||
* @param game {Phaser.Game} Current game instance.
|
||||
* @param [x] {number} the initial x position of the button.
|
||||
* @param [y] {number} the initial y position of the button.
|
||||
* @param [key] {string} Key of the graphic you want to load for this button.
|
||||
* @param [x] {number} X position of the button.
|
||||
* @param [y] {number} Y position of the button.
|
||||
* @param [key] {string} The image key as defined in the Game.Cache to use as the texture for this button.
|
||||
* @param [callback] {function} The function to call when this button is pressed
|
||||
* @param [callbackContext] {object} The context in which the callback will be called (usually 'this')
|
||||
* @param [overFrame] {string|number} This is the frame or frameName that will be set when this button is in an over state. Give either a number to use a frame ID or a string for a frame name.
|
||||
* @param [outFrame] {string|number} This is the frame or frameName that will be set when this button is in an out state. Give either a number to use a frame ID or a string for a frame name.
|
||||
* @param [downFrame] {string|number} This is the frame or frameName that will be set when this button is in a down state. Give either a number to use a frame ID or a string for a frame name.
|
||||
*/
|
||||
constructor(game: Game, x?: number, y?: number, key?: string, callback?, callbackContext?, overFrame?, outFrame?, downFrame?);
|
||||
private _onOverFrameName;
|
||||
|
@ -6780,6 +6823,7 @@ module Phaser {
|
|||
* @returns {Sprite} The newly created sprite object.
|
||||
*/
|
||||
public sprite(x: number, y: number, key?: string, frame?, bodyType?: number): Sprite;
|
||||
public audio(key: string, volume?: number, loop?: bool): Sound;
|
||||
/**
|
||||
* Create a new Sprite with the physics automatically created and set to DYNAMIC. The Sprite position offset is set to its center.
|
||||
*
|
||||
|
@ -6846,12 +6890,13 @@ module Phaser {
|
|||
*/
|
||||
public tilemap(key: string, mapData: string, format: number, resizeWorld?: bool, tileWidth?: number, tileHeight?: number): Tilemap;
|
||||
/**
|
||||
* Create a tween object for a specific object.
|
||||
* Create a tween object for a specific object. The object can be any JavaScript object or Phaser object such as Sprite.
|
||||
*
|
||||
* @param obj Object you wish the tween will affect.
|
||||
* @param obj {object} Object the tween will be run on.
|
||||
* @param [localReference] {bool} If true the tween will be stored in the object.tween property so long as it exists. If already set it'll be over-written.
|
||||
* @return {Phaser.Tween} The newly created tween object.
|
||||
*/
|
||||
public tween(obj): Tween;
|
||||
public tween(obj, localReference?: bool): Tween;
|
||||
/**
|
||||
* Add an existing Sprite to the current world.
|
||||
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
|
||||
|
@ -6861,6 +6906,14 @@ module Phaser {
|
|||
*/
|
||||
public existingSprite(sprite: Sprite): Sprite;
|
||||
/**
|
||||
* Add an existing Button to the current world.
|
||||
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
|
||||
*
|
||||
* @param button The Button to add to the Game World
|
||||
* @return {Phaser.Button} The Button object
|
||||
*/
|
||||
public existingButton(button: Button): Button;
|
||||
/**
|
||||
* Add an existing Emitter to the current world.
|
||||
* Note: This doesn't check or update the objects reference to Game. If that is wrong, all kinds of things will break.
|
||||
*
|
||||
|
@ -6903,27 +6956,29 @@ module Phaser {
|
|||
class Sound {
|
||||
/**
|
||||
* Sound constructor
|
||||
* @param context {object} The AudioContext instance.
|
||||
* @param gainNode {object} Gain node instance.
|
||||
* @param data {object} Sound data.
|
||||
* @param [volume] {number} volume of this sound when playing.
|
||||
* @param [loop] {boolean} loop this sound when playing? (Default to false)
|
||||
*/
|
||||
constructor(context, gainNode, data, volume?: number, loop?: bool);
|
||||
constructor(game: Game, key: string, volume?: number, loop?: bool);
|
||||
private soundHasUnlocked(key);
|
||||
/**
|
||||
* Local private reference to AudioContext.
|
||||
* Local reference to the current Phaser.Game.
|
||||
*/
|
||||
private _context;
|
||||
public game: Game;
|
||||
/**
|
||||
* Reference to AudioContext instance.
|
||||
*/
|
||||
public context;
|
||||
/**
|
||||
* Reference to gain node of SoundManager.
|
||||
*/
|
||||
private _gainNode;
|
||||
public masterGainNode;
|
||||
/**
|
||||
* GainNode of this sound.
|
||||
*/
|
||||
private _localGainNode;
|
||||
public gainNode;
|
||||
/**
|
||||
* Decoded data buffer.
|
||||
* Decoded data buffer / Audio tag.
|
||||
*/
|
||||
private _buffer;
|
||||
/**
|
||||
|
@ -6934,28 +6989,66 @@ module Phaser {
|
|||
* The real sound object (buffer source).
|
||||
*/
|
||||
private _sound;
|
||||
public loop: bool;
|
||||
private _muteVolume;
|
||||
private _muted;
|
||||
private _tempPosition;
|
||||
private _tempVolume;
|
||||
private _tempLoop;
|
||||
private _tempMarker;
|
||||
public usingWebAudio: bool;
|
||||
public usingAudioTag: bool;
|
||||
public name: string;
|
||||
public autoplay: bool;
|
||||
public totalDuration: number;
|
||||
public startTime: number;
|
||||
public currentTime: number;
|
||||
public duration: number;
|
||||
public stopTime: number;
|
||||
public position: number;
|
||||
public paused: bool;
|
||||
public loop: bool;
|
||||
public isPlaying: bool;
|
||||
public isDecoding: bool;
|
||||
public setDecodedBuffer(data): void;
|
||||
public key: string;
|
||||
public markers;
|
||||
public currentMarker: string;
|
||||
public onDecoded: Signal;
|
||||
public onPlay: Signal;
|
||||
public onPause: Signal;
|
||||
public onResume: Signal;
|
||||
public onLoop: Signal;
|
||||
public onStop: Signal;
|
||||
public onMute: Signal;
|
||||
public pendingPlayback: bool;
|
||||
public isDecoding : bool;
|
||||
public isDecoded : bool;
|
||||
public addMarker(name: string, start: number, stop: number, volume?: number, loop?: bool): void;
|
||||
public removeMarker(name: string): void;
|
||||
public update(): void;
|
||||
/**
|
||||
* Play this sound.
|
||||
* Play this sound, or a marked section of it.
|
||||
* @param marker {string} Assets key of the sound you want to play.
|
||||
* @param [volume] {number} volume of the sound you want to play.
|
||||
* @param [loop] {boolean} loop when it finished playing? (Default to false)
|
||||
* @return {Sound} The playing sound object.
|
||||
*/
|
||||
public play(): void;
|
||||
public play(marker?: string, position?: number, volume?: number, loop?: bool, forceRestart?: bool): void;
|
||||
public restart(marker?: string, position?: number, volume?: number, loop?: bool): void;
|
||||
public pause(): void;
|
||||
public resume(): void;
|
||||
/**
|
||||
* Stop playing this sound.
|
||||
*/
|
||||
public stop(): void;
|
||||
/**
|
||||
* Mute the sound.
|
||||
* Mute sounds.
|
||||
*/
|
||||
public mute(): void;
|
||||
/**
|
||||
* Enable the sound.
|
||||
*/
|
||||
public unmute(): void;
|
||||
public mute : bool;
|
||||
public volume : number;
|
||||
/**
|
||||
* Renders the Pointer.circle object onto the stage in green if down or red if up.
|
||||
* @method renderDebug
|
||||
*/
|
||||
public renderDebug(x: number, y: number): void;
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -6970,47 +7063,53 @@ module Phaser {
|
|||
* Create a new <code>SoundManager</code>.
|
||||
*/
|
||||
constructor(game: Game);
|
||||
public usingWebAudio: bool;
|
||||
public usingAudioTag: bool;
|
||||
public noAudio: bool;
|
||||
/**
|
||||
* Local private reference to game.
|
||||
* Local reference to the current Phaser.Game.
|
||||
*/
|
||||
private _game;
|
||||
public game: Game;
|
||||
/**
|
||||
* Reference to AudioContext instance.
|
||||
*/
|
||||
private _context;
|
||||
public context;
|
||||
/**
|
||||
* Gain node created from audio context.
|
||||
* The Master Gain node through which all sounds
|
||||
*/
|
||||
private _gainNode;
|
||||
public masterGain;
|
||||
/**
|
||||
* Volume of sounds.
|
||||
* @type {number}
|
||||
*/
|
||||
private _volume;
|
||||
private _sounds;
|
||||
private _muteVolume;
|
||||
private _muted;
|
||||
public channels: number;
|
||||
public touchLocked: bool;
|
||||
private _unlockSource;
|
||||
public unlock(): void;
|
||||
/**
|
||||
* Mute sounds.
|
||||
* A global audio mute toggle.
|
||||
*/
|
||||
public mute(): void;
|
||||
public mute : bool;
|
||||
/**
|
||||
* Enable sounds.
|
||||
* The global audio volume. A value between 0 (silence) and 1 (full volume)
|
||||
*/
|
||||
public unmute(): void;
|
||||
public volume : number;
|
||||
public stopAll(): void;
|
||||
public pauseAll(): void;
|
||||
public resumeAll(): void;
|
||||
/**
|
||||
* Decode a sound with its assets key.
|
||||
* @param key {string} Assets key of the sound to be decoded.
|
||||
* @param callback {function} This will be invoked when finished decoding.
|
||||
* @param [sound] {Sound} its bufer will be set to decoded data.
|
||||
*/
|
||||
public decode(key: string, callback?, sound?: Sound): void;
|
||||
/**
|
||||
* Play a sound with its assets key.
|
||||
* @param key {string} Assets key of the sound you want to play.
|
||||
* @param [volume] {number} volume of the sound you want to play.
|
||||
* @param [loop] {boolean} loop when it finished playing? (Default to false)
|
||||
* @return {Sound} The playing sound object.
|
||||
*/
|
||||
public play(key: string, volume?: number, loop?: bool): Sound;
|
||||
public decode(key: string, sound?: Sound): void;
|
||||
public onSoundDecode: Signal;
|
||||
public update(): void;
|
||||
public add(key: string, volume?: number, loop?: bool): Sound;
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -7656,14 +7755,15 @@ module Phaser {
|
|||
*/
|
||||
public removeAll(): void;
|
||||
/**
|
||||
* Create a tween object for a specific object.
|
||||
* Create a tween object for a specific object. The object can be any JavaScript object or Phaser object such as Sprite.
|
||||
*
|
||||
* @param object {object} Object you wish the tween will affect.
|
||||
* @param obj {object} Object the tween will be run on.
|
||||
* @param [localReference] {bool} If true the tween will be stored in the object.tween property so long as it exists. If already set it'll be over-written.
|
||||
* @return {Phaser.Tween} The newly created tween object.
|
||||
*/
|
||||
public create(object): Tween;
|
||||
public create(object, localReference?: bool): Tween;
|
||||
/**
|
||||
* Add an exist tween object to the manager.
|
||||
* Add a new tween into the TweenManager.
|
||||
*
|
||||
* @param tween {Phaser.Tween} The tween object you want to add.
|
||||
* @return {Phaser.Tween} The tween object you added to the manager.
|
||||
|
@ -8070,36 +8170,46 @@ module Phaser {
|
|||
public safari: bool;
|
||||
public webApp: bool;
|
||||
/**
|
||||
* Is audioData available?
|
||||
* Are Audio tags available?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public audioData: bool;
|
||||
/**
|
||||
* Is webaudio available?
|
||||
* Is the WebAudio API available?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public webaudio: bool;
|
||||
public webAudio: bool;
|
||||
/**
|
||||
* Is ogg available?
|
||||
* Can this device play ogg files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public ogg: bool;
|
||||
/**
|
||||
* Is mp3 available?
|
||||
* Can this device play opus files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public opus: bool;
|
||||
/**
|
||||
* Can this device play mp3 files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public mp3: bool;
|
||||
/**
|
||||
* Is wav available?
|
||||
* Can this device play wav files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public wav: bool;
|
||||
/**
|
||||
* Is m4a available?
|
||||
* Can this device play m4a files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public m4a: bool;
|
||||
/**
|
||||
* Can this device play webm files?
|
||||
* @type {boolean}
|
||||
*/
|
||||
public webm: bool;
|
||||
/**
|
||||
* Is running on iPhone?
|
||||
* @type {boolean}
|
||||
*/
|
||||
|
@ -8134,6 +8244,7 @@ module Phaser {
|
|||
* @private
|
||||
*/
|
||||
private _checkBrowser();
|
||||
public canPlayAudio(type: string): bool;
|
||||
/**
|
||||
* Check audio support.
|
||||
* @private
|
||||
|
@ -8369,6 +8480,9 @@ module Phaser {
|
|||
* @return {Phaser.Pointer} This object.
|
||||
*/
|
||||
constructor(game: Game, id: number);
|
||||
private _highestRenderOrderID;
|
||||
private _highestRenderObject;
|
||||
private _highestInputPriorityID;
|
||||
/**
|
||||
* Local private reference to game.
|
||||
* @property game
|
||||
|
@ -8546,6 +8660,12 @@ module Phaser {
|
|||
**/
|
||||
public totalTouches: number;
|
||||
/**
|
||||
* The number of miliseconds since the last click
|
||||
* @property msSinceLastClick
|
||||
* @type {Number}
|
||||
**/
|
||||
public msSinceLastClick: number;
|
||||
/**
|
||||
* How long the Pointer has been depressed on the touchscreen. If not currently down it returns -1.
|
||||
* @property duration
|
||||
* @type {Number}
|
||||
|
@ -8574,9 +8694,6 @@ module Phaser {
|
|||
*/
|
||||
public start(event): Pointer;
|
||||
public update(): void;
|
||||
private _highestRenderOrderID;
|
||||
private _highestRenderObject;
|
||||
private _highestInputPriorityID;
|
||||
/**
|
||||
* Called when the Pointer is moved on the touchscreen
|
||||
* @method move
|
||||
|
@ -9229,7 +9346,7 @@ module Phaser {
|
|||
public recordRate: number;
|
||||
/**
|
||||
* The total number of entries that can be recorded into the Pointer objects tracking history.
|
||||
* The the Pointer is tracking one event every 100ms, then a trackLimit of 100 would store the last 10 seconds worth of history.
|
||||
* If the Pointer is tracking one event every 100ms, then a trackLimit of 100 would store the last 10 seconds worth of history.
|
||||
* @property recordLimit
|
||||
* @type {Number}
|
||||
*/
|
||||
|
|
956
build/phaser.js
956
build/phaser.js
File diff suppressed because it is too large
Load diff
BIN
todo/docChanges.zip
Normal file
BIN
todo/docChanges.zip
Normal file
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
777
todo/phaser clean up/Collision.js
Normal file
777
todo/phaser clean up/Collision.js
Normal file
|
@ -0,0 +1,777 @@
|
|||
var Phaser;
|
||||
(function (Phaser) {
|
||||
var Collision = (function () {
|
||||
function Collision(game) {
|
||||
this._game = game;
|
||||
Collision.T_VECTORS = [];
|
||||
for(var i = 0; i < 10; i++) {
|
||||
Collision.T_VECTORS.push(new Vector2());
|
||||
}
|
||||
Collision.T_ARRAYS = [];
|
||||
for(var i = 0; i < 5; i++) {
|
||||
Collision.T_ARRAYS.push([]);
|
||||
}
|
||||
}
|
||||
Collision.LEFT = 0x0001;
|
||||
Collision.RIGHT = 0x0010;
|
||||
Collision.UP = 0x0100;
|
||||
Collision.DOWN = 0x1000;
|
||||
Collision.NONE = 0;
|
||||
Collision.CEILING = Phaser.Collision.UP;
|
||||
Collision.FLOOR = Phaser.Collision.DOWN;
|
||||
Collision.WALL = Phaser.Collision.LEFT | Phaser.Collision.RIGHT;
|
||||
Collision.ANY = Phaser.Collision.LEFT | Phaser.Collision.RIGHT | Phaser.Collision.UP | Phaser.Collision.DOWN;
|
||||
Collision.OVERLAP_BIAS = 4;
|
||||
Collision.TILE_OVERLAP = false;
|
||||
Collision.lineToLine = function lineToLine(line1, line2, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
var denominator = (line1.x1 - line1.x2) * (line2.y1 - line2.y2) - (line1.y1 - line1.y2) * (line2.x1 - line2.x2);
|
||||
if(denominator !== 0) {
|
||||
output.result = true;
|
||||
output.x = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (line2.x1 - line2.x2) - (line1.x1 - line1.x2) * (line2.x1 * line2.y2 - line2.y1 * line2.x2)) / denominator;
|
||||
output.y = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (line2.y1 - line2.y2) - (line1.y1 - line1.y2) * (line2.x1 * line2.y2 - line2.y1 * line2.x2)) / denominator;
|
||||
}
|
||||
return output;
|
||||
};
|
||||
Collision.lineToLineSegment = function lineToLineSegment(line, seg, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
var denominator = (line.x1 - line.x2) * (seg.y1 - seg.y2) - (line.y1 - line.y2) * (seg.x1 - seg.x2);
|
||||
if(denominator !== 0) {
|
||||
output.x = ((line.x1 * line.y2 - line.y1 * line.x2) * (seg.x1 - seg.x2) - (line.x1 - line.x2) * (seg.x1 * seg.y2 - seg.y1 * seg.x2)) / denominator;
|
||||
output.y = ((line.x1 * line.y2 - line.y1 * line.x2) * (seg.y1 - seg.y2) - (line.y1 - line.y2) * (seg.x1 * seg.y2 - seg.y1 * seg.x2)) / denominator;
|
||||
var maxX = Math.max(seg.x1, seg.x2);
|
||||
var minX = Math.min(seg.x1, seg.x2);
|
||||
var maxY = Math.max(seg.y1, seg.y2);
|
||||
var minY = Math.min(seg.y1, seg.y2);
|
||||
if((output.x <= maxX && output.x >= minX) === true || (output.y <= maxY && output.y >= minY) === true) {
|
||||
output.result = true;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
Collision.lineToRawSegment = function lineToRawSegment(line, x1, y1, x2, y2, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
var denominator = (line.x1 - line.x2) * (y1 - y2) - (line.y1 - line.y2) * (x1 - x2);
|
||||
if(denominator !== 0) {
|
||||
output.x = ((line.x1 * line.y2 - line.y1 * line.x2) * (x1 - x2) - (line.x1 - line.x2) * (x1 * y2 - y1 * x2)) / denominator;
|
||||
output.y = ((line.x1 * line.y2 - line.y1 * line.x2) * (y1 - y2) - (line.y1 - line.y2) * (x1 * y2 - y1 * x2)) / denominator;
|
||||
var maxX = Math.max(x1, x2);
|
||||
var minX = Math.min(x1, x2);
|
||||
var maxY = Math.max(y1, y2);
|
||||
var minY = Math.min(y1, y2);
|
||||
if((output.x <= maxX && output.x >= minX) === true || (output.y <= maxY && output.y >= minY) === true) {
|
||||
output.result = true;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
Collision.lineToRay = function lineToRay(line1, ray, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
var denominator = (line1.x1 - line1.x2) * (ray.y1 - ray.y2) - (line1.y1 - line1.y2) * (ray.x1 - ray.x2);
|
||||
if(denominator !== 0) {
|
||||
output.x = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (ray.x1 - ray.x2) - (line1.x1 - line1.x2) * (ray.x1 * ray.y2 - ray.y1 * ray.x2)) / denominator;
|
||||
output.y = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (ray.y1 - ray.y2) - (line1.y1 - line1.y2) * (ray.x1 * ray.y2 - ray.y1 * ray.x2)) / denominator;
|
||||
output.result = true;
|
||||
if(!(ray.x1 >= ray.x2) && output.x < ray.x1) {
|
||||
output.result = false;
|
||||
}
|
||||
if(!(ray.y1 >= ray.y2) && output.y < ray.y1) {
|
||||
output.result = false;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
Collision.lineToCircle = function lineToCircle(line, circle, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
if(line.perp(circle.x, circle.y).length <= circle.radius) {
|
||||
output.result = true;
|
||||
}
|
||||
return output;
|
||||
};
|
||||
Collision.lineToRectangle = function lineToRectangle(line, rect, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
Phaser.Collision.lineToRawSegment(line, rect.x, rect.y, rect.right, rect.y, output);
|
||||
if(output.result === true) {
|
||||
return output;
|
||||
}
|
||||
Phaser.Collision.lineToRawSegment(line, rect.x, rect.y, rect.x, rect.bottom, output);
|
||||
if(output.result === true) {
|
||||
return output;
|
||||
}
|
||||
Phaser.Collision.lineToRawSegment(line, rect.x, rect.bottom, rect.right, rect.bottom, output);
|
||||
if(output.result === true) {
|
||||
return output;
|
||||
}
|
||||
Phaser.Collision.lineToRawSegment(line, rect.right, rect.y, rect.right, rect.bottom, output);
|
||||
return output;
|
||||
};
|
||||
Collision.lineSegmentToLineSegment = function lineSegmentToLineSegment(line1, line2, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
Phaser.Collision.lineToLineSegment(line1, line2);
|
||||
if(output.result === true) {
|
||||
if(!(output.x >= Math.min(line1.x1, line1.x2) && output.x <= Math.max(line1.x1, line1.x2) && output.y >= Math.min(line1.y1, line1.y2) && output.y <= Math.max(line1.y1, line1.y2))) {
|
||||
output.result = false;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
Collision.lineSegmentToRay = function lineSegmentToRay(line, ray, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
Phaser.Collision.lineToRay(line, ray, output);
|
||||
if(output.result === true) {
|
||||
if(!(output.x >= Math.min(line.x1, line.x2) && output.x <= Math.max(line.x1, line.x2) && output.y >= Math.min(line.y1, line.y2) && output.y <= Math.max(line.y1, line.y2))) {
|
||||
output.result = false;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
Collision.lineSegmentToCircle = function lineSegmentToCircle(seg, circle, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
var perp = seg.perp(circle.x, circle.y);
|
||||
if(perp.length <= circle.radius) {
|
||||
var maxX = Math.max(seg.x1, seg.x2);
|
||||
var minX = Math.min(seg.x1, seg.x2);
|
||||
var maxY = Math.max(seg.y1, seg.y2);
|
||||
var minY = Math.min(seg.y1, seg.y2);
|
||||
if((perp.x2 <= maxX && perp.x2 >= minX) && (perp.y2 <= maxY && perp.y2 >= minY)) {
|
||||
output.result = true;
|
||||
} else {
|
||||
if(Phaser.Collision.circleContainsPoint(circle, {
|
||||
x: seg.x1,
|
||||
y: seg.y1
|
||||
}) || Phaser.Collision.circleContainsPoint(circle, {
|
||||
x: seg.x2,
|
||||
y: seg.y2
|
||||
})) {
|
||||
output.result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
Collision.lineSegmentToRectangle = function lineSegmentToRectangle(seg, rect, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
if(rect.contains(seg.x1, seg.y1) && rect.contains(seg.x2, seg.y2)) {
|
||||
output.result = true;
|
||||
} else {
|
||||
Phaser.Collision.lineToRawSegment(seg, rect.x, rect.y, rect.right, rect.bottom, output);
|
||||
if(output.result === true) {
|
||||
return output;
|
||||
}
|
||||
Phaser.Collision.lineToRawSegment(seg, rect.x, rect.y, rect.x, rect.bottom, output);
|
||||
if(output.result === true) {
|
||||
return output;
|
||||
}
|
||||
Phaser.Collision.lineToRawSegment(seg, rect.x, rect.bottom, rect.right, rect.bottom, output);
|
||||
if(output.result === true) {
|
||||
return output;
|
||||
}
|
||||
Phaser.Collision.lineToRawSegment(seg, rect.right, rect.y, rect.right, rect.bottom, output);
|
||||
return output;
|
||||
}
|
||||
return output;
|
||||
};
|
||||
Collision.rayToRectangle = function rayToRectangle(ray, rect, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
Phaser.Collision.lineToRectangle(ray, rect, output);
|
||||
return output;
|
||||
};
|
||||
Collision.rayToLineSegment = function rayToLineSegment(rayX1, rayY1, rayX2, rayY2, lineX1, lineY1, lineX2, lineY2, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
var r;
|
||||
var s;
|
||||
var d;
|
||||
if((rayY2 - rayY1) / (rayX2 - rayX1) != (lineY2 - lineY1) / (lineX2 - lineX1)) {
|
||||
d = (((rayX2 - rayX1) * (lineY2 - lineY1)) - (rayY2 - rayY1) * (lineX2 - lineX1));
|
||||
if(d != 0) {
|
||||
r = (((rayY1 - lineY1) * (lineX2 - lineX1)) - (rayX1 - lineX1) * (lineY2 - lineY1)) / d;
|
||||
s = (((rayY1 - lineY1) * (rayX2 - rayX1)) - (rayX1 - lineX1) * (rayY2 - rayY1)) / d;
|
||||
if(r >= 0) {
|
||||
if(s >= 0 && s <= 1) {
|
||||
output.result = true;
|
||||
output.x = rayX1 + r * (rayX2 - rayX1);
|
||||
output.y = rayY1 + r * (rayY2 - rayY1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
Collision.pointToRectangle = function pointToRectangle(point, rect, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
output.setTo(point.x, point.y);
|
||||
output.result = rect.containsPoint(point);
|
||||
return output;
|
||||
};
|
||||
Collision.rectangleToRectangle = function rectangleToRectangle(rect1, rect2, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
var leftX = Math.max(rect1.x, rect2.x);
|
||||
var rightX = Math.min(rect1.right, rect2.right);
|
||||
var topY = Math.max(rect1.y, rect2.y);
|
||||
var bottomY = Math.min(rect1.bottom, rect2.bottom);
|
||||
output.setTo(leftX, topY, rightX - leftX, bottomY - topY, rightX - leftX, bottomY - topY);
|
||||
var cx = output.x + output.width * .5;
|
||||
var cy = output.y + output.height * .5;
|
||||
if((cx > rect1.x && cx < rect1.right) && (cy > rect1.y && cy < rect1.bottom)) {
|
||||
output.result = true;
|
||||
}
|
||||
return output;
|
||||
};
|
||||
Collision.rectangleToCircle = function rectangleToCircle(rect, circle, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
return Phaser.Collision.circleToRectangle(circle, rect, output);
|
||||
};
|
||||
Collision.circleToCircle = function circleToCircle(circle1, circle2, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
output.result = ((circle1.radius + circle2.radius) * (circle1.radius + circle2.radius)) >= Phaser.Collision.distanceSquared(circle1.x, circle1.y, circle2.x, circle2.y);
|
||||
return output;
|
||||
};
|
||||
Collision.circleToRectangle = function circleToRectangle(circle, rect, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
var inflatedRect = rect.clone();
|
||||
inflatedRect.inflate(circle.radius, circle.radius);
|
||||
output.result = inflatedRect.contains(circle.x, circle.y);
|
||||
return output;
|
||||
};
|
||||
Collision.circleContainsPoint = function circleContainsPoint(circle, point, output) {
|
||||
if (typeof output === "undefined") { output = new Phaser.IntersectResult(); }
|
||||
output.result = circle.radius * circle.radius >= Phaser.Collision.distanceSquared(circle.x, circle.y, point.x, point.y);
|
||||
return output;
|
||||
};
|
||||
Collision.prototype.overlap = function (object1, object2, notifyCallback, processCallback, context) {
|
||||
if (typeof object1 === "undefined") { object1 = null; }
|
||||
if (typeof object2 === "undefined") { object2 = null; }
|
||||
if (typeof notifyCallback === "undefined") { notifyCallback = null; }
|
||||
if (typeof processCallback === "undefined") { processCallback = null; }
|
||||
if (typeof context === "undefined") { context = null; }
|
||||
if(object1 == null) {
|
||||
object1 = this._game.world.group;
|
||||
}
|
||||
if(object2 == object1) {
|
||||
object2 = null;
|
||||
}
|
||||
Phaser.QuadTree.divisions = this._game.world.worldDivisions;
|
||||
var quadTree = new Phaser.QuadTree(this._game.world.bounds.x, this._game.world.bounds.y, this._game.world.bounds.width, this._game.world.bounds.height);
|
||||
quadTree.load(object1, object2, notifyCallback, processCallback, context);
|
||||
var result = quadTree.execute();
|
||||
quadTree.destroy();
|
||||
quadTree = null;
|
||||
return result;
|
||||
};
|
||||
Collision.separate = function separate(object1, object2) {
|
||||
object1.collisionMask.update();
|
||||
object2.collisionMask.update();
|
||||
var separatedX = Phaser.Collision.separateX(object1, object2);
|
||||
var separatedY = Phaser.Collision.separateY(object1, object2);
|
||||
return separatedX || separatedY;
|
||||
};
|
||||
Collision.separateTile = function separateTile(object, x, y, width, height, mass, collideLeft, collideRight, collideUp, collideDown, separateX, separateY) {
|
||||
object.collisionMask.update();
|
||||
var separatedX = Phaser.Collision.separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separateX);
|
||||
var separatedY = Phaser.Collision.separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separateY);
|
||||
return separatedX || separatedY;
|
||||
};
|
||||
Collision.separateTileX = function separateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separate) {
|
||||
if(object.immovable) {
|
||||
return false;
|
||||
}
|
||||
var overlap = 0;
|
||||
var objDelta = object.x - object.last.x;
|
||||
if(objDelta != 0) {
|
||||
var objDeltaAbs = (objDelta > 0) ? objDelta : -objDelta;
|
||||
var objBounds = new Phaser.Quad(object.x - ((objDelta > 0) ? objDelta : 0), object.last.y, object.width + ((objDelta > 0) ? objDelta : -objDelta), object.height);
|
||||
if((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) {
|
||||
var maxOverlap = objDeltaAbs + Phaser.Collision.OVERLAP_BIAS;
|
||||
if(objDelta > 0) {
|
||||
overlap = object.x + object.width - x;
|
||||
if((overlap > maxOverlap) || !(object.allowCollisions & Phaser.Collision.RIGHT) || collideLeft == false) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object.touching |= Phaser.Collision.RIGHT;
|
||||
}
|
||||
} else if(objDelta < 0) {
|
||||
overlap = object.x - width - x;
|
||||
if((-overlap > maxOverlap) || !(object.allowCollisions & Phaser.Collision.LEFT) || collideRight == false) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object.touching |= Phaser.Collision.LEFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(overlap != 0) {
|
||||
if(separate == true) {
|
||||
object.x = object.x - overlap;
|
||||
object.velocity.x = -(object.velocity.x * object.elasticity);
|
||||
}
|
||||
Phaser.Collision.TILE_OVERLAP = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Collision.separateTileY = function separateTileY(object, x, y, width, height, mass, collideUp, collideDown, separate) {
|
||||
if(object.immovable) {
|
||||
return false;
|
||||
}
|
||||
var overlap = 0;
|
||||
var objDelta = object.y - object.last.y;
|
||||
if(objDelta != 0) {
|
||||
var objDeltaAbs = (objDelta > 0) ? objDelta : -objDelta;
|
||||
var objBounds = new Phaser.Quad(object.x, object.y - ((objDelta > 0) ? objDelta : 0), object.width, object.height + objDeltaAbs);
|
||||
if((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height)) {
|
||||
var maxOverlap = objDeltaAbs + Phaser.Collision.OVERLAP_BIAS;
|
||||
if(objDelta > 0) {
|
||||
overlap = object.y + object.height - y;
|
||||
if((overlap > maxOverlap) || !(object.allowCollisions & Phaser.Collision.DOWN) || collideUp == false) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object.touching |= Phaser.Collision.DOWN;
|
||||
}
|
||||
} else if(objDelta < 0) {
|
||||
overlap = object.y - height - y;
|
||||
if((-overlap > maxOverlap) || !(object.allowCollisions & Phaser.Collision.UP) || collideDown == false) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object.touching |= Phaser.Collision.UP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(overlap != 0) {
|
||||
if(separate == true) {
|
||||
object.y = object.y - overlap;
|
||||
object.velocity.y = -(object.velocity.y * object.elasticity);
|
||||
}
|
||||
Phaser.Collision.TILE_OVERLAP = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Collision.NEWseparateTileX = function NEWseparateTileX(object, x, y, width, height, mass, collideLeft, collideRight, separate) {
|
||||
if(object.immovable) {
|
||||
return false;
|
||||
}
|
||||
var overlap = 0;
|
||||
if(object.collisionMask.deltaX != 0) {
|
||||
if(object.collisionMask.intersectsRaw(x, x + width, y, y + height)) {
|
||||
var maxOverlap = object.collisionMask.deltaXAbs + Phaser.Collision.OVERLAP_BIAS;
|
||||
if(object.collisionMask.deltaX > 0) {
|
||||
overlap = object.collisionMask.right - x;
|
||||
if((overlap > maxOverlap) || !(object.allowCollisions & Phaser.Collision.RIGHT) || collideLeft == false) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object.touching |= Phaser.Collision.RIGHT;
|
||||
}
|
||||
} else if(object.collisionMask.deltaX < 0) {
|
||||
overlap = object.collisionMask.x - width - x;
|
||||
if((-overlap > maxOverlap) || !(object.allowCollisions & Phaser.Collision.LEFT) || collideRight == false) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object.touching |= Phaser.Collision.LEFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(overlap != 0) {
|
||||
if(separate == true) {
|
||||
object.x = object.x - overlap;
|
||||
object.velocity.x = -(object.velocity.x * object.elasticity);
|
||||
}
|
||||
Phaser.Collision.TILE_OVERLAP = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Collision.NEWseparateTileY = function NEWseparateTileY(object, x, y, width, height, mass, collideUp, collideDown, separate) {
|
||||
if(object.immovable) {
|
||||
return false;
|
||||
}
|
||||
var overlap = 0;
|
||||
if(object.collisionMask.deltaY != 0) {
|
||||
if(object.collisionMask.intersectsRaw(x, x + width, y, y + height)) {
|
||||
var maxOverlap = object.collisionMask.deltaYAbs + Phaser.Collision.OVERLAP_BIAS;
|
||||
if(object.collisionMask.deltaY > 0) {
|
||||
overlap = object.collisionMask.bottom - y;
|
||||
if((overlap > maxOverlap) || !(object.allowCollisions & Phaser.Collision.DOWN) || collideUp == false) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object.touching |= Phaser.Collision.DOWN;
|
||||
}
|
||||
} else if(object.collisionMask.deltaY < 0) {
|
||||
overlap = object.collisionMask.y - height - y;
|
||||
if((-overlap > maxOverlap) || !(object.allowCollisions & Phaser.Collision.UP) || collideDown == false) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object.touching |= Phaser.Collision.UP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(overlap != 0) {
|
||||
if(separate == true) {
|
||||
object.y = object.y - overlap;
|
||||
object.velocity.y = -(object.velocity.y * object.elasticity);
|
||||
}
|
||||
Phaser.Collision.TILE_OVERLAP = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Collision.separateX = function separateX(object1, object2) {
|
||||
if(object1.immovable && object2.immovable) {
|
||||
return false;
|
||||
}
|
||||
var overlap = 0;
|
||||
if(object1.collisionMask.deltaX != object2.collisionMask.deltaX) {
|
||||
if(object1.collisionMask.intersects(object2.collisionMask)) {
|
||||
var maxOverlap = object1.collisionMask.deltaXAbs + object2.collisionMask.deltaXAbs + Phaser.Collision.OVERLAP_BIAS;
|
||||
if(object1.collisionMask.deltaX > object2.collisionMask.deltaX) {
|
||||
overlap = object1.collisionMask.right - object2.collisionMask.x;
|
||||
if((overlap > maxOverlap) || !(object1.allowCollisions & Phaser.Collision.RIGHT) || !(object2.allowCollisions & Phaser.Collision.LEFT)) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object1.touching |= Phaser.Collision.RIGHT;
|
||||
object2.touching |= Phaser.Collision.LEFT;
|
||||
}
|
||||
} else if(object1.collisionMask.deltaX < object2.collisionMask.deltaX) {
|
||||
overlap = object1.collisionMask.x - object2.collisionMask.width - object2.collisionMask.x;
|
||||
if((-overlap > maxOverlap) || !(object1.allowCollisions & Phaser.Collision.LEFT) || !(object2.allowCollisions & Phaser.Collision.RIGHT)) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object1.touching |= Phaser.Collision.LEFT;
|
||||
object2.touching |= Phaser.Collision.RIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(overlap != 0) {
|
||||
var obj1Velocity = object1.velocity.x;
|
||||
var obj2Velocity = object2.velocity.x;
|
||||
if(!object1.immovable && !object2.immovable) {
|
||||
overlap *= 0.5;
|
||||
object1.x = object1.x - overlap;
|
||||
object2.x += overlap;
|
||||
var obj1NewVelocity = Math.sqrt((obj2Velocity * obj2Velocity * object2.mass) / object1.mass) * ((obj2Velocity > 0) ? 1 : -1);
|
||||
var obj2NewVelocity = Math.sqrt((obj1Velocity * obj1Velocity * object1.mass) / object2.mass) * ((obj1Velocity > 0) ? 1 : -1);
|
||||
var average = (obj1NewVelocity + obj2NewVelocity) * 0.5;
|
||||
obj1NewVelocity -= average;
|
||||
obj2NewVelocity -= average;
|
||||
object1.velocity.x = average + obj1NewVelocity * object1.elasticity;
|
||||
object2.velocity.x = average + obj2NewVelocity * object2.elasticity;
|
||||
} else if(!object1.immovable) {
|
||||
object1.x = object1.x - overlap;
|
||||
object1.velocity.x = obj2Velocity - obj1Velocity * object1.elasticity;
|
||||
} else if(!object2.immovable) {
|
||||
object2.x += overlap;
|
||||
object2.velocity.x = obj1Velocity - obj2Velocity * object2.elasticity;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Collision.separateY = function separateY(object1, object2) {
|
||||
if(object1.immovable && object2.immovable) {
|
||||
return false;
|
||||
}
|
||||
var overlap = 0;
|
||||
if(object1.collisionMask.deltaY != object2.collisionMask.deltaY) {
|
||||
if(object1.collisionMask.intersects(object2.collisionMask)) {
|
||||
var maxOverlap = object1.collisionMask.deltaYAbs + object2.collisionMask.deltaYAbs + Phaser.Collision.OVERLAP_BIAS;
|
||||
if(object1.collisionMask.deltaY > object2.collisionMask.deltaY) {
|
||||
overlap = object1.collisionMask.bottom - object2.collisionMask.y;
|
||||
if((overlap > maxOverlap) || !(object1.allowCollisions & Phaser.Collision.DOWN) || !(object2.allowCollisions & Phaser.Collision.UP)) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object1.touching |= Phaser.Collision.DOWN;
|
||||
object2.touching |= Phaser.Collision.UP;
|
||||
}
|
||||
} else if(object1.collisionMask.deltaY < object2.collisionMask.deltaY) {
|
||||
overlap = object1.collisionMask.y - object2.collisionMask.height - object2.collisionMask.y;
|
||||
if((-overlap > maxOverlap) || !(object1.allowCollisions & Phaser.Collision.UP) || !(object2.allowCollisions & Phaser.Collision.DOWN)) {
|
||||
overlap = 0;
|
||||
} else {
|
||||
object1.touching |= Phaser.Collision.UP;
|
||||
object2.touching |= Phaser.Collision.DOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(overlap != 0) {
|
||||
var obj1Velocity = object1.velocity.y;
|
||||
var obj2Velocity = object2.velocity.y;
|
||||
if(!object1.immovable && !object2.immovable) {
|
||||
overlap *= 0.5;
|
||||
object1.y = object1.y - overlap;
|
||||
object2.y += overlap;
|
||||
var obj1NewVelocity = Math.sqrt((obj2Velocity * obj2Velocity * object2.mass) / object1.mass) * ((obj2Velocity > 0) ? 1 : -1);
|
||||
var obj2NewVelocity = Math.sqrt((obj1Velocity * obj1Velocity * object1.mass) / object2.mass) * ((obj1Velocity > 0) ? 1 : -1);
|
||||
var average = (obj1NewVelocity + obj2NewVelocity) * 0.5;
|
||||
obj1NewVelocity -= average;
|
||||
obj2NewVelocity -= average;
|
||||
object1.velocity.y = average + obj1NewVelocity * object1.elasticity;
|
||||
object2.velocity.y = average + obj2NewVelocity * object2.elasticity;
|
||||
} else if(!object1.immovable) {
|
||||
object1.y = object1.y - overlap;
|
||||
object1.velocity.y = obj2Velocity - obj1Velocity * object1.elasticity;
|
||||
if(object2.active && object2.moves && (object1.collisionMask.deltaY > object2.collisionMask.deltaY)) {
|
||||
object1.x += object2.x - object2.last.x;
|
||||
}
|
||||
} else if(!object2.immovable) {
|
||||
object2.y += overlap;
|
||||
object2.velocity.y = obj1Velocity - obj2Velocity * object2.elasticity;
|
||||
if(object1.active && object1.moves && (object1.collisionMask.deltaY < object2.collisionMask.deltaY)) {
|
||||
object2.x += object1.x - object1.last.x;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Collision.distance = function distance(x1, y1, x2, y2) {
|
||||
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
|
||||
};
|
||||
Collision.distanceSquared = function distanceSquared(x1, y1, x2, y2) {
|
||||
return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
|
||||
};
|
||||
Collision.flattenPointsOn = function flattenPointsOn(points, normal, result) {
|
||||
var min = Number.MAX_VALUE;
|
||||
var max = -Number.MAX_VALUE;
|
||||
var len = points.length;
|
||||
for(var i = 0; i < len; i++) {
|
||||
var dot = points[i].dot(normal);
|
||||
if(dot < min) {
|
||||
min = dot;
|
||||
}
|
||||
if(dot > max) {
|
||||
max = dot;
|
||||
}
|
||||
}
|
||||
result[0] = min;
|
||||
result[1] = max;
|
||||
};
|
||||
Collision.isSeparatingAxis = function isSeparatingAxis(aPos, bPos, aPoints, bPoints, axis, response) {
|
||||
if (typeof response === "undefined") { response = null; }
|
||||
var rangeA = Phaser.Collision.T_ARRAYS.pop();
|
||||
var rangeB = Phaser.Collision.T_ARRAYS.pop();
|
||||
var offsetV = Phaser.Collision.T_VECTORS.pop().copyFrom(bPos).sub(aPos);
|
||||
var projectedOffset = offsetV.dot(axis);
|
||||
Phaser.Collision.flattenPointsOn(aPoints, axis, rangeA);
|
||||
Phaser.Collision.flattenPointsOn(bPoints, axis, rangeB);
|
||||
rangeB[0] += projectedOffset;
|
||||
rangeB[1] += projectedOffset;
|
||||
if(rangeA[0] > rangeB[1] || rangeB[0] > rangeA[1]) {
|
||||
Phaser.Collision.T_VECTORS.push(offsetV);
|
||||
Phaser.Collision.T_ARRAYS.push(rangeA);
|
||||
Phaser.Collision.T_ARRAYS.push(rangeB);
|
||||
return true;
|
||||
}
|
||||
if(response) {
|
||||
var overlap = 0;
|
||||
if(rangeA[0] < rangeB[0]) {
|
||||
response.aInB = false;
|
||||
if(rangeA[1] < rangeB[1]) {
|
||||
overlap = rangeA[1] - rangeB[0];
|
||||
response.bInA = false;
|
||||
} else {
|
||||
var option1 = rangeA[1] - rangeB[0];
|
||||
var option2 = rangeB[1] - rangeA[0];
|
||||
overlap = option1 < option2 ? option1 : -option2;
|
||||
}
|
||||
} else {
|
||||
response.bInA = false;
|
||||
if(rangeA[1] > rangeB[1]) {
|
||||
overlap = rangeA[0] - rangeB[1];
|
||||
response.aInB = false;
|
||||
} else {
|
||||
var option1 = rangeA[1] - rangeB[0];
|
||||
var option2 = rangeB[1] - rangeA[0];
|
||||
overlap = option1 < option2 ? option1 : -option2;
|
||||
}
|
||||
}
|
||||
var absOverlap = Math.abs(overlap);
|
||||
if(absOverlap < response.overlap) {
|
||||
response.overlap = absOverlap;
|
||||
response.overlapN.copyFrom(axis);
|
||||
if(overlap < 0) {
|
||||
response.overlapN.reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
Phaser.Collision.T_VECTORS.push(offsetV);
|
||||
Phaser.Collision.T_ARRAYS.push(rangeA);
|
||||
Phaser.Collision.T_ARRAYS.push(rangeB);
|
||||
return false;
|
||||
};
|
||||
Collision.LEFT_VORNOI_REGION = -1;
|
||||
Collision.MIDDLE_VORNOI_REGION = 0;
|
||||
Collision.RIGHT_VORNOI_REGION = 1;
|
||||
Collision.vornoiRegion = function vornoiRegion(line, point) {
|
||||
var len2 = line.length2();
|
||||
var dp = point.dot(line);
|
||||
if(dp < 0) {
|
||||
return Phaser.Collision.LEFT_VORNOI_REGION;
|
||||
} else if(dp > len2) {
|
||||
return Phaser.Collision.RIGHT_VORNOI_REGION;
|
||||
} else {
|
||||
return Phaser.Collision.MIDDLE_VORNOI_REGION;
|
||||
}
|
||||
};
|
||||
Collision.testCircleCircle = function testCircleCircle(a, b, response) {
|
||||
if (typeof response === "undefined") { response = null; }
|
||||
var differenceV = Phaser.Collision.T_VECTORS.pop().copyFrom(b.pos).sub(a.pos);
|
||||
var totalRadius = a.radius + b.radius;
|
||||
var totalRadiusSq = totalRadius * totalRadius;
|
||||
var distanceSq = differenceV.length2();
|
||||
if(distanceSq > totalRadiusSq) {
|
||||
Phaser.Collision.T_VECTORS.push(differenceV);
|
||||
return false;
|
||||
}
|
||||
if(response) {
|
||||
var dist = Math.sqrt(distanceSq);
|
||||
response.a = a;
|
||||
response.b = b;
|
||||
response.overlap = totalRadius - dist;
|
||||
response.overlapN.copyFrom(differenceV.normalize());
|
||||
response.overlapV.copyFrom(differenceV).scale(response.overlap);
|
||||
response.aInB = a.radius <= b.radius && dist <= b.radius - a.radius;
|
||||
response.bInA = b.radius <= a.radius && dist <= a.radius - b.radius;
|
||||
}
|
||||
Phaser.Collision.T_VECTORS.push(differenceV);
|
||||
return true;
|
||||
};
|
||||
Collision.testPolygonCircle = function testPolygonCircle(polygon, circle, response) {
|
||||
if (typeof response === "undefined") { response = null; }
|
||||
var circlePos = Phaser.Collision.T_VECTORS.pop().copyFrom(circle.pos).sub(polygon.pos);
|
||||
var radius = circle.radius;
|
||||
var radius2 = radius * radius;
|
||||
var points = polygon.points;
|
||||
var len = points.length;
|
||||
var edge = Collision.T_VECTORS.pop();
|
||||
var point = Collision.T_VECTORS.pop();
|
||||
for(var i = 0; i < len; i++) {
|
||||
var next = i === len - 1 ? 0 : i + 1;
|
||||
var prev = i === 0 ? len - 1 : i - 1;
|
||||
var overlap = 0;
|
||||
var overlapN = null;
|
||||
edge.copyFrom(polygon.edges[i]);
|
||||
point.copyFrom(circlePos).sub(points[i]);
|
||||
if(response && point.length2() > radius2) {
|
||||
response.aInB = false;
|
||||
}
|
||||
var region = Collision.vornoiRegion(edge, point);
|
||||
if(region === Phaser.Collision.LEFT_VORNOI_REGION) {
|
||||
edge.copyFrom(polygon.edges[prev]);
|
||||
var point2 = Phaser.Collision.T_VECTORS.pop().copyFrom(circlePos).sub(points[prev]);
|
||||
region = Collision.vornoiRegion(edge, point2);
|
||||
if(region === Phaser.Collision.RIGHT_VORNOI_REGION) {
|
||||
var dist = point.length2();
|
||||
if(dist > radius) {
|
||||
Phaser.Collision.T_VECTORS.push(circlePos);
|
||||
Phaser.Collision.T_VECTORS.push(edge);
|
||||
Phaser.Collision.T_VECTORS.push(point);
|
||||
Phaser.Collision.T_VECTORS.push(point2);
|
||||
return false;
|
||||
} else if(response) {
|
||||
response.bInA = false;
|
||||
overlapN = point.normalize();
|
||||
overlap = radius - dist;
|
||||
}
|
||||
}
|
||||
Phaser.Collision.T_VECTORS.push(point2);
|
||||
} else if(region === Phaser.Collision.RIGHT_VORNOI_REGION) {
|
||||
edge.copyFrom(polygon.edges[next]);
|
||||
point.copyFrom(circlePos).sub(points[next]);
|
||||
region = Collision.vornoiRegion(edge, point);
|
||||
if(region === Phaser.Collision.LEFT_VORNOI_REGION) {
|
||||
var dist = point.length2();
|
||||
if(dist > radius) {
|
||||
Phaser.Collision.T_VECTORS.push(circlePos);
|
||||
Phaser.Collision.T_VECTORS.push(edge);
|
||||
Phaser.Collision.T_VECTORS.push(point);
|
||||
return false;
|
||||
} else if(response) {
|
||||
response.bInA = false;
|
||||
overlapN = point.normalize();
|
||||
overlap = radius - dist;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var normal = edge.perp().normalize();
|
||||
var dist = point.dot(normal);
|
||||
var distAbs = Math.abs(dist);
|
||||
if(dist > 0 && distAbs > radius) {
|
||||
Phaser.Collision.T_VECTORS.push(circlePos);
|
||||
Phaser.Collision.T_VECTORS.push(normal);
|
||||
Phaser.Collision.T_VECTORS.push(point);
|
||||
return false;
|
||||
} else if(response) {
|
||||
overlapN = normal;
|
||||
overlap = radius - dist;
|
||||
if(dist >= 0 || overlap < 2 * radius) {
|
||||
response.bInA = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(overlapN && response && Math.abs(overlap) < Math.abs(response.overlap)) {
|
||||
response.overlap = overlap;
|
||||
response.overlapN.copyFrom(overlapN);
|
||||
}
|
||||
}
|
||||
if(response) {
|
||||
response.a = polygon;
|
||||
response.b = circle;
|
||||
response.overlapV.copyFrom(response.overlapN).scale(response.overlap);
|
||||
}
|
||||
Phaser.Collision.T_VECTORS.push(circlePos);
|
||||
Phaser.Collision.T_VECTORS.push(edge);
|
||||
Phaser.Collision.T_VECTORS.push(point);
|
||||
return true;
|
||||
};
|
||||
Collision.testCirclePolygon = function testCirclePolygon(circle, polygon, response) {
|
||||
if (typeof response === "undefined") { response = null; }
|
||||
var result = Phaser.Collision.testPolygonCircle(polygon, circle, response);
|
||||
if(result && response) {
|
||||
var a = response.a;
|
||||
var aInB = response.aInB;
|
||||
response.overlapN.reverse();
|
||||
response.overlapV.reverse();
|
||||
response.a = response.b;
|
||||
response.b = a;
|
||||
response.aInB = response.bInA;
|
||||
response.bInA = aInB;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
Collision.testPolygonPolygon = function testPolygonPolygon(a, b, response) {
|
||||
if (typeof response === "undefined") { response = null; }
|
||||
var aPoints = a.points;
|
||||
var aLen = aPoints.length;
|
||||
var bPoints = b.points;
|
||||
var bLen = bPoints.length;
|
||||
for(var i = 0; i < aLen; i++) {
|
||||
if(Phaser.Collision.isSeparatingAxis(a.pos, b.pos, aPoints, bPoints, a.normals[i], response)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for(var i = 0; i < bLen; i++) {
|
||||
if(Phaser.Collision.isSeparatingAxis(a.pos, b.pos, aPoints, bPoints, b.normals[i], response)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(response) {
|
||||
response.a = a;
|
||||
response.b = b;
|
||||
response.overlapV.copyFrom(response.overlapN).scale(response.overlap);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
return Collision;
|
||||
})();
|
||||
Phaser.Collision = Collision;
|
||||
})(Phaser || (Phaser = {}));
|
1702
todo/phaser clean up/Collision.ts
Normal file
1702
todo/phaser clean up/Collision.ts
Normal file
File diff suppressed because it is too large
Load diff
365
todo/phaser clean up/CollisionMask.js
Normal file
365
todo/phaser clean up/CollisionMask.js
Normal file
|
@ -0,0 +1,365 @@
|
|||
/// <reference path="../Game.ts" />
|
||||
/**
|
||||
* Phaser - CollisionMask
|
||||
*/
|
||||
var Phaser;
|
||||
(function (Phaser) {
|
||||
var CollisionMask = (function () {
|
||||
/**
|
||||
* CollisionMask constructor. Creates a new <code>CollisionMask</code> for the given GameObject.
|
||||
*
|
||||
* @param game {Phaser.Game} Current game instance.
|
||||
* @param parent {Phaser.GameObject} The GameObject this CollisionMask belongs to.
|
||||
* @param x {number} The initial x position of the CollisionMask.
|
||||
* @param y {number} The initial y position of the CollisionMask.
|
||||
* @param width {number} The width of the CollisionMask.
|
||||
* @param height {number} The height of the CollisionMask.
|
||||
*/
|
||||
function CollisionMask(game, parent, x, y, width, height) {
|
||||
/**
|
||||
* Geom type of this sprite. (available: QUAD, POINT, CIRCLE, LINE, RECTANGLE, POLYGON)
|
||||
* @type {number}
|
||||
*/
|
||||
this.type = 0;
|
||||
this._game = game;
|
||||
this._parent = parent;
|
||||
// By default the CollisionMask is a quad
|
||||
this.type = CollisionMask.QUAD;
|
||||
this.quad = new Phaser.Quad(this._parent.x, this._parent.y, this._parent.width, this._parent.height);
|
||||
this.offset = new Phaser.MicroPoint(0, 0);
|
||||
this.last = new Phaser.MicroPoint(0, 0);
|
||||
this._ref = this.quad;
|
||||
return this;
|
||||
}
|
||||
CollisionMask.QUAD = 0;
|
||||
CollisionMask.POINT = 1;
|
||||
CollisionMask.CIRCLE = 2;
|
||||
CollisionMask.LINE = 3;
|
||||
CollisionMask.RECTANGLE = 4;
|
||||
CollisionMask.POLYGON = 5;
|
||||
CollisionMask.prototype.createCircle = /**
|
||||
* Create a circle shape with specific diameter.
|
||||
* @param diameter {number} Diameter of the circle.
|
||||
* @return {CollisionMask} This
|
||||
*/
|
||||
function (diameter) {
|
||||
this.type = CollisionMask.CIRCLE;
|
||||
this.circle = new Phaser.Circle(this.last.x, this.last.y, diameter);
|
||||
this._ref = this.circle;
|
||||
return this;
|
||||
};
|
||||
CollisionMask.prototype.preUpdate = /**
|
||||
* Pre-update is called right before update() on each object in the game loop.
|
||||
*/
|
||||
function () {
|
||||
this.last.x = this.x;
|
||||
this.last.y = this.y;
|
||||
};
|
||||
CollisionMask.prototype.update = function () {
|
||||
this._ref.x = this._parent.x + this.offset.x;
|
||||
this._ref.y = this._parent.y + this.offset.y;
|
||||
};
|
||||
CollisionMask.prototype.render = /**
|
||||
* Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
|
||||
* @param camera {Camera} Camera the bound will be rendered to.
|
||||
* @param cameraOffsetX {number} X offset of bound to the camera.
|
||||
* @param cameraOffsetY {number} Y offset of bound to the camera.
|
||||
*/
|
||||
function (camera, cameraOffsetX, cameraOffsetY) {
|
||||
var _dx = cameraOffsetX + (this.x - camera.worldView.x);
|
||||
var _dy = cameraOffsetY + (this.y - camera.worldView.y);
|
||||
this._parent.context.fillStyle = this._parent.renderDebugColor;
|
||||
if(this.type == CollisionMask.QUAD) {
|
||||
this._parent.context.fillRect(_dx, _dy, this.width, this.height);
|
||||
} else if(this.type == CollisionMask.CIRCLE) {
|
||||
this._parent.context.beginPath();
|
||||
this._parent.context.arc(_dx, _dy, this.circle.radius, 0, Math.PI * 2);
|
||||
this._parent.context.fill();
|
||||
this._parent.context.closePath();
|
||||
}
|
||||
};
|
||||
CollisionMask.prototype.destroy = /**
|
||||
* Destroy all objects and references belonging to this CollisionMask
|
||||
*/
|
||||
function () {
|
||||
this._game = null;
|
||||
this._parent = null;
|
||||
this._ref = null;
|
||||
this.quad = null;
|
||||
this.point = null;
|
||||
this.circle = null;
|
||||
this.rect = null;
|
||||
this.line = null;
|
||||
this.offset = null;
|
||||
};
|
||||
CollisionMask.prototype.intersectsRaw = function (left, right, top, bottom) {
|
||||
//if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
|
||||
return true;
|
||||
};
|
||||
CollisionMask.prototype.intersectsVector = function (vector) {
|
||||
if(this.type == CollisionMask.QUAD) {
|
||||
return this.quad.contains(vector.x, vector.y);
|
||||
}
|
||||
};
|
||||
CollisionMask.prototype.intersects = /**
|
||||
* 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.
|
||||
* @param source {GeomSprite} Sprite you want to check.
|
||||
* @return {boolean} Whether they overlaps or not.
|
||||
*/
|
||||
function (source) {
|
||||
// Quad vs. Quad
|
||||
if(this.type == CollisionMask.QUAD && source.type == CollisionMask.QUAD) {
|
||||
return this.quad.intersects(source.quad);
|
||||
}
|
||||
// Circle vs. Circle
|
||||
if(this.type == CollisionMask.CIRCLE && source.type == CollisionMask.CIRCLE) {
|
||||
return Phaser.Collision.circleToCircle(this.circle, source.circle).result;
|
||||
}
|
||||
// Circle vs. Rect
|
||||
if(this.type == CollisionMask.CIRCLE && source.type == CollisionMask.RECTANGLE) {
|
||||
return Phaser.Collision.circleToRectangle(this.circle, source.rect).result;
|
||||
}
|
||||
// Circle vs. Point
|
||||
if(this.type == CollisionMask.CIRCLE && source.type == CollisionMask.POINT) {
|
||||
return Phaser.Collision.circleContainsPoint(this.circle, source.point).result;
|
||||
}
|
||||
// Circle vs. Line
|
||||
if(this.type == CollisionMask.CIRCLE && source.type == CollisionMask.LINE) {
|
||||
return Phaser.Collision.lineToCircle(source.line, this.circle).result;
|
||||
}
|
||||
// Rect vs. Rect
|
||||
if(this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.RECTANGLE) {
|
||||
return Phaser.Collision.rectangleToRectangle(this.rect, source.rect).result;
|
||||
}
|
||||
// Rect vs. Circle
|
||||
if(this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.CIRCLE) {
|
||||
return Phaser.Collision.circleToRectangle(source.circle, this.rect).result;
|
||||
}
|
||||
// Rect vs. Point
|
||||
if(this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.POINT) {
|
||||
return Phaser.Collision.pointToRectangle(source.point, this.rect).result;
|
||||
}
|
||||
// Rect vs. Line
|
||||
if(this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.LINE) {
|
||||
return Phaser.Collision.lineToRectangle(source.line, this.rect).result;
|
||||
}
|
||||
// Point vs. Point
|
||||
if(this.type == CollisionMask.POINT && source.type == CollisionMask.POINT) {
|
||||
return this.point.equals(source.point);
|
||||
}
|
||||
// Point vs. Circle
|
||||
if(this.type == CollisionMask.POINT && source.type == CollisionMask.CIRCLE) {
|
||||
return Phaser.Collision.circleContainsPoint(source.circle, this.point).result;
|
||||
}
|
||||
// Point vs. Rect
|
||||
if(this.type == CollisionMask.POINT && source.type == CollisionMask.RECTANGLE) {
|
||||
return Phaser.Collision.pointToRectangle(this.point, source.rect).result;
|
||||
}
|
||||
// Point vs. Line
|
||||
if(this.type == CollisionMask.POINT && source.type == CollisionMask.LINE) {
|
||||
return source.line.isPointOnLine(this.point.x, this.point.y);
|
||||
}
|
||||
// Line vs. Line
|
||||
if(this.type == CollisionMask.LINE && source.type == CollisionMask.LINE) {
|
||||
return Phaser.Collision.lineSegmentToLineSegment(this.line, source.line).result;
|
||||
}
|
||||
// Line vs. Circle
|
||||
if(this.type == CollisionMask.LINE && source.type == CollisionMask.CIRCLE) {
|
||||
return Phaser.Collision.lineToCircle(this.line, source.circle).result;
|
||||
}
|
||||
// Line vs. Rect
|
||||
if(this.type == CollisionMask.LINE && source.type == CollisionMask.RECTANGLE) {
|
||||
return Phaser.Collision.lineSegmentToRectangle(this.line, source.rect).result;
|
||||
}
|
||||
// Line vs. Point
|
||||
if(this.type == CollisionMask.LINE && source.type == CollisionMask.POINT) {
|
||||
return this.line.isPointOnLine(source.point.x, source.point.y);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
CollisionMask.prototype.checkHullIntersection = function (mask) {
|
||||
if((this.hullX + this.hullWidth > mask.hullX) && (this.hullX < mask.hullX + mask.width) && (this.hullY + this.hullHeight > mask.hullY) && (this.hullY < mask.hullY + mask.hullHeight)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Object.defineProperty(CollisionMask.prototype, "hullWidth", {
|
||||
get: function () {
|
||||
if(this.deltaX > 0) {
|
||||
return this.width + this.deltaX;
|
||||
} else {
|
||||
return this.width - this.deltaX;
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "hullHeight", {
|
||||
get: function () {
|
||||
if(this.deltaY > 0) {
|
||||
return this.height + this.deltaY;
|
||||
} else {
|
||||
return this.height - this.deltaY;
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "hullX", {
|
||||
get: function () {
|
||||
if(this.x < this.last.x) {
|
||||
return this.x;
|
||||
} else {
|
||||
return this.last.x;
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "hullY", {
|
||||
get: function () {
|
||||
if(this.y < this.last.y) {
|
||||
return this.y;
|
||||
} else {
|
||||
return this.last.y;
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "deltaXAbs", {
|
||||
get: function () {
|
||||
return (this.deltaX > 0 ? this.deltaX : -this.deltaX);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "deltaYAbs", {
|
||||
get: function () {
|
||||
return (this.deltaY > 0 ? this.deltaY : -this.deltaY);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "deltaX", {
|
||||
get: function () {
|
||||
return this.x - this.last.x;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "deltaY", {
|
||||
get: function () {
|
||||
return this.y - this.last.y;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "x", {
|
||||
get: function () {
|
||||
return this._ref.x;
|
||||
//return this.quad.x;
|
||||
},
|
||||
set: function (value) {
|
||||
this._ref.x = value;
|
||||
//this.quad.x = value;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "y", {
|
||||
get: function () {
|
||||
return this._ref.y;
|
||||
//return this.quad.y;
|
||||
},
|
||||
set: function (value) {
|
||||
this._ref.y = value;
|
||||
//this.quad.y = value;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "width", {
|
||||
get: function () {
|
||||
//return this.quad.width;
|
||||
return this._ref.width;
|
||||
},
|
||||
set: //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);
|
||||
//}
|
||||
function (value) {
|
||||
//this.quad.width = value;
|
||||
this._ref.width = value;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "height", {
|
||||
get: function () {
|
||||
//return this.quad.height;
|
||||
return this._ref.height;
|
||||
},
|
||||
set: function (value) {
|
||||
//this.quad.height = value;
|
||||
this._ref.height = value;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "left", {
|
||||
get: function () {
|
||||
return this.x;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "right", {
|
||||
get: function () {
|
||||
return this.x + this.width;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "top", {
|
||||
get: function () {
|
||||
return this.y;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "bottom", {
|
||||
get: function () {
|
||||
return this.y + this.height;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "halfWidth", {
|
||||
get: function () {
|
||||
return this.width / 2;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CollisionMask.prototype, "halfHeight", {
|
||||
get: function () {
|
||||
return this.height / 2;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
return CollisionMask;
|
||||
})();
|
||||
Phaser.CollisionMask = CollisionMask;
|
||||
})(Phaser || (Phaser = {}));
|
501
todo/phaser clean up/CollisionMask.ts
Normal file
501
todo/phaser clean up/CollisionMask.ts
Normal file
|
@ -0,0 +1,501 @@
|
|||
/// <reference path="../Game.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - CollisionMask
|
||||
*/
|
||||
|
||||
module Phaser {
|
||||
|
||||
export class CollisionMask {
|
||||
|
||||
/**
|
||||
* CollisionMask constructor. Creates a new <code>CollisionMask</code> for the given GameObject.
|
||||
*
|
||||
* @param game {Phaser.Game} Current game instance.
|
||||
* @param parent {Phaser.GameObject} The GameObject this CollisionMask belongs to.
|
||||
* @param x {number} The initial x position of the CollisionMask.
|
||||
* @param y {number} The initial y position of the CollisionMask.
|
||||
* @param width {number} The width of the CollisionMask.
|
||||
* @param height {number} The height of the CollisionMask.
|
||||
*/
|
||||
constructor(game: Game, parent: GameObject, x: number, y: number, width: number, height: number) {
|
||||
|
||||
this._game = game;
|
||||
this._parent = parent;
|
||||
|
||||
// By default the CollisionMask is a quad
|
||||
this.type = CollisionMask.QUAD;
|
||||
|
||||
this.quad = new Phaser.Quad(this._parent.x, this._parent.y, this._parent.width, this._parent.height);
|
||||
this.offset = new MicroPoint(0, 0);
|
||||
this.last = new MicroPoint(0, 0);
|
||||
|
||||
this._ref = this.quad;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
private _game;
|
||||
private _parent;
|
||||
|
||||
// An internal reference to the active collision shape
|
||||
private _ref;
|
||||
|
||||
/**
|
||||
* Geom type of this sprite. (available: QUAD, POINT, CIRCLE, LINE, RECTANGLE, POLYGON)
|
||||
* @type {number}
|
||||
*/
|
||||
public type: number = 0;
|
||||
|
||||
/**
|
||||
* Quad (a smaller version of Rectangle).
|
||||
* @type {number}
|
||||
*/
|
||||
public static QUAD: number = 0;
|
||||
|
||||
/**
|
||||
* Point.
|
||||
* @type {number}
|
||||
*/
|
||||
public static POINT: number = 1;
|
||||
|
||||
/**
|
||||
* Circle.
|
||||
* @type {number}
|
||||
*/
|
||||
public static CIRCLE: number = 2;
|
||||
|
||||
/**
|
||||
* Line.
|
||||
* @type {number}
|
||||
*/
|
||||
public static LINE: number = 3;
|
||||
|
||||
/**
|
||||
* Rectangle.
|
||||
* @type {number}
|
||||
*/
|
||||
public static RECTANGLE: number = 4;
|
||||
|
||||
/**
|
||||
* Polygon.
|
||||
* @type {number}
|
||||
*/
|
||||
public static POLYGON: number = 5;
|
||||
|
||||
/**
|
||||
* Rectangle shape container. A Rectangle instance.
|
||||
* @type {Rectangle}
|
||||
*/
|
||||
public quad: Quad;
|
||||
|
||||
/**
|
||||
* Point shape container. A Point instance.
|
||||
* @type {Point}
|
||||
*/
|
||||
public point: Point;
|
||||
|
||||
/**
|
||||
* Circle shape container. A Circle instance.
|
||||
* @type {Circle}
|
||||
*/
|
||||
public circle: Circle;
|
||||
|
||||
/**
|
||||
* Line shape container. A Line instance.
|
||||
* @type {Line}
|
||||
*/
|
||||
public line: Line;
|
||||
|
||||
/**
|
||||
* Rectangle shape container. A Rectangle instance.
|
||||
* @type {Rectangle}
|
||||
*/
|
||||
public rect: Rectangle;
|
||||
|
||||
/**
|
||||
* A value from the top-left of the GameObject frame that this collisionMask is offset to.
|
||||
* If the CollisionMask is a Quad/Rectangle the offset relates to the top-left of that Quad.
|
||||
* If the CollisionMask is a Circle the offset relates to the center of the circle.
|
||||
* @type {MicroPoint}
|
||||
*/
|
||||
public offset: MicroPoint;
|
||||
|
||||
/**
|
||||
* The previous x/y coordinates of the CollisionMask, used for hull calculations
|
||||
* @type {MicroPoint}
|
||||
*/
|
||||
public last: MicroPoint;
|
||||
|
||||
/**
|
||||
* Create a circle shape with specific diameter.
|
||||
* @param diameter {number} Diameter of the circle.
|
||||
* @return {CollisionMask} This
|
||||
*/
|
||||
createCircle(diameter: number): CollisionMask {
|
||||
|
||||
this.type = CollisionMask.CIRCLE;
|
||||
this.circle = new Circle(this.last.x, this.last.y, diameter);
|
||||
this._ref = this.circle;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-update is called right before update() on each object in the game loop.
|
||||
*/
|
||||
public preUpdate() {
|
||||
|
||||
this.last.x = this.x;
|
||||
this.last.y = this.y;
|
||||
|
||||
}
|
||||
|
||||
public update() {
|
||||
|
||||
this._ref.x = this._parent.x + this.offset.x;
|
||||
this._ref.y = this._parent.y + this.offset.y;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
|
||||
* @param camera {Camera} Camera the bound will be rendered to.
|
||||
* @param cameraOffsetX {number} X offset of bound to the camera.
|
||||
* @param cameraOffsetY {number} Y offset of bound to the camera.
|
||||
*/
|
||||
public render(camera:Camera, cameraOffsetX:number, cameraOffsetY:number) {
|
||||
|
||||
var _dx = cameraOffsetX + (this.x - camera.worldView.x);
|
||||
var _dy = cameraOffsetY + (this.y - camera.worldView.y);
|
||||
|
||||
this._parent.context.fillStyle = this._parent.renderDebugColor;
|
||||
|
||||
if (this.type == CollisionMask.QUAD)
|
||||
{
|
||||
this._parent.context.fillRect(_dx, _dy, this.width, this.height);
|
||||
}
|
||||
else if (this.type == CollisionMask.CIRCLE)
|
||||
{
|
||||
this._parent.context.beginPath();
|
||||
this._parent.context.arc(_dx, _dy, this.circle.radius, 0, Math.PI * 2);
|
||||
this._parent.context.fill();
|
||||
this._parent.context.closePath();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy all objects and references belonging to this CollisionMask
|
||||
*/
|
||||
public destroy() {
|
||||
|
||||
this._game = null;
|
||||
this._parent = null;
|
||||
this._ref = null;
|
||||
this.quad = null;
|
||||
this.point = null;
|
||||
this.circle = null;
|
||||
this.rect = null;
|
||||
this.line = null;
|
||||
this.offset = null;
|
||||
|
||||
}
|
||||
|
||||
public intersectsRaw(left: number, right: number, top: number, bottom: number): bool {
|
||||
|
||||
//if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public intersectsVector(vector: Phaser.Vector2): bool {
|
||||
|
||||
if (this.type == CollisionMask.QUAD)
|
||||
{
|
||||
return this.quad.contains(vector.x, vector.y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param source {GeomSprite} Sprite you want to check.
|
||||
* @return {boolean} Whether they overlaps or not.
|
||||
*/
|
||||
public intersects(source: CollisionMask): bool {
|
||||
|
||||
// Quad vs. Quad
|
||||
if (this.type == CollisionMask.QUAD && source.type == CollisionMask.QUAD)
|
||||
{
|
||||
return this.quad.intersects(source.quad);
|
||||
}
|
||||
|
||||
// Circle vs. Circle
|
||||
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.CIRCLE)
|
||||
{
|
||||
return Collision.circleToCircle(this.circle, source.circle).result;
|
||||
}
|
||||
|
||||
// Circle vs. Rect
|
||||
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.RECTANGLE)
|
||||
{
|
||||
return Collision.circleToRectangle(this.circle, source.rect).result;
|
||||
}
|
||||
|
||||
// Circle vs. Point
|
||||
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.POINT)
|
||||
{
|
||||
return Collision.circleContainsPoint(this.circle, source.point).result;
|
||||
}
|
||||
|
||||
// Circle vs. Line
|
||||
if (this.type == CollisionMask.CIRCLE && source.type == CollisionMask.LINE)
|
||||
{
|
||||
return Collision.lineToCircle(source.line, this.circle).result;
|
||||
}
|
||||
|
||||
// Rect vs. Rect
|
||||
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.RECTANGLE)
|
||||
{
|
||||
return Collision.rectangleToRectangle(this.rect, source.rect).result;
|
||||
}
|
||||
|
||||
// Rect vs. Circle
|
||||
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.CIRCLE)
|
||||
{
|
||||
return Collision.circleToRectangle(source.circle, this.rect).result;
|
||||
}
|
||||
|
||||
// Rect vs. Point
|
||||
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.POINT)
|
||||
{
|
||||
return Collision.pointToRectangle(source.point, this.rect).result;
|
||||
}
|
||||
|
||||
// Rect vs. Line
|
||||
if (this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.LINE)
|
||||
{
|
||||
return Collision.lineToRectangle(source.line, this.rect).result;
|
||||
}
|
||||
|
||||
// Point vs. Point
|
||||
if (this.type == CollisionMask.POINT && source.type == CollisionMask.POINT)
|
||||
{
|
||||
return this.point.equals(source.point);
|
||||
}
|
||||
|
||||
// Point vs. Circle
|
||||
if (this.type == CollisionMask.POINT && source.type == CollisionMask.CIRCLE)
|
||||
{
|
||||
return Collision.circleContainsPoint(source.circle, this.point).result;
|
||||
}
|
||||
|
||||
// Point vs. Rect
|
||||
if (this.type == CollisionMask.POINT && source.type == CollisionMask.RECTANGLE)
|
||||
{
|
||||
return Collision.pointToRectangle(this.point, source.rect).result;
|
||||
}
|
||||
|
||||
// Point vs. Line
|
||||
if (this.type == CollisionMask.POINT && source.type == CollisionMask.LINE)
|
||||
{
|
||||
return source.line.isPointOnLine(this.point.x, this.point.y);
|
||||
}
|
||||
|
||||
// Line vs. Line
|
||||
if (this.type == CollisionMask.LINE && source.type == CollisionMask.LINE)
|
||||
{
|
||||
return Collision.lineSegmentToLineSegment(this.line, source.line).result;
|
||||
}
|
||||
|
||||
// Line vs. Circle
|
||||
if (this.type == CollisionMask.LINE && source.type == CollisionMask.CIRCLE)
|
||||
{
|
||||
return Collision.lineToCircle(this.line, source.circle).result;
|
||||
}
|
||||
|
||||
// Line vs. Rect
|
||||
if (this.type == CollisionMask.LINE && source.type == CollisionMask.RECTANGLE)
|
||||
{
|
||||
return Collision.lineSegmentToRectangle(this.line, source.rect).result;
|
||||
}
|
||||
|
||||
// Line vs. Point
|
||||
if (this.type == CollisionMask.LINE && source.type == CollisionMask.POINT)
|
||||
{
|
||||
return this.line.isPointOnLine(source.point.x, source.point.y);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public checkHullIntersection(mask: CollisionMask): bool {
|
||||
|
||||
if ((this.hullX + this.hullWidth > mask.hullX) && (this.hullX < mask.hullX + mask.width) && (this.hullY + this.hullHeight > mask.hullY) && (this.hullY < mask.hullY + mask.hullHeight))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public get hullWidth(): number {
|
||||
|
||||
if (this.deltaX > 0)
|
||||
{
|
||||
return this.width + this.deltaX;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.width - this.deltaX;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public get hullHeight(): number {
|
||||
|
||||
if (this.deltaY > 0)
|
||||
{
|
||||
return this.height + this.deltaY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.height - this.deltaY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public get hullX(): number {
|
||||
|
||||
if (this.x < this.last.x)
|
||||
{
|
||||
return this.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.last.x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public get hullY(): number {
|
||||
|
||||
if (this.y < this.last.y)
|
||||
{
|
||||
return this.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.last.y;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public get deltaXAbs(): number {
|
||||
return (this.deltaX > 0 ? this.deltaX : -this.deltaX);
|
||||
}
|
||||
|
||||
public get deltaYAbs(): number {
|
||||
return (this.deltaY > 0 ? this.deltaY : -this.deltaY);
|
||||
}
|
||||
|
||||
public get deltaX(): number {
|
||||
return this.x - this.last.x;
|
||||
}
|
||||
|
||||
public get deltaY(): number {
|
||||
return this.y - this.last.y;
|
||||
}
|
||||
|
||||
public get x(): number {
|
||||
return this._ref.x;
|
||||
//return this.quad.x;
|
||||
}
|
||||
|
||||
public set x(value: number) {
|
||||
this._ref.x = value;
|
||||
//this.quad.x = value;
|
||||
}
|
||||
|
||||
public get y(): number {
|
||||
return this._ref.y;
|
||||
//return this.quad.y;
|
||||
}
|
||||
|
||||
public set y(value: number) {
|
||||
this._ref.y = value;
|
||||
//this.quad.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.quad.width = value;
|
||||
this._ref.width = value;
|
||||
}
|
||||
|
||||
public set height(value:number) {
|
||||
//this.quad.height = value;
|
||||
this._ref.height = value;
|
||||
}
|
||||
|
||||
public get width(): number {
|
||||
//return this.quad.width;
|
||||
return this._ref.width;
|
||||
}
|
||||
|
||||
public get height(): number {
|
||||
//return this.quad.height;
|
||||
return this._ref.height;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
19
todo/phaser clean up/Debug.js
Normal file
19
todo/phaser clean up/Debug.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
var Shapes;
|
||||
(function (Shapes) {
|
||||
|
||||
var Point = Shapes.Point = (function () {
|
||||
function Point(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
Point.prototype.getDist = function () {
|
||||
return Math.sqrt((this.x * this.x) + (this.y * this.y));
|
||||
};
|
||||
Point.origin = new Point(0, 0);
|
||||
return Point;
|
||||
})();
|
||||
|
||||
})(Shapes || (Shapes = {}));
|
||||
|
||||
var p = new Shapes.Point(3, 4);
|
||||
var dist = p.getDist();
|
90
todo/phaser clean up/Debug.ts
Normal file
90
todo/phaser clean up/Debug.ts
Normal file
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* Phaser - Components - Debug
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
module Phaser.Components {
|
||||
|
||||
export class Debug {
|
||||
|
||||
/**
|
||||
* Render bound of this sprite for debugging? (default to false)
|
||||
* @type {boolean}
|
||||
*/
|
||||
public renderDebug: bool = false;
|
||||
|
||||
/**
|
||||
* Color of the Sprite when no image is present. Format is a css color string.
|
||||
* @type {string}
|
||||
*/
|
||||
public fillColor: string = 'rgb(255,255,255)';
|
||||
|
||||
/**
|
||||
* Color of bound when render debug. (see renderDebug) Format is a css color string.
|
||||
* @type {string}
|
||||
*/
|
||||
public renderDebugColor: string = 'rgba(0,255,0,0.5)';
|
||||
|
||||
/**
|
||||
* Color of points when render debug. (see renderDebug) Format is a css color string.
|
||||
* @type {string}
|
||||
*/
|
||||
public renderDebugPointColor: string = 'rgba(255,255,255,1)';
|
||||
|
||||
/**
|
||||
* Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
|
||||
* @param camera {Camera} Camera the bound will be rendered to.
|
||||
* @param cameraOffsetX {number} X offset of bound to the camera.
|
||||
* @param cameraOffsetY {number} Y offset of bound to the camera.
|
||||
*/
|
||||
/*
|
||||
private renderBounds(camera: Camera, cameraOffsetX: number, cameraOffsetY: number) {
|
||||
|
||||
this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
|
||||
this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
|
||||
|
||||
this.context.fillStyle = this.renderDebugColor;
|
||||
this.context.fillRect(this._dx, this._dy, this.frameBounds.width, this.frameBounds.height);
|
||||
|
||||
//this.context.fillStyle = this.renderDebugPointColor;
|
||||
|
||||
//var hw = this.frameBounds.halfWidth * this.scale.x;
|
||||
//var hh = this.frameBounds.halfHeight * this.scale.y;
|
||||
//var sw = (this.frameBounds.width * this.scale.x) - 1;
|
||||
//var sh = (this.frameBounds.height * this.scale.y) - 1;
|
||||
|
||||
//this.context.fillRect(this._dx, this._dy, 1, 1); // top left
|
||||
//this.context.fillRect(this._dx + hw, this._dy, 1, 1); // top center
|
||||
//this.context.fillRect(this._dx + sw, this._dy, 1, 1); // top right
|
||||
//this.context.fillRect(this._dx, this._dy + hh, 1, 1); // left center
|
||||
//this.context.fillRect(this._dx + hw, this._dy + hh, 1, 1); // center
|
||||
//this.context.fillRect(this._dx + sw, this._dy + hh, 1, 1); // right center
|
||||
//this.context.fillRect(this._dx, this._dy + sh, 1, 1); // bottom left
|
||||
//this.context.fillRect(this._dx + hw, this._dy + sh, 1, 1); // bottom center
|
||||
//this.context.fillRect(this._dx + sw, this._dy + sh, 1, 1); // bottom right
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Render debug infos. (including name, bounds info, position and some other properties)
|
||||
* @param x {number} X position of the debug info to be rendered.
|
||||
* @param y {number} Y position of the debug info to be rendered.
|
||||
* @param [color] {number} color of the debug info to be rendered. (format is css color string)
|
||||
*/
|
||||
/*
|
||||
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
|
||||
|
||||
this.context.fillStyle = color;
|
||||
this.context.fillText('Sprite: ' + this.name + ' (' + this.frameBounds.width + ' x ' + this.frameBounds.height + ')', x, y);
|
||||
this.context.fillText('x: ' + this.frameBounds.x.toFixed(1) + ' y: ' + this.frameBounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
|
||||
this.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.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);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
}
|
183
todo/phaser clean up/Emitter.js
Normal file
183
todo/phaser clean up/Emitter.js
Normal file
|
@ -0,0 +1,183 @@
|
|||
var __extends = this.__extends || function (d, b) {
|
||||
function __() { this.constructor = d; }
|
||||
__.prototype = b.prototype;
|
||||
d.prototype = new __();
|
||||
};
|
||||
var Phaser;
|
||||
(function (Phaser) {
|
||||
var Emitter = (function (_super) {
|
||||
__extends(Emitter, _super);
|
||||
function Emitter(game, x, y, size) {
|
||||
if (typeof x === "undefined") { x = 0; }
|
||||
if (typeof y === "undefined") { y = 0; }
|
||||
if (typeof size === "undefined") { size = 0; }
|
||||
_super.call(this, game, size);
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
this.minParticleSpeed = new MicroPoint(-100, -100);
|
||||
this.maxParticleSpeed = new MicroPoint(100, 100);
|
||||
this.minRotation = -360;
|
||||
this.maxRotation = 360;
|
||||
this.gravity = 0;
|
||||
this.particleClass = null;
|
||||
this.particleDrag = new MicroPoint();
|
||||
this.frequency = 0.1;
|
||||
this.lifespan = 3;
|
||||
this.bounce = 0;
|
||||
this._quantity = 0;
|
||||
this._counter = 0;
|
||||
this._explode = true;
|
||||
this.on = false;
|
||||
this._point = new MicroPoint();
|
||||
}
|
||||
Emitter.prototype.destroy = function () {
|
||||
this.minParticleSpeed = null;
|
||||
this.maxParticleSpeed = null;
|
||||
this.particleDrag = null;
|
||||
this.particleClass = null;
|
||||
this._point = null;
|
||||
_super.prototype.destroy.call(this);
|
||||
};
|
||||
Emitter.prototype.makeParticles = function (graphics, quantity, multiple, collide) {
|
||||
if (typeof quantity === "undefined") { quantity = 50; }
|
||||
if (typeof multiple === "undefined") { multiple = false; }
|
||||
if (typeof collide === "undefined") { collide = 0; }
|
||||
this.maxSize = quantity;
|
||||
var totalFrames = 1;
|
||||
var randomFrame;
|
||||
var particle;
|
||||
var i = 0;
|
||||
while(i < quantity) {
|
||||
if(this.particleClass == null) {
|
||||
particle = new Phaser.Particle(this._game);
|
||||
} else {
|
||||
particle = new this.particleClass(this._game);
|
||||
}
|
||||
if(multiple) {
|
||||
} else {
|
||||
if(graphics) {
|
||||
particle.loadGraphic(graphics);
|
||||
}
|
||||
}
|
||||
if(collide > 0) {
|
||||
particle.allowCollisions = Phaser.Collision.ANY;
|
||||
particle.width *= collide;
|
||||
particle.height *= collide;
|
||||
} else {
|
||||
particle.allowCollisions = Phaser.Collision.NONE;
|
||||
}
|
||||
particle.exists = false;
|
||||
this.add(particle);
|
||||
i++;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Emitter.prototype.update = function () {
|
||||
if(this.on) {
|
||||
if(this._explode) {
|
||||
this.on = false;
|
||||
var i = 0;
|
||||
var l = this._quantity;
|
||||
if((l <= 0) || (l > this.length)) {
|
||||
l = this.length;
|
||||
}
|
||||
while(i < l) {
|
||||
this.emitParticle();
|
||||
i++;
|
||||
}
|
||||
this._quantity = 0;
|
||||
} else {
|
||||
this._timer += this._game.time.elapsed;
|
||||
while((this.frequency > 0) && (this._timer > this.frequency) && this.on) {
|
||||
this._timer -= this.frequency;
|
||||
this.emitParticle();
|
||||
if((this._quantity > 0) && (++this._counter >= this._quantity)) {
|
||||
this.on = false;
|
||||
this._quantity = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_super.prototype.update.call(this);
|
||||
};
|
||||
Emitter.prototype.kill = function () {
|
||||
this.on = false;
|
||||
_super.prototype.kill.call(this);
|
||||
};
|
||||
Emitter.prototype.start = function (explode, lifespan, frequency, quantity) {
|
||||
if (typeof explode === "undefined") { explode = true; }
|
||||
if (typeof lifespan === "undefined") { lifespan = 0; }
|
||||
if (typeof frequency === "undefined") { frequency = 0.1; }
|
||||
if (typeof quantity === "undefined") { quantity = 0; }
|
||||
this.revive();
|
||||
this.visible = true;
|
||||
this.on = true;
|
||||
this._explode = explode;
|
||||
this.lifespan = lifespan;
|
||||
this.frequency = frequency;
|
||||
this._quantity += quantity;
|
||||
this._counter = 0;
|
||||
this._timer = 0;
|
||||
};
|
||||
Emitter.prototype.emitParticle = function () {
|
||||
var particle = this.recycle(Phaser.Particle);
|
||||
particle.lifespan = this.lifespan;
|
||||
particle.elasticity = this.bounce;
|
||||
particle.reset(this.x - (particle.width >> 1) + this._game.math.random() * this.width, this.y - (particle.height >> 1) + this._game.math.random() * this.height);
|
||||
particle.visible = true;
|
||||
if(this.minParticleSpeed.x != this.maxParticleSpeed.x) {
|
||||
particle.velocity.x = this.minParticleSpeed.x + this._game.math.random() * (this.maxParticleSpeed.x - this.minParticleSpeed.x);
|
||||
} else {
|
||||
particle.velocity.x = this.minParticleSpeed.x;
|
||||
}
|
||||
if(this.minParticleSpeed.y != this.maxParticleSpeed.y) {
|
||||
particle.velocity.y = this.minParticleSpeed.y + this._game.math.random() * (this.maxParticleSpeed.y - this.minParticleSpeed.y);
|
||||
} else {
|
||||
particle.velocity.y = this.minParticleSpeed.y;
|
||||
}
|
||||
particle.acceleration.y = this.gravity;
|
||||
if(this.minRotation != this.maxRotation && this.minRotation !== 0 && this.maxRotation !== 0) {
|
||||
particle.angularVelocity = this.minRotation + this._game.math.random() * (this.maxRotation - this.minRotation);
|
||||
} else {
|
||||
particle.angularVelocity = this.minRotation;
|
||||
}
|
||||
if(particle.angularVelocity != 0) {
|
||||
particle.angle = this._game.math.random() * 360 - 180;
|
||||
}
|
||||
particle.drag.x = this.particleDrag.x;
|
||||
particle.drag.y = this.particleDrag.y;
|
||||
particle.onEmit();
|
||||
};
|
||||
Emitter.prototype.setSize = function (width, height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
};
|
||||
Emitter.prototype.setXSpeed = function (min, max) {
|
||||
if (typeof min === "undefined") { min = 0; }
|
||||
if (typeof max === "undefined") { max = 0; }
|
||||
this.minParticleSpeed.x = min;
|
||||
this.maxParticleSpeed.x = max;
|
||||
};
|
||||
Emitter.prototype.setYSpeed = function (min, max) {
|
||||
if (typeof min === "undefined") { min = 0; }
|
||||
if (typeof max === "undefined") { max = 0; }
|
||||
this.minParticleSpeed.y = min;
|
||||
this.maxParticleSpeed.y = max;
|
||||
};
|
||||
Emitter.prototype.setRotation = function (min, max) {
|
||||
if (typeof min === "undefined") { min = 0; }
|
||||
if (typeof max === "undefined") { max = 0; }
|
||||
this.minRotation = min;
|
||||
this.maxRotation = max;
|
||||
};
|
||||
Emitter.prototype.at = function (object) {
|
||||
object.getMidpoint(this._point);
|
||||
this.x = this._point.x - (this.width >> 1);
|
||||
this.y = this._point.y - (this.height >> 1);
|
||||
};
|
||||
return Emitter;
|
||||
})(Phaser.Group);
|
||||
Phaser.Emitter = Emitter;
|
||||
})(Phaser || (Phaser = {}));
|
454
todo/phaser clean up/Emitter.ts
Normal file
454
todo/phaser clean up/Emitter.ts
Normal file
|
@ -0,0 +1,454 @@
|
|||
/// <reference path="../Game.ts" />
|
||||
/// <reference path="../Group.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Emitter
|
||||
*
|
||||
* Emitter is a lightweight particle emitter. It can be used for one-time explosions or for
|
||||
* continuous effects like rain and fire. All it really does is launch Particle objects out
|
||||
* at set intervals, and fixes their positions and velocities accorindgly.
|
||||
*/
|
||||
|
||||
module Phaser {
|
||||
|
||||
export class Emitter extends Group {
|
||||
|
||||
/**
|
||||
* Creates a new <code>Emitter</code> object at a specific position.
|
||||
* Does NOT automatically generate or attach particles!
|
||||
*
|
||||
* @param x {number} The X position of the emitter.
|
||||
* @param y {number} The Y position of the emitter.
|
||||
* @param [size] {number} Specifies a maximum capacity for this emitter.
|
||||
*/
|
||||
constructor(game: Game, x: number = 0, y: number = 0, size: number = 0) {
|
||||
|
||||
super(game, size);
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
this.minParticleSpeed = new MicroPoint(-100, -100);
|
||||
this.maxParticleSpeed = new MicroPoint(100, 100);
|
||||
this.minRotation = -360;
|
||||
this.maxRotation = 360;
|
||||
this.gravity = 0;
|
||||
this.particleClass = null;
|
||||
this.particleDrag = new MicroPoint();
|
||||
this.frequency = 0.1;
|
||||
this.lifespan = 3;
|
||||
this.bounce = 0;
|
||||
this._quantity = 0;
|
||||
this._counter = 0;
|
||||
this._explode = true;
|
||||
this.on = false;
|
||||
this._point = new MicroPoint();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The X position of the top left corner of the emitter in world space.
|
||||
*/
|
||||
public x: number;
|
||||
|
||||
/**
|
||||
* The Y position of the top left corner of emitter in world space.
|
||||
*/
|
||||
public y: number;
|
||||
|
||||
/**
|
||||
* The width of the emitter. Particles can be randomly generated from anywhere within this box.
|
||||
*/
|
||||
public width: number;
|
||||
|
||||
/**
|
||||
* The height of the emitter. Particles can be randomly generated from anywhere within this box.
|
||||
*/
|
||||
public height: number;
|
||||
|
||||
/**
|
||||
* The minimum possible velocity of a particle.
|
||||
* The default value is (-100,-100).
|
||||
*/
|
||||
public minParticleSpeed: MicroPoint;
|
||||
|
||||
/**
|
||||
* The maximum possible velocity of a particle.
|
||||
* The default value is (100,100).
|
||||
*/
|
||||
public maxParticleSpeed: MicroPoint;
|
||||
|
||||
/**
|
||||
* The X and Y drag component of particles launched from the emitter.
|
||||
*/
|
||||
public particleDrag: MicroPoint;
|
||||
|
||||
/**
|
||||
* The minimum possible angular velocity of a particle. The default value is -360.
|
||||
* NOTE: rotating particles are more expensive to draw than non-rotating ones!
|
||||
*/
|
||||
public minRotation: number;
|
||||
|
||||
/**
|
||||
* The maximum possible angular velocity of a particle. The default value is 360.
|
||||
* NOTE: rotating particles are more expensive to draw than non-rotating ones!
|
||||
*/
|
||||
public maxRotation: number;
|
||||
|
||||
/**
|
||||
* Sets the <code>acceleration.y</code> member of each particle to this value on launch.
|
||||
*/
|
||||
public gravity: number;
|
||||
|
||||
/**
|
||||
* Determines whether the emitter is currently emitting particles.
|
||||
* It is totally safe to directly toggle this.
|
||||
*/
|
||||
public on: bool;
|
||||
|
||||
/**
|
||||
* How often a particle is emitted (if emitter is started with Explode == false).
|
||||
*/
|
||||
public frequency: number;
|
||||
|
||||
/**
|
||||
* How long each particle lives once it is emitted.
|
||||
* Set lifespan to 'zero' for particles to live forever.
|
||||
*/
|
||||
public lifespan: number;
|
||||
|
||||
/**
|
||||
* How much each particle should bounce. 1 = full bounce, 0 = no bounce.
|
||||
*/
|
||||
public bounce: number;
|
||||
|
||||
/**
|
||||
* Set your own particle class type here.
|
||||
* Default is <code>Particle</code>.
|
||||
*/
|
||||
public particleClass;
|
||||
|
||||
/**
|
||||
* Internal helper for deciding how many particles to launch.
|
||||
*/
|
||||
private _quantity: number;
|
||||
|
||||
/**
|
||||
* Internal helper for the style of particle emission (all at once, or one at a time).
|
||||
*/
|
||||
private _explode: bool;
|
||||
|
||||
/**
|
||||
* Internal helper for deciding when to launch particles or kill them.
|
||||
*/
|
||||
private _timer: number;
|
||||
|
||||
/**
|
||||
* Internal counter for figuring out how many particles to launch.
|
||||
*/
|
||||
private _counter: number;
|
||||
|
||||
/**
|
||||
* Internal point object, handy for reusing for memory mgmt purposes.
|
||||
*/
|
||||
private _point: MicroPoint;
|
||||
|
||||
/**
|
||||
* Clean up memory.
|
||||
*/
|
||||
public destroy() {
|
||||
this.minParticleSpeed = null;
|
||||
this.maxParticleSpeed = null;
|
||||
this.particleDrag = null;
|
||||
this.particleClass = null;
|
||||
this._point = null;
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function generates a new array of particle sprites to attach to the emitter.
|
||||
*
|
||||
* @param graphics If you opted to not pre-configure an array of 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 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 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.
|
||||
*
|
||||
* @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 {
|
||||
|
||||
this.maxSize = quantity;
|
||||
|
||||
var totalFrames: number = 1;
|
||||
|
||||
/*
|
||||
if(Multiple)
|
||||
{
|
||||
var sprite:Sprite = new Sprite(this._game);
|
||||
sprite.loadGraphic(Graphics,true);
|
||||
totalFrames = sprite.frames;
|
||||
sprite.destroy();
|
||||
}
|
||||
*/
|
||||
|
||||
var randomFrame: number;
|
||||
var particle: Particle;
|
||||
var i: number = 0;
|
||||
|
||||
while (i < quantity)
|
||||
{
|
||||
if (this.particleClass == null)
|
||||
{
|
||||
particle = new Particle(this._game);
|
||||
}
|
||||
else
|
||||
{
|
||||
particle = new this.particleClass(this._game);
|
||||
}
|
||||
|
||||
if (multiple)
|
||||
{
|
||||
/*
|
||||
randomFrame = this._game.math.random()*totalFrames;
|
||||
if(BakedRotations > 0)
|
||||
particle.loadRotatedGraphic(Graphics,BakedRotations,randomFrame);
|
||||
else
|
||||
{
|
||||
particle.loadGraphic(Graphics,true);
|
||||
particle.frame = randomFrame;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
if (BakedRotations > 0)
|
||||
particle.loadRotatedGraphic(Graphics,BakedRotations);
|
||||
else
|
||||
particle.loadGraphic(Graphics);
|
||||
*/
|
||||
|
||||
if (graphics)
|
||||
{
|
||||
particle.loadGraphic(graphics);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (collide > 0)
|
||||
{
|
||||
particle.allowCollisions = Collision.ANY;
|
||||
particle.width *= collide;
|
||||
particle.height *= collide;
|
||||
//particle.centerOffsets();
|
||||
}
|
||||
else
|
||||
{
|
||||
particle.allowCollisions = Collision.NONE;
|
||||
}
|
||||
|
||||
particle.exists = false;
|
||||
|
||||
this.add(particle);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called automatically by the game loop, decides when to launch particles and when to "die".
|
||||
*/
|
||||
public update() {
|
||||
|
||||
if (this.on)
|
||||
{
|
||||
if (this._explode)
|
||||
{
|
||||
this.on = false;
|
||||
|
||||
var i: number = 0;
|
||||
var l: number = this._quantity;
|
||||
|
||||
if ((l <= 0) || (l > this.length))
|
||||
{
|
||||
l = this.length;
|
||||
}
|
||||
|
||||
while (i < l)
|
||||
{
|
||||
this.emitParticle();
|
||||
i++;
|
||||
}
|
||||
|
||||
this._quantity = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this._timer += this._game.time.elapsed;
|
||||
|
||||
while ((this.frequency > 0) && (this._timer > this.frequency) && this.on)
|
||||
{
|
||||
this._timer -= this.frequency;
|
||||
this.emitParticle();
|
||||
|
||||
if ((this._quantity > 0) && (++this._counter >= this._quantity))
|
||||
{
|
||||
this.on = false;
|
||||
this._quantity = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.update();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this function to turn off all the particles and the emitter.
|
||||
*/
|
||||
public kill() {
|
||||
|
||||
this.on = false;
|
||||
|
||||
super.kill();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this function to start emitting particles.
|
||||
*
|
||||
* @param explode {boolean} Whether the particles should all burst out at once.
|
||||
* @param lifespan {number} 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 quantity {number} How many particles to launch. 0 = "all of the particles".
|
||||
*/
|
||||
public start(explode: bool = true, lifespan: number = 0, frequency: number = 0.1, quantity: number = 0) {
|
||||
|
||||
this.revive();
|
||||
|
||||
this.visible = true;
|
||||
this.on = true;
|
||||
|
||||
this._explode = explode;
|
||||
this.lifespan = lifespan;
|
||||
this.frequency = frequency;
|
||||
this._quantity += quantity;
|
||||
|
||||
this._counter = 0;
|
||||
this._timer = 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This function can be used both internally and externally to emit the next particle.
|
||||
*/
|
||||
public emitParticle() {
|
||||
|
||||
var particle: Particle = this.recycle(Particle);
|
||||
|
||||
particle.lifespan = this.lifespan;
|
||||
particle.elasticity = this.bounce;
|
||||
particle.reset(this.x - (particle.width >> 1) + this._game.math.random() * this.width, this.y - (particle.height >> 1) + this._game.math.random() * this.height);
|
||||
particle.visible = true;
|
||||
|
||||
if (this.minParticleSpeed.x != this.maxParticleSpeed.x)
|
||||
{
|
||||
particle.velocity.x = this.minParticleSpeed.x + this._game.math.random() * (this.maxParticleSpeed.x - this.minParticleSpeed.x);
|
||||
}
|
||||
else
|
||||
{
|
||||
particle.velocity.x = this.minParticleSpeed.x;
|
||||
}
|
||||
|
||||
if (this.minParticleSpeed.y != this.maxParticleSpeed.y)
|
||||
{
|
||||
particle.velocity.y = this.minParticleSpeed.y + this._game.math.random() * (this.maxParticleSpeed.y - this.minParticleSpeed.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
particle.velocity.y = this.minParticleSpeed.y;
|
||||
}
|
||||
|
||||
particle.acceleration.y = this.gravity;
|
||||
|
||||
if (this.minRotation != this.maxRotation && this.minRotation !== 0 && this.maxRotation !== 0)
|
||||
{
|
||||
particle.angularVelocity = this.minRotation + this._game.math.random() * (this.maxRotation - this.minRotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
particle.angularVelocity = this.minRotation;
|
||||
}
|
||||
|
||||
if (particle.angularVelocity != 0)
|
||||
{
|
||||
particle.angle = this._game.math.random() * 360 - 180;
|
||||
}
|
||||
|
||||
particle.drag.x = this.particleDrag.x;
|
||||
particle.drag.y = this.particleDrag.y;
|
||||
particle.onEmit();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A more compact way of setting the width and height of the emitter.
|
||||
*
|
||||
* @param width {number} The desired width of the emitter (particles are spawned randomly within these dimensions).
|
||||
* @param height {number} The desired height of the emitter.
|
||||
*/
|
||||
public setSize(width: number, height: number) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* A more compact way of setting the X velocity range of the emitter.
|
||||
*
|
||||
* @param Min {number} The minimum value for this range.
|
||||
* @param Max {number} The maximum value for this range.
|
||||
*/
|
||||
public setXSpeed(min: number = 0, max: number = 0) {
|
||||
this.minParticleSpeed.x = min;
|
||||
this.maxParticleSpeed.x = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* A more compact way of setting the Y velocity range of the emitter.
|
||||
*
|
||||
* @param Min {number} The minimum value for this range.
|
||||
* @param Max {number} The maximum value for this range.
|
||||
*/
|
||||
public setYSpeed(min: number = 0, max: number = 0) {
|
||||
this.minParticleSpeed.y = min;
|
||||
this.maxParticleSpeed.y = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* A more compact way of setting the angular velocity constraints of the emitter.
|
||||
*
|
||||
* @param Min {number} The minimum value for this range.
|
||||
* @param Max {number} The maximum value for this range.
|
||||
*/
|
||||
public setRotation(min: number = 0, max: number = 0) {
|
||||
this.minRotation = min;
|
||||
this.maxRotation = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the emitter's midpoint to match the midpoint of a <code>Object</code>.
|
||||
*
|
||||
* @param Object {object} The <code>Object</code> that you want to sync up with.
|
||||
*/
|
||||
public at(object) {
|
||||
object.getMidpoint(this._point);
|
||||
this.x = this._point.x - (this.width >> 1);
|
||||
this.y = this._point.y - (this.height >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
271
todo/phaser clean up/GeomSprite.js
Normal file
271
todo/phaser clean up/GeomSprite.js
Normal file
|
@ -0,0 +1,271 @@
|
|||
var __extends = this.__extends || function (d, b) {
|
||||
function __() { this.constructor = d; }
|
||||
__.prototype = b.prototype;
|
||||
d.prototype = new __();
|
||||
};
|
||||
var Phaser;
|
||||
(function (Phaser) {
|
||||
var GeomSprite = (function (_super) {
|
||||
__extends(GeomSprite, _super);
|
||||
function GeomSprite(game, x, y) {
|
||||
if (typeof x === "undefined") { x = 0; }
|
||||
if (typeof y === "undefined") { y = 0; }
|
||||
_super.call(this, game, x, y);
|
||||
this._dx = 0;
|
||||
this._dy = 0;
|
||||
this._dw = 0;
|
||||
this._dh = 0;
|
||||
this.type = 0;
|
||||
this.renderOutline = true;
|
||||
this.renderFill = true;
|
||||
this.lineWidth = 1;
|
||||
this.lineColor = 'rgb(0,255,0)';
|
||||
this.fillColor = 'rgb(0,100,0)';
|
||||
this.type = GeomSprite.UNASSIGNED;
|
||||
return this;
|
||||
}
|
||||
GeomSprite.UNASSIGNED = 0;
|
||||
GeomSprite.CIRCLE = 1;
|
||||
GeomSprite.LINE = 2;
|
||||
GeomSprite.POINT = 3;
|
||||
GeomSprite.RECTANGLE = 4;
|
||||
GeomSprite.POLYGON = 5;
|
||||
GeomSprite.prototype.loadCircle = function (circle) {
|
||||
this.refresh();
|
||||
this.circle = circle;
|
||||
this.type = Phaser.GeomSprite.CIRCLE;
|
||||
return this;
|
||||
};
|
||||
GeomSprite.prototype.loadLine = function (line) {
|
||||
this.refresh();
|
||||
this.line = line;
|
||||
this.type = Phaser.GeomSprite.LINE;
|
||||
return this;
|
||||
};
|
||||
GeomSprite.prototype.loadPoint = function (point) {
|
||||
this.refresh();
|
||||
this.point = point;
|
||||
this.type = Phaser.GeomSprite.POINT;
|
||||
return this;
|
||||
};
|
||||
GeomSprite.prototype.loadRectangle = function (rect) {
|
||||
this.refresh();
|
||||
this.rect = rect;
|
||||
this.type = Phaser.GeomSprite.RECTANGLE;
|
||||
return this;
|
||||
};
|
||||
GeomSprite.prototype.createCircle = function (diameter) {
|
||||
this.refresh();
|
||||
this.circle = new Phaser.Circle(this.x, this.y, diameter);
|
||||
this.type = Phaser.GeomSprite.CIRCLE;
|
||||
this.frameBounds.setTo(this.circle.x - this.circle.radius, this.circle.y - this.circle.radius, this.circle.diameter, this.circle.diameter);
|
||||
return this;
|
||||
};
|
||||
GeomSprite.prototype.createLine = function (x, y) {
|
||||
this.refresh();
|
||||
this.line = new Phaser.Line(this.x, this.y, x, y);
|
||||
this.type = Phaser.GeomSprite.LINE;
|
||||
this.frameBounds.setTo(this.x, this.y, this.line.width, this.line.height);
|
||||
return this;
|
||||
};
|
||||
GeomSprite.prototype.createPoint = function () {
|
||||
this.refresh();
|
||||
this.point = new Phaser.Point(this.x, this.y);
|
||||
this.type = Phaser.GeomSprite.POINT;
|
||||
this.frameBounds.width = 1;
|
||||
this.frameBounds.height = 1;
|
||||
return this;
|
||||
};
|
||||
GeomSprite.prototype.createRectangle = function (width, height) {
|
||||
this.refresh();
|
||||
this.rect = new Phaser.Rectangle(this.x, this.y, width, height);
|
||||
this.type = Phaser.GeomSprite.RECTANGLE;
|
||||
this.frameBounds.copyFrom(this.rect);
|
||||
return this;
|
||||
};
|
||||
GeomSprite.prototype.createPolygon = function (points) {
|
||||
if (typeof points === "undefined") { points = []; }
|
||||
this.refresh();
|
||||
this.polygon = new Phaser.Polygon(new Vector2(this.x, this.y), points);
|
||||
this.type = Phaser.GeomSprite.POLYGON;
|
||||
return this;
|
||||
};
|
||||
GeomSprite.prototype.refresh = function () {
|
||||
this.circle = null;
|
||||
this.line = null;
|
||||
this.point = null;
|
||||
this.rect = null;
|
||||
};
|
||||
GeomSprite.prototype.update = function () {
|
||||
if(this.type == Phaser.GeomSprite.UNASSIGNED) {
|
||||
return;
|
||||
} else if(this.type == Phaser.GeomSprite.CIRCLE) {
|
||||
this.circle.x = this.x;
|
||||
this.circle.y = this.y;
|
||||
this.frameBounds.width = this.circle.diameter;
|
||||
this.frameBounds.height = this.circle.diameter;
|
||||
} else if(this.type == Phaser.GeomSprite.LINE) {
|
||||
this.line.x1 = this.x;
|
||||
this.line.y1 = this.y;
|
||||
this.frameBounds.setTo(this.x, this.y, this.line.width, this.line.height);
|
||||
} else if(this.type == Phaser.GeomSprite.POINT) {
|
||||
this.point.x = this.x;
|
||||
this.point.y = this.y;
|
||||
} else if(this.type == Phaser.GeomSprite.RECTANGLE) {
|
||||
this.rect.x = this.x;
|
||||
this.rect.y = this.y;
|
||||
this.frameBounds.copyFrom(this.rect);
|
||||
}
|
||||
};
|
||||
GeomSprite.prototype.inCamera = function (camera) {
|
||||
if(this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) {
|
||||
this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
|
||||
this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
|
||||
this._dw = this.frameBounds.width * this.scale.x;
|
||||
this._dh = this.frameBounds.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.frameBounds);
|
||||
}
|
||||
};
|
||||
GeomSprite.prototype.render = function (camera, cameraOffsetX, cameraOffsetY) {
|
||||
if(this.type == Phaser.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;
|
||||
}
|
||||
if(this.alpha !== 1) {
|
||||
var globalAlpha = this.context.globalAlpha;
|
||||
this.context.globalAlpha = this.alpha;
|
||||
}
|
||||
this._dx = cameraOffsetX + (this.frameBounds.x - camera.worldView.x);
|
||||
this._dy = cameraOffsetY + (this.frameBounds.y - camera.worldView.y);
|
||||
this._dw = this.frameBounds.width * this.scale.x;
|
||||
this._dh = this.frameBounds.height * this.scale.y;
|
||||
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);
|
||||
}
|
||||
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();
|
||||
this.context.lineWidth = this.lineWidth;
|
||||
this.context.strokeStyle = this.lineColor;
|
||||
this.context.fillStyle = this.fillColor;
|
||||
if(this._game.stage.fillStyle !== this.fillColor) {
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.CIRCLE) {
|
||||
this.context.beginPath();
|
||||
this.context.arc(this._dx, this._dy, this.circle.radius, 0, Math.PI * 2);
|
||||
if(this.renderOutline) {
|
||||
this.context.stroke();
|
||||
}
|
||||
if(this.renderFill) {
|
||||
this.context.fill();
|
||||
}
|
||||
this.context.closePath();
|
||||
} else if(this.type == Phaser.GeomSprite.LINE) {
|
||||
this.context.beginPath();
|
||||
this.context.moveTo(this._dx, this._dy);
|
||||
this.context.lineTo(this.line.x2, this.line.y2);
|
||||
this.context.stroke();
|
||||
this.context.closePath();
|
||||
} else if(this.type == Phaser.GeomSprite.POINT) {
|
||||
this.context.fillRect(this._dx, this._dy, 2, 2);
|
||||
} else if(this.type == Phaser.GeomSprite.RECTANGLE) {
|
||||
if(this.renderOutline == false) {
|
||||
this.context.fillRect(this._dx, this._dy, this.rect.width, this.rect.height);
|
||||
} else {
|
||||
this.context.beginPath();
|
||||
this.context.rect(this._dx, this._dy, this.rect.width, this.rect.height);
|
||||
this.context.stroke();
|
||||
if(this.renderFill) {
|
||||
this.context.fill();
|
||||
}
|
||||
this.context.closePath();
|
||||
}
|
||||
this.context.fillStyle = 'rgb(255,255,255)';
|
||||
this.renderPoint(this.rect.topLeft, 0, 0, 2);
|
||||
this.renderPoint(this.rect.topCenter, 0, 0, 2);
|
||||
this.renderPoint(this.rect.topRight, 0, 0, 2);
|
||||
this.renderPoint(this.rect.leftCenter, 0, 0, 2);
|
||||
this.renderPoint(this.rect.center, 0, 0, 2);
|
||||
this.renderPoint(this.rect.rightCenter, 0, 0, 2);
|
||||
this.renderPoint(this.rect.bottomLeft, 0, 0, 2);
|
||||
this.renderPoint(this.rect.bottomCenter, 0, 0, 2);
|
||||
this.renderPoint(this.rect.bottomRight, 0, 0, 2);
|
||||
}
|
||||
this._game.stage.restoreCanvasValues();
|
||||
if(this.rotation !== 0) {
|
||||
this.context.translate(0, 0);
|
||||
this.context.restore();
|
||||
}
|
||||
if(globalAlpha > -1) {
|
||||
this.context.globalAlpha = globalAlpha;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
GeomSprite.prototype.renderPoint = function (point, offsetX, offsetY, size) {
|
||||
if (typeof offsetX === "undefined") { offsetX = 0; }
|
||||
if (typeof offsetY === "undefined") { offsetY = 0; }
|
||||
if (typeof size === "undefined") { size = 1; }
|
||||
this.context.fillRect(offsetX + point.x, offsetY + point.y, size, size);
|
||||
};
|
||||
GeomSprite.prototype.renderDebugInfo = function (x, y, color) {
|
||||
if (typeof color === "undefined") { color = 'rgb(255,255,255)'; }
|
||||
};
|
||||
GeomSprite.prototype.collide = function (source) {
|
||||
if(this.type == Phaser.GeomSprite.CIRCLE && source.type == Phaser.GeomSprite.CIRCLE) {
|
||||
return Phaser.Collision.circleToCircle(this.circle, source.circle).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.CIRCLE && source.type == Phaser.GeomSprite.RECTANGLE) {
|
||||
return Phaser.Collision.circleToRectangle(this.circle, source.rect).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.CIRCLE && source.type == Phaser.GeomSprite.POINT) {
|
||||
return Phaser.Collision.circleContainsPoint(this.circle, source.point).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.CIRCLE && source.type == Phaser.GeomSprite.LINE) {
|
||||
return Phaser.Collision.lineToCircle(source.line, this.circle).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.RECTANGLE && source.type == Phaser.GeomSprite.RECTANGLE) {
|
||||
return Phaser.Collision.rectangleToRectangle(this.rect, source.rect).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.RECTANGLE && source.type == Phaser.GeomSprite.CIRCLE) {
|
||||
return Phaser.Collision.circleToRectangle(source.circle, this.rect).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.RECTANGLE && source.type == Phaser.GeomSprite.POINT) {
|
||||
return Phaser.Collision.pointToRectangle(source.point, this.rect).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.RECTANGLE && source.type == Phaser.GeomSprite.LINE) {
|
||||
return Phaser.Collision.lineToRectangle(source.line, this.rect).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.POINT && source.type == Phaser.GeomSprite.POINT) {
|
||||
return this.point.equals(source.point);
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.POINT && source.type == Phaser.GeomSprite.CIRCLE) {
|
||||
return Phaser.Collision.circleContainsPoint(source.circle, this.point).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.POINT && source.type == Phaser.GeomSprite.RECTANGLE) {
|
||||
return Phaser.Collision.pointToRectangle(this.point, source.rect).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.POINT && source.type == Phaser.GeomSprite.LINE) {
|
||||
return source.line.isPointOnLine(this.point.x, this.point.y);
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.LINE && source.type == Phaser.GeomSprite.LINE) {
|
||||
return Phaser.Collision.lineSegmentToLineSegment(this.line, source.line).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.LINE && source.type == Phaser.GeomSprite.CIRCLE) {
|
||||
return Phaser.Collision.lineToCircle(this.line, source.circle).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.LINE && source.type == Phaser.GeomSprite.RECTANGLE) {
|
||||
return Phaser.Collision.lineSegmentToRectangle(this.line, source.rect).result;
|
||||
}
|
||||
if(this.type == Phaser.GeomSprite.LINE && source.type == Phaser.GeomSprite.POINT) {
|
||||
return this.line.isPointOnLine(source.point.x, source.point.y);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
return GeomSprite;
|
||||
})(Phaser.GameObject);
|
||||
Phaser.GeomSprite = GeomSprite;
|
||||
})(Phaser || (Phaser = {}));
|
645
todo/phaser clean up/GeomSprite.ts
Normal file
645
todo/phaser clean up/GeomSprite.ts
Normal file
|
@ -0,0 +1,645 @@
|
|||
/// <reference path="../Game.ts" />
|
||||
/// <reference path="../geom/Polygon.ts" />
|
||||
/// <reference path="../utils/RectangleUtils.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 Sprite {
|
||||
|
||||
/**
|
||||
* GeomSprite constructor
|
||||
* Create a new <code>GeomSprite</code>.
|
||||
*
|
||||
* @param game {Phaser.Game} Current game instance.
|
||||
* @param [x] {number} the initial x position of the sprite.
|
||||
* @param [y] {number} the initial y position of the sprite.
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* Geom type of this sprite. (available: UNASSIGNED, CIRCLE, LINE, POINT, RECTANGLE)
|
||||
* @type {number}
|
||||
*/
|
||||
public type: number = 0;
|
||||
|
||||
/**
|
||||
* Not completely set yet. (the default type)
|
||||
*/
|
||||
public static UNASSIGNED: number = 0;
|
||||
|
||||
/**
|
||||
* Circle.
|
||||
* @type {number}
|
||||
*/
|
||||
public static CIRCLE: number = 1;
|
||||
|
||||
/**
|
||||
* Line.
|
||||
* @type {number}
|
||||
*/
|
||||
public static LINE: number = 2;
|
||||
|
||||
/**
|
||||
* Point.
|
||||
* @type {number}
|
||||
*/
|
||||
public static POINT: number = 3;
|
||||
|
||||
/**
|
||||
* Rectangle.
|
||||
* @type {number}
|
||||
*/
|
||||
public static RECTANGLE: number = 4;
|
||||
|
||||
/**
|
||||
* Polygon.
|
||||
* @type {number}
|
||||
*/
|
||||
public static POLYGON: number = 5;
|
||||
|
||||
/**
|
||||
* Circle shape container. A Circle instance.
|
||||
* @type {Circle}
|
||||
*/
|
||||
public circle: Circle;
|
||||
|
||||
/**
|
||||
* Line shape container. A Line instance.
|
||||
* @type {Line}
|
||||
*/
|
||||
public line: Line;
|
||||
|
||||
/**
|
||||
* Point shape container. A Point instance.
|
||||
* @type {Point}
|
||||
*/
|
||||
public point: Point;
|
||||
|
||||
/**
|
||||
* Rectangle shape container. A Rectangle instance.
|
||||
* @type {Rectangle}
|
||||
*/
|
||||
public rect: Rectangle;
|
||||
|
||||
/**
|
||||
* Polygon shape container. A Polygon instance.
|
||||
* @type {Polygon}
|
||||
*/
|
||||
public polygon: Polygon;
|
||||
|
||||
/**
|
||||
* Render outline of this sprite or not. (default is true)
|
||||
* @type {boolean}
|
||||
*/
|
||||
public renderOutline: bool = true;
|
||||
|
||||
/**
|
||||
* Fill the shape or not. (default is true)
|
||||
* @type {boolean}
|
||||
*/
|
||||
public renderFill: bool = true;
|
||||
|
||||
/**
|
||||
* Width of outline. (default is 1)
|
||||
* @type {number}
|
||||
*/
|
||||
public lineWidth: number = 1;
|
||||
|
||||
/**
|
||||
* Width of outline. (default is 1)
|
||||
* @type {number}
|
||||
*/
|
||||
public lineColor: string = 'rgb(0,255,0)';
|
||||
|
||||
/**
|
||||
* The color of the filled area in rgb or rgba string format
|
||||
* @type {string} Defaults to rgb(0,100,0) - a green color
|
||||
*/
|
||||
public fillColor: string = 'rgb(0,100,0)';
|
||||
|
||||
/**
|
||||
* Just like Sprite.loadGraphic(), this will load a circle and set its shape to Circle.
|
||||
* @param circle {Circle} Circle geometry define.
|
||||
* @return {GeomSprite} GeomSprite instance itself.
|
||||
*/
|
||||
loadCircle(circle:Circle): GeomSprite {
|
||||
|
||||
this.refresh();
|
||||
this.circle = circle;
|
||||
this.type = GeomSprite.CIRCLE;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Just like Sprite.loadGraphic(), this will load a line and set its shape to Line.
|
||||
* @param line {Line} Line geometry define.
|
||||
* @return {GeomSprite} GeomSprite instance itself.
|
||||
*/
|
||||
loadLine(line:Line): GeomSprite {
|
||||
|
||||
this.refresh();
|
||||
this.line = line;
|
||||
this.type = GeomSprite.LINE;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Just like Sprite.loadGraphic(), this will load a point and set its shape to Point.
|
||||
* @param point {Point} Point geometry define.
|
||||
* @return {GeomSprite} GeomSprite instance itself.
|
||||
*/
|
||||
loadPoint(point:Point): GeomSprite {
|
||||
|
||||
this.refresh();
|
||||
this.point = point;
|
||||
this.type = GeomSprite.POINT;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Just like Sprite.loadGraphic(), this will load a rect and set its shape to Rectangle.
|
||||
* @param rect {Rectangle} Rectangle geometry define.
|
||||
* @return {GeomSprite} GeomSprite instance itself.
|
||||
*/
|
||||
loadRectangle(rect:Rectangle): GeomSprite {
|
||||
|
||||
this.refresh();
|
||||
this.rect = rect;
|
||||
this.type = GeomSprite.RECTANGLE;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a circle shape with specific diameter.
|
||||
* @param diameter {number} Diameter of the circle.
|
||||
* @return {GeomSprite} GeomSprite instance itself.
|
||||
*/
|
||||
createCircle(diameter: number): GeomSprite {
|
||||
|
||||
this.refresh();
|
||||
this.circle = new Circle(this.x, this.y, diameter);
|
||||
this.type = GeomSprite.CIRCLE;
|
||||
this.frameBounds.setTo(this.circle.x - this.circle.radius, this.circle.y - this.circle.radius, this.circle.diameter, this.circle.diameter);
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a line shape with specific end point.
|
||||
* @param x {number} X position of the end point.
|
||||
* @param y {number} Y position of the end point.
|
||||
* @return {GeomSprite} GeomSprite instance itself.
|
||||
*/
|
||||
createLine(x: number, y: number): GeomSprite {
|
||||
|
||||
this.refresh();
|
||||
this.line = new Line(this.x, this.y, x, y);
|
||||
this.type = GeomSprite.LINE;
|
||||
this.frameBounds.setTo(this.x, this.y, this.line.width, this.line.height);
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a point shape at spriter's position.
|
||||
* @return {GeomSprite} GeomSprite instance itself.
|
||||
*/
|
||||
createPoint(): GeomSprite {
|
||||
|
||||
this.refresh();
|
||||
this.point = new Point(this.x, this.y);
|
||||
this.type = GeomSprite.POINT;
|
||||
this.frameBounds.width = 1;
|
||||
this.frameBounds.height = 1;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a rectangle shape of the given width and height size
|
||||
* @param width {Number} Width of the rectangle
|
||||
* @param height {Number} Height of the rectangle
|
||||
* @return {GeomSprite} GeomSprite instance.
|
||||
*/
|
||||
createRectangle(width: number, height: number): GeomSprite {
|
||||
|
||||
this.refresh();
|
||||
this.rect = new Rectangle(this.x, this.y, width, height);
|
||||
this.type = GeomSprite.RECTANGLE;
|
||||
this.frameBounds.copyFrom(this.rect);
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a polygon object
|
||||
* @param width {Number} Width of the rectangle
|
||||
* @param height {Number} Height of the rectangle
|
||||
* @return {GeomSprite} GeomSprite instance.
|
||||
*/
|
||||
createPolygon(points?: Vec2[] = []): GeomSprite {
|
||||
|
||||
//this.refresh();
|
||||
//this.polygon = new Polygon(new Vec2(this.x, this.y), points);
|
||||
//this.type = GeomSprite.POLYGON;
|
||||
//this.frameBounds.copyFrom(this.rect);
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy all geom shapes of this sprite.
|
||||
*/
|
||||
refresh() {
|
||||
|
||||
this.circle = null;
|
||||
this.line = null;
|
||||
this.point = null;
|
||||
this.rect = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update bounds.
|
||||
*/
|
||||
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.frameBounds.width = this.circle.diameter;
|
||||
this.frameBounds.height = this.circle.diameter;
|
||||
}
|
||||
else if (this.type == GeomSprite.LINE)
|
||||
{
|
||||
this.line.x1 = this.x;
|
||||
this.line.y1 = this.y;
|
||||
this.frameBounds.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.frameBounds.copyFrom(this.rect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this object is visible in a specific camera rectangle.
|
||||
* @param camera {Rectangle} The rectangle you want to check.
|
||||
* @return {boolean} Return true if bounds of this sprite intersects the given rectangle, otherwise return false.
|
||||
*/
|
||||
/*
|
||||
public inCamera(camera: Rectangle): bool {
|
||||
|
||||
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
|
||||
{
|
||||
this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
|
||||
this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
|
||||
this._dw = this.frameBounds.width * this.scale.x;
|
||||
this._dh = this.frameBounds.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.frameBounds);
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Render this sprite to specific camera. Called by game loop after update().
|
||||
* @param camera {Camera} Camera this sprite will be rendered to.
|
||||
* @cameraOffsetX {number} X offset to the camera.
|
||||
* @cameraOffsetY {number} Y offset to the camera.
|
||||
* @return {boolean} Return false if not rendered, otherwise return true.
|
||||
*/
|
||||
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.context.globalAlpha;
|
||||
this.context.globalAlpha = this.alpha;
|
||||
}
|
||||
|
||||
this._dx = cameraOffsetX + (this.frameBounds.x - camera.worldView.x);
|
||||
this._dy = cameraOffsetY + (this.frameBounds.y - camera.worldView.y);
|
||||
this._dw = this.frameBounds.width * this.scale.x;
|
||||
this._dh = this.frameBounds.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 is disabled for now as I don't want it to be misleading re: collision
|
||||
/*
|
||||
if (this.angle !== 0)
|
||||
{
|
||||
this.context.save();
|
||||
this.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y);
|
||||
this.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.context.fillStyle = 'rgba(255,0,0,0.5)';
|
||||
//this.context.fillRect(this.frameBounds.x, this.frameBounds.y, this.frameBounds.width, this.frameBounds.height);
|
||||
|
||||
this.context.lineWidth = this.lineWidth;
|
||||
this.context.strokeStyle = this.lineColor;
|
||||
this.context.fillStyle = this.fillColor;
|
||||
|
||||
if (this._game.stage.fillStyle !== this.fillColor)
|
||||
{
|
||||
}
|
||||
|
||||
// Primitive Renderer
|
||||
if (this.type == GeomSprite.CIRCLE)
|
||||
{
|
||||
this.context.beginPath();
|
||||
this.context.arc(this._dx, this._dy, this.circle.radius, 0, Math.PI * 2);
|
||||
|
||||
if (this.renderOutline)
|
||||
{
|
||||
this.context.stroke();
|
||||
}
|
||||
|
||||
if (this.renderFill)
|
||||
{
|
||||
this.context.fill();
|
||||
}
|
||||
|
||||
this.context.closePath();
|
||||
}
|
||||
else if (this.type == GeomSprite.LINE)
|
||||
{
|
||||
this.context.beginPath();
|
||||
this.context.moveTo(this._dx, this._dy);
|
||||
this.context.lineTo(this.line.x2, this.line.y2);
|
||||
this.context.stroke();
|
||||
this.context.closePath();
|
||||
}
|
||||
else if (this.type == GeomSprite.POINT)
|
||||
{
|
||||
this.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.context.fillRect(this._dx, this._dy, this.rect.width, this.rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.context.beginPath();
|
||||
this.context.rect(this._dx, this._dy, this.rect.width, this.rect.height);
|
||||
this.context.stroke();
|
||||
|
||||
if (this.renderFill)
|
||||
{
|
||||
this.context.fill();
|
||||
}
|
||||
|
||||
this.context.closePath();
|
||||
}
|
||||
|
||||
// And now the edge points
|
||||
this.context.fillStyle = 'rgb(255,255,255)';
|
||||
//this.renderPoint(this.rect.topLeft, this._dx, this._dy, 2);
|
||||
//this.renderPoint(this.rect.topCenter, this._dx, this._dy, 2);
|
||||
//this.renderPoint(this.rect.topRight, this._dx, this._dy, 2);
|
||||
//this.renderPoint(this.rect.leftCenter, this._dx, this._dy, 2);
|
||||
//this.renderPoint(this.rect.center, this._dx, this._dy, 2);
|
||||
//this.renderPoint(this.rect.rightCenter, this._dx, this._dy, 2);
|
||||
//this.renderPoint(this.rect.bottomLeft, this._dx, this._dy, 2);
|
||||
//this.renderPoint(this.rect.bottomCenter, this._dx, this._dy, 2);
|
||||
//this.renderPoint(this.rect.bottomRight, this._dx, this._dy, 2);
|
||||
this.renderPoint(this.rect.topLeft, 0, 0, 2);
|
||||
this.renderPoint(this.rect.topCenter, 0, 0, 2);
|
||||
this.renderPoint(this.rect.topRight, 0, 0, 2);
|
||||
this.renderPoint(this.rect.leftCenter, 0, 0, 2);
|
||||
this.renderPoint(this.rect.center, 0, 0, 2);
|
||||
this.renderPoint(this.rect.rightCenter, 0, 0, 2);
|
||||
this.renderPoint(this.rect.bottomLeft, 0, 0, 2);
|
||||
this.renderPoint(this.rect.bottomCenter, 0, 0, 2);
|
||||
this.renderPoint(this.rect.bottomRight, 0, 0, 2);
|
||||
|
||||
}
|
||||
|
||||
this._game.stage.restoreCanvasValues();
|
||||
|
||||
if (this.rotation !== 0)
|
||||
{
|
||||
this.context.translate(0, 0);
|
||||
this.context.restore();
|
||||
}
|
||||
|
||||
if (globalAlpha > -1)
|
||||
{
|
||||
this.context.globalAlpha = globalAlpha;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a point of geometry.
|
||||
* @param point {Point} Position of the point.
|
||||
* @param offsetX {number} X offset to its position.
|
||||
* @param offsetY {number} Y offset to its position.
|
||||
* @param [size] {number} point size.
|
||||
*/
|
||||
public renderPoint(point, offsetX?: number = 0, offsetY?: number = 0, size?: number = 1) {
|
||||
|
||||
this.context.fillRect(offsetX + point.x, offsetY + point.y, size, size);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Render debug infos. (this method does not work now)
|
||||
* @param x {number} X position of the debug info to be rendered.
|
||||
* @param y {number} Y position of the debug info to be rendered.
|
||||
* @param [color] {number} color of the debug info to be rendered. (format is css color string)
|
||||
*/
|
||||
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
|
||||
|
||||
//this.context.fillStyle = color;
|
||||
//this.context.fillText('Sprite: ' + this.name + ' (' + this.frameBounds.width + ' x ' + this.frameBounds.height + ')', x, y);
|
||||
//this.context.fillText('x: ' + this.frameBounds.x.toFixed(1) + ' y: ' + this.frameBounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
|
||||
//this.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.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.
|
||||
* @param source {GeomSprite} Sprite you want to check.
|
||||
* @return {boolean} Whether they overlaps or not.
|
||||
*/
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
19
todo/phaser clean up/Input.js
Normal file
19
todo/phaser clean up/Input.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
var Shapes;
|
||||
(function (Shapes) {
|
||||
|
||||
var Point = Shapes.Point = (function () {
|
||||
function Point(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
Point.prototype.getDist = function () {
|
||||
return Math.sqrt((this.x * this.x) + (this.y * this.y));
|
||||
};
|
||||
Point.origin = new Point(0, 0);
|
||||
return Point;
|
||||
})();
|
||||
|
||||
})(Shapes || (Shapes = {}));
|
||||
|
||||
var p = new Shapes.Point(3, 4);
|
||||
var dist = p.getDist();
|
29
todo/phaser clean up/Input.ts
Normal file
29
todo/phaser clean up/Input.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Phaser - Components - Input
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
module Phaser.Components {
|
||||
|
||||
export class Input {
|
||||
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Update input.
|
||||
*/
|
||||
private updateInput() {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
161
todo/phaser clean up/Motion.js
Normal file
161
todo/phaser clean up/Motion.js
Normal file
|
@ -0,0 +1,161 @@
|
|||
var Phaser;
|
||||
(function (Phaser) {
|
||||
var Motion = (function () {
|
||||
function Motion(game) {
|
||||
this._game = game;
|
||||
}
|
||||
Motion.prototype.computeVelocity = function (Velocity, Acceleration, Drag, Max) {
|
||||
if (typeof Acceleration === "undefined") { Acceleration = 0; }
|
||||
if (typeof Drag === "undefined") { Drag = 0; }
|
||||
if (typeof Max === "undefined") { Max = 10000; }
|
||||
if(Acceleration !== 0) {
|
||||
Velocity += Acceleration * this._game.time.elapsed;
|
||||
} else if(Drag !== 0) {
|
||||
var drag = Drag * this._game.time.elapsed;
|
||||
if(Velocity - drag > 0) {
|
||||
Velocity = Velocity - drag;
|
||||
} else if(Velocity + drag < 0) {
|
||||
Velocity += drag;
|
||||
} else {
|
||||
Velocity = 0;
|
||||
}
|
||||
}
|
||||
if((Velocity != 0) && (Max != 10000)) {
|
||||
if(Velocity > Max) {
|
||||
Velocity = Max;
|
||||
} else if(Velocity < -Max) {
|
||||
Velocity = -Max;
|
||||
}
|
||||
}
|
||||
return Velocity;
|
||||
};
|
||||
Motion.prototype.velocityFromAngle = function (angle, speed) {
|
||||
if(isNaN(speed)) {
|
||||
speed = 0;
|
||||
}
|
||||
var a = this._game.math.degreesToRadians(angle);
|
||||
return new Phaser.Point((Math.cos(a) * speed), (Math.sin(a) * speed));
|
||||
};
|
||||
Motion.prototype.moveTowardsObject = function (source, dest, speed, maxTime) {
|
||||
if (typeof speed === "undefined") { speed = 60; }
|
||||
if (typeof maxTime === "undefined") { maxTime = 0; }
|
||||
var a = this.angleBetween(source, dest);
|
||||
if(maxTime > 0) {
|
||||
var d = this.distanceBetween(source, dest);
|
||||
speed = d / (maxTime / 1000);
|
||||
}
|
||||
source.velocity.x = Math.cos(a) * speed;
|
||||
source.velocity.y = Math.sin(a) * speed;
|
||||
};
|
||||
Motion.prototype.accelerateTowardsObject = function (source, dest, speed, xSpeedMax, ySpeedMax) {
|
||||
var a = this.angleBetween(source, dest);
|
||||
source.velocity.x = 0;
|
||||
source.velocity.y = 0;
|
||||
source.acceleration.x = Math.cos(a) * speed;
|
||||
source.acceleration.y = Math.sin(a) * speed;
|
||||
source.maxVelocity.x = xSpeedMax;
|
||||
source.maxVelocity.y = ySpeedMax;
|
||||
};
|
||||
Motion.prototype.moveTowardsMouse = function (source, speed, maxTime) {
|
||||
if (typeof speed === "undefined") { speed = 60; }
|
||||
if (typeof maxTime === "undefined") { maxTime = 0; }
|
||||
var a = this.angleBetweenMouse(source);
|
||||
if(maxTime > 0) {
|
||||
var d = this.distanceToMouse(source);
|
||||
speed = d / (maxTime / 1000);
|
||||
}
|
||||
source.velocity.x = Math.cos(a) * speed;
|
||||
source.velocity.y = Math.sin(a) * speed;
|
||||
};
|
||||
Motion.prototype.accelerateTowardsMouse = function (source, speed, xSpeedMax, ySpeedMax) {
|
||||
var a = this.angleBetweenMouse(source);
|
||||
source.velocity.x = 0;
|
||||
source.velocity.y = 0;
|
||||
source.acceleration.x = Math.cos(a) * speed;
|
||||
source.acceleration.y = Math.sin(a) * speed;
|
||||
source.maxVelocity.x = xSpeedMax;
|
||||
source.maxVelocity.y = ySpeedMax;
|
||||
};
|
||||
Motion.prototype.moveTowardsPoint = function (source, target, speed, maxTime) {
|
||||
if (typeof speed === "undefined") { speed = 60; }
|
||||
if (typeof maxTime === "undefined") { maxTime = 0; }
|
||||
var a = this.angleBetweenPoint(source, target);
|
||||
if(maxTime > 0) {
|
||||
var d = this.distanceToPoint(source, target);
|
||||
speed = d / (maxTime / 1000);
|
||||
}
|
||||
source.velocity.x = Math.cos(a) * speed;
|
||||
source.velocity.y = Math.sin(a) * speed;
|
||||
};
|
||||
Motion.prototype.accelerateTowardsPoint = function (source, target, speed, xSpeedMax, ySpeedMax) {
|
||||
var a = this.angleBetweenPoint(source, target);
|
||||
source.velocity.x = 0;
|
||||
source.velocity.y = 0;
|
||||
source.acceleration.x = Math.cos(a) * speed;
|
||||
source.acceleration.y = Math.sin(a) * speed;
|
||||
source.maxVelocity.x = xSpeedMax;
|
||||
source.maxVelocity.y = ySpeedMax;
|
||||
};
|
||||
Motion.prototype.distanceBetween = function (a, b) {
|
||||
var dx = (a.x + a.origin.x) - (b.x + b.origin.x);
|
||||
var dy = (a.y + a.origin.y) - (b.y + b.origin.y);
|
||||
return this._game.math.vectorLength(dx, dy);
|
||||
};
|
||||
Motion.prototype.distanceToPoint = function (a, target) {
|
||||
var dx = (a.x + a.origin.x) - (target.x);
|
||||
var dy = (a.y + a.origin.y) - (target.y);
|
||||
return this._game.math.vectorLength(dx, dy);
|
||||
};
|
||||
Motion.prototype.distanceToMouse = function (a) {
|
||||
var dx = (a.x + a.origin.x) - this._game.input.x;
|
||||
var dy = (a.y + a.origin.y) - this._game.input.y;
|
||||
return this._game.math.vectorLength(dx, dy);
|
||||
};
|
||||
Motion.prototype.angleBetweenPoint = function (a, target, asDegrees) {
|
||||
if (typeof asDegrees === "undefined") { asDegrees = false; }
|
||||
var dx = (target.x) - (a.x + a.origin.x);
|
||||
var dy = (target.y) - (a.y + a.origin.y);
|
||||
if(asDegrees) {
|
||||
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
|
||||
} else {
|
||||
return Math.atan2(dy, dx);
|
||||
}
|
||||
};
|
||||
Motion.prototype.angleBetween = function (a, b, asDegrees) {
|
||||
if (typeof asDegrees === "undefined") { asDegrees = false; }
|
||||
var dx = (b.x + b.origin.x) - (a.x + a.origin.x);
|
||||
var dy = (b.y + b.origin.y) - (a.y + a.origin.y);
|
||||
if(asDegrees) {
|
||||
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
|
||||
} else {
|
||||
return Math.atan2(dy, dx);
|
||||
}
|
||||
};
|
||||
Motion.prototype.velocityFromFacing = function (parent, speed) {
|
||||
var a;
|
||||
if(parent.facing == Phaser.Collision.LEFT) {
|
||||
a = this._game.math.degreesToRadians(180);
|
||||
} else if(parent.facing == Phaser.Collision.RIGHT) {
|
||||
a = this._game.math.degreesToRadians(0);
|
||||
} else if(parent.facing == Phaser.Collision.UP) {
|
||||
a = this._game.math.degreesToRadians(-90);
|
||||
} else if(parent.facing == Phaser.Collision.DOWN) {
|
||||
a = this._game.math.degreesToRadians(90);
|
||||
}
|
||||
return new Phaser.Point(Math.cos(a) * speed, Math.sin(a) * speed);
|
||||
};
|
||||
Motion.prototype.angleBetweenMouse = function (a, asDegrees) {
|
||||
if (typeof asDegrees === "undefined") { asDegrees = false; }
|
||||
var p = a.getScreenXY();
|
||||
var dx = a._game.input.x - p.x;
|
||||
var dy = a._game.input.y - p.y;
|
||||
if(asDegrees) {
|
||||
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
|
||||
} else {
|
||||
return Math.atan2(dy, dx);
|
||||
}
|
||||
};
|
||||
return Motion;
|
||||
})();
|
||||
Phaser.Motion = Motion;
|
||||
})(Phaser || (Phaser = {}));
|
409
todo/phaser clean up/Motion.ts
Normal file
409
todo/phaser clean up/Motion.ts
Normal file
|
@ -0,0 +1,409 @@
|
|||
/// <reference path="Game.ts" />
|
||||
/// <reference path="gameobjects/GameObject.ts" />
|
||||
|
||||
/**
|
||||
* Phaser - Motion
|
||||
*
|
||||
* The Motion class contains lots of useful functions for moving game objects around in world space.
|
||||
*/
|
||||
|
||||
module Phaser {
|
||||
|
||||
export class Motion {
|
||||
|
||||
constructor(game: Game) {
|
||||
|
||||
this._game = game;
|
||||
|
||||
}
|
||||
|
||||
private _game: Game;
|
||||
|
||||
/**
|
||||
* A tween-like function that takes a starting velocity and some other factors and returns an altered velocity.
|
||||
*
|
||||
* @param {number} Velocity Any component of velocity (e.g. 20).
|
||||
* @param {number} 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 {number} Max An absolute value cap for the velocity.
|
||||
*
|
||||
* @return {number} The altered Velocity value.
|
||||
*/
|
||||
public computeVelocity(Velocity: number, Acceleration: number = 0, Drag: number = 0, Max: number = 10000): number {
|
||||
|
||||
if (Acceleration !== 0)
|
||||
{
|
||||
Velocity += Acceleration * this._game.time.elapsed;
|
||||
}
|
||||
else if (Drag !== 0)
|
||||
{
|
||||
var drag: number = Drag * this._game.time.elapsed;
|
||||
|
||||
if (Velocity - drag > 0)
|
||||
{
|
||||
Velocity = Velocity - drag;
|
||||
}
|
||||
else if (Velocity + drag < 0)
|
||||
{
|
||||
Velocity += drag;
|
||||
}
|
||||
else
|
||||
{
|
||||
Velocity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Velocity != 0) && (Max != 10000))
|
||||
{
|
||||
if (Velocity > Max)
|
||||
{
|
||||
Velocity = Max;
|
||||
}
|
||||
else if (Velocity < -Max)
|
||||
{
|
||||
Velocity = -Max;
|
||||
}
|
||||
}
|
||||
|
||||
return Velocity;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the angle and speed calculate the velocity and return it as a Point
|
||||
*
|
||||
* @param {number} 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
|
||||
*
|
||||
* @return {Point} 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 {
|
||||
|
||||
if (isNaN(speed))
|
||||
{
|
||||
speed = 0;
|
||||
}
|
||||
|
||||
var a: number = this._game.math.degreesToRadians(angle);
|
||||
|
||||
return new Point((Math.cos(a) * speed), (Math.sin(a) * speed));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source Sprite x/y velocity so it will move directly towards the destination Sprite at the speed given (in pixels per second)<br>
|
||||
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.<br>
|
||||
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<br>
|
||||
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
|
||||
* If you need the object to accelerate, see accelerateTowardsObject() instead
|
||||
* Note: Doesn't take into account acceleration, maxVelocity or drag (if you set drag or acceleration too high this object may not move at all)
|
||||
*
|
||||
* @param {GameObject} source The Sprite on which the velocity will be set
|
||||
* @param {GameObject} 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 {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
|
||||
*/
|
||||
public moveTowardsObject(source:GameObject, dest:GameObject, speed:number= 60, maxTime:number = 0)
|
||||
{
|
||||
var a:number = this.angleBetween(source, dest);
|
||||
|
||||
if (maxTime > 0)
|
||||
{
|
||||
var d:number = this.distanceBetween(source, dest);
|
||||
|
||||
// We know how many pixels we need to move, but how fast?
|
||||
speed = d / (maxTime / 1000);
|
||||
}
|
||||
|
||||
source.velocity.x = Math.cos(a) * speed;
|
||||
source.velocity.y = Math.sin(a) * speed;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the x/y acceleration on the source Sprite so it will move towards the destination Sprite at the speed given (in pixels per second)<br>
|
||||
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
|
||||
* If you don't need acceleration look at moveTowardsObject() instead.
|
||||
*
|
||||
* @param {GameObject} source The Sprite on which the acceleration will be set
|
||||
* @param {GameObject} dest The Sprite where the source object will move towards
|
||||
* @param {number} 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 {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
|
||||
*/
|
||||
public accelerateTowardsObject(source:GameObject, dest:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
|
||||
{
|
||||
var a:number = this.angleBetween(source, dest);
|
||||
|
||||
source.velocity.x = 0;
|
||||
source.velocity.y = 0;
|
||||
|
||||
source.acceleration.x = Math.cos(a) * speed;
|
||||
source.acceleration.y = Math.sin(a) * speed;
|
||||
|
||||
source.maxVelocity.x = xSpeedMax;
|
||||
source.maxVelocity.y = ySpeedMax;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the given Sprite towards the mouse pointer coordinates at a steady velocity
|
||||
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.<br>
|
||||
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<br>
|
||||
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
|
||||
*
|
||||
* @param {GameObject} source The Sprite to move
|
||||
* @param {number} 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
|
||||
*/
|
||||
public moveTowardsMouse(source:GameObject, speed:number = 60, maxTime:number = 0)
|
||||
{
|
||||
var a:number = this.angleBetweenMouse(source);
|
||||
|
||||
if (maxTime > 0)
|
||||
{
|
||||
var d:number = this.distanceToMouse(source);
|
||||
|
||||
// We know how many pixels we need to move, but how fast?
|
||||
speed = d / (maxTime / 1000);
|
||||
}
|
||||
|
||||
source.velocity.x = Math.cos(a) * speed;
|
||||
source.velocity.y = Math.sin(a) * speed;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the x/y acceleration on the source Sprite so it will move towards the mouse coordinates at the speed given (in pixels per second)<br>
|
||||
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
|
||||
* If you don't need acceleration look at moveTowardsMouse() instead.
|
||||
*
|
||||
* @param {GameObject} source The Sprite on which the acceleration will be set
|
||||
* @param {number} 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 {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
|
||||
*/
|
||||
public accelerateTowardsMouse(source:GameObject, speed:number, xSpeedMax:number, ySpeedMax:number)
|
||||
{
|
||||
var a:number = this.angleBetweenMouse(source);
|
||||
|
||||
source.velocity.x = 0;
|
||||
source.velocity.y = 0;
|
||||
|
||||
source.acceleration.x = Math.cos(a) * speed;
|
||||
source.acceleration.y = Math.sin(a) * speed;
|
||||
|
||||
source.maxVelocity.x = xSpeedMax;
|
||||
source.maxVelocity.y = ySpeedMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the x/y velocity on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)<br>
|
||||
* If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.<br>
|
||||
* Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.<br>
|
||||
* The source object doesn't stop moving automatically should it ever reach the destination coordinates.<br>
|
||||
*
|
||||
* @param {GameObject} source The Sprite to move
|
||||
* @param {Point} 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 {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
|
||||
*/
|
||||
public moveTowardsPoint(source:GameObject, target:Point, speed:number = 60, maxTime:number = 0)
|
||||
{
|
||||
var a:number = this.angleBetweenPoint(source, target);
|
||||
|
||||
if (maxTime > 0)
|
||||
{
|
||||
var d:number = this.distanceToPoint(source, target);
|
||||
|
||||
// We know how many pixels we need to move, but how fast?
|
||||
speed = d / (maxTime / 1000);
|
||||
}
|
||||
|
||||
source.velocity.x = Math.cos(a) * speed;
|
||||
source.velocity.y = Math.sin(a) * speed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the x/y acceleration on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)<br>
|
||||
* You must give a maximum speed value, beyond which the Sprite won't go any faster.<br>
|
||||
* If you don't need acceleration look at moveTowardsPoint() instead.
|
||||
*
|
||||
* @param {GameObject} source The Sprite on which the acceleration will be set
|
||||
* @param {Point} target The Point coordinates to move the source Sprite towards
|
||||
* @param {number} 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 {number} ySpeedMax The maximum speed in pixels per second in which the sprite can move vertically
|
||||
*/
|
||||
public accelerateTowardsPoint(source:GameObject, target:Point, speed:number, xSpeedMax:number, ySpeedMax:number)
|
||||
{
|
||||
var a:number = this.angleBetweenPoint(source, target);
|
||||
|
||||
source.velocity.x = 0;
|
||||
source.velocity.y = 0;
|
||||
|
||||
source.acceleration.x = Math.cos(a) * speed;
|
||||
source.acceleration.y = Math.sin(a) * speed;
|
||||
|
||||
source.maxVelocity.x = xSpeedMax;
|
||||
source.maxVelocity.y = ySpeedMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the distance (in pixels, rounded) between two Sprites, taking their origin into account
|
||||
*
|
||||
* @param {GameObject} a The first Sprite
|
||||
* @param {GameObject} b The second Sprite
|
||||
* @return {number} int Distance (in pixels)
|
||||
*/
|
||||
public distanceBetween(a:GameObject, b:GameObject):number
|
||||
{
|
||||
var dx:number = (a.x + a.origin.x) - (b.x + b.origin.x);
|
||||
var dy:number = (a.y + a.origin.y) - (b.y + b.origin.y);
|
||||
|
||||
return this._game.math.vectorLength(dx, dy);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the distance (in pixels, rounded) from an Sprite to the given Point, taking the source origin into account
|
||||
*
|
||||
* @param {GameObject} a The Sprite
|
||||
* @param {Point} target The Point
|
||||
* @return {number} Distance (in pixels)
|
||||
*/
|
||||
public distanceToPoint(a:GameObject, target:Point):number
|
||||
{
|
||||
var dx:number = (a.x + a.origin.x) - (target.x);
|
||||
var dy:number = (a.y + a.origin.y) - (target.y);
|
||||
|
||||
return this._game.math.vectorLength(dx, dy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the distance (in pixels, rounded) from the object x/y and the mouse x/y
|
||||
*
|
||||
* @param {GameObject} a Sprite to test against
|
||||
* @return {number} The distance between the given sprite and the mouse coordinates
|
||||
*/
|
||||
public distanceToMouse(a:GameObject):number
|
||||
{
|
||||
var dx: number = (a.x + a.origin.x) - this._game.input.x;
|
||||
var dy: number = (a.y + a.origin.y) - this._game.input.y;
|
||||
|
||||
return this._game.math.vectorLength(dx, dy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the angle (in radians) between an Sprite and an Point. The source sprite takes its x/y and origin into account.
|
||||
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
|
||||
*
|
||||
* @param {GameObject} a The Sprite to test from
|
||||
* @param {Point} target The Point to angle the Sprite towards
|
||||
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true
|
||||
*
|
||||
* @return {number} The angle (in radians unless asDegrees is true)
|
||||
*/
|
||||
public angleBetweenPoint(a:GameObject, target:Point, asDegrees:bool = false):number
|
||||
{
|
||||
var dx:number = (target.x) - (a.x + a.origin.x);
|
||||
var dy:number = (target.y) - (a.y + a.origin.y);
|
||||
|
||||
if (asDegrees)
|
||||
{
|
||||
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Math.atan2(dy, dx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the angle (in radians) between the two Sprite, taking their x/y and origin into account.
|
||||
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
|
||||
*
|
||||
* @param {GameObject} a The Sprite to test from
|
||||
* @param {GameObject} b The Sprite to test to
|
||||
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true
|
||||
*
|
||||
* @return {number} The angle (in radians unless asDegrees is true)
|
||||
*/
|
||||
public angleBetween(a:GameObject, b:GameObject, asDegrees:bool = false):number
|
||||
{
|
||||
var dx:number = (b.x + b.origin.x) - (a.x + a.origin.x);
|
||||
var dy:number = (b.y + b.origin.y) - (a.y + a.origin.y);
|
||||
|
||||
if (asDegrees)
|
||||
{
|
||||
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Math.atan2(dy, dx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the GameObject and speed calculate the velocity and return it as an Point based on the direction the sprite is facing
|
||||
*
|
||||
* @param {GameObject} parent The Sprite to get the facing value from
|
||||
* @param {number} 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
|
||||
*/
|
||||
public velocityFromFacing(parent:GameObject, speed:number):Point
|
||||
{
|
||||
var a:number;
|
||||
|
||||
if (parent.facing == Collision.LEFT)
|
||||
{
|
||||
a = this._game.math.degreesToRadians(180);
|
||||
}
|
||||
else if (parent.facing == Collision.RIGHT)
|
||||
{
|
||||
a = this._game.math.degreesToRadians(0);
|
||||
}
|
||||
else if (parent.facing == Collision.UP)
|
||||
{
|
||||
a = this._game.math.degreesToRadians(-90);
|
||||
}
|
||||
else if (parent.facing == Collision.DOWN)
|
||||
{
|
||||
a = this._game.math.degreesToRadians(90);
|
||||
}
|
||||
|
||||
return new Point(Math.cos(a) * speed, Math.sin(a) * speed);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account.
|
||||
* The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative)
|
||||
*
|
||||
* @param {GameObject} a The Object to test from
|
||||
* @param {boolean} asDegrees If you need the value in degrees instead of radians, set to true
|
||||
*
|
||||
* @return {number} The angle (in radians unless asDegrees is true)
|
||||
*/
|
||||
public angleBetweenMouse(a:GameObject, asDegrees:bool = false):number
|
||||
{
|
||||
// In order to get the angle between the object and mouse, we need the objects screen coordinates (rather than world coordinates)
|
||||
var p:MicroPoint = a.getScreenXY();
|
||||
|
||||
var dx:number = a._game.input.x - p.x;
|
||||
var dy:number = a._game.input.y - p.y;
|
||||
|
||||
if (asDegrees)
|
||||
{
|
||||
return this._game.math.radiansToDegrees(Math.atan2(dy, dx));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Math.atan2(dy, dx);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
BIN
todo/phaser clean up/N_tutorialAsrc.zip
Normal file
BIN
todo/phaser clean up/N_tutorialAsrc.zip
Normal file
Binary file not shown.
BIN
todo/phaser clean up/N_tutorialAsrc/tutA_demo05.fla
Normal file
BIN
todo/phaser clean up/N_tutorialAsrc/tutA_demo05.fla
Normal file
Binary file not shown.
BIN
todo/phaser clean up/N_tutorialAsrc/tutA_demo05.swf
Normal file
BIN
todo/phaser clean up/N_tutorialAsrc/tutA_demo05.swf
Normal file
Binary file not shown.
BIN
todo/phaser clean up/N_tutorialBsrc/tutB_demo04.fla
Normal file
BIN
todo/phaser clean up/N_tutorialBsrc/tutB_demo04.fla
Normal file
Binary file not shown.
BIN
todo/phaser clean up/N_tutorialBsrc/tutB_demo04.swf
Normal file
BIN
todo/phaser clean up/N_tutorialBsrc/tutB_demo04.swf
Normal file
Binary file not shown.
355
todo/phaser clean up/OldSprite.ts
Normal file
355
todo/phaser clean up/OldSprite.ts
Normal file
|
@ -0,0 +1,355 @@
|
|||
/// <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 OldSprite {
|
||||
|
||||
/**
|
||||
* Sprite constructor
|
||||
* Create a new <code>Sprite</code>.
|
||||
*
|
||||
* @param game {Phaser.Game} Current game instance.
|
||||
* @param [x] {number} the initial x position of the sprite.
|
||||
* @param [y] {number} the initial y position of the sprite.
|
||||
* @param [key] {string} Key of the graphic you want to load for this sprite.
|
||||
* @param [width] {number} The width of the object.
|
||||
* @param [height] {number} The height of the object.
|
||||
*/
|
||||
constructor(game: Game, x?: number = 0, y?: number = 0, key?: string = null, width?: number = 16, height?: number = 16) {
|
||||
|
||||
this.canvas = game.stage.canvas;
|
||||
this.context = game.stage.context;
|
||||
|
||||
this.frameBounds = 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.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);
|
||||
this.collisionMask = new CollisionMask(game, this, x, y, width, height);
|
||||
|
||||
|
||||
this._texture = null;
|
||||
|
||||
this.animations = new AnimationManager(this._game, this);
|
||||
|
||||
if (key !== null)
|
||||
{
|
||||
this.cacheKey = key;
|
||||
this.loadGraphic(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.frameBounds.width = 16;
|
||||
this.frameBounds.height = 16;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The essential reference to the main game object
|
||||
*/
|
||||
public _game: Game;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Setting this to true will prevent the object from being updated during the main game loop (you will have to call update on it yourself)
|
||||
*/
|
||||
public ignoreGlobalUpdate: bool;
|
||||
|
||||
/**
|
||||
* Setting this to true will prevent the object from being rendered during the main game loop (you will have to call render on it yourself)
|
||||
*/
|
||||
public ignoreGlobalRender: bool;
|
||||
|
||||
/**
|
||||
* An Array of Cameras to which this GameObject won't render
|
||||
* @type {Array}
|
||||
*/
|
||||
public cameraBlacklist: number[];
|
||||
|
||||
/**
|
||||
* Orientation of the object.
|
||||
* @type {number}
|
||||
*/
|
||||
public facing: number;
|
||||
|
||||
/**
|
||||
* Set alpha to a number between 0 and 1 to change the opacity.
|
||||
* @type {number}
|
||||
*/
|
||||
public alpha: number;
|
||||
|
||||
/**
|
||||
* Scale factor of the object.
|
||||
* @type {MicroPoint}
|
||||
*/
|
||||
public scale: MicroPoint;
|
||||
|
||||
/**
|
||||
* Controls if the GameObject is rendered rotated or not.
|
||||
* If renderRotation is false then the object can still rotate but it will never be rendered rotated.
|
||||
* @type {boolean}
|
||||
*/
|
||||
public renderRotation: bool = true;
|
||||
|
||||
/**
|
||||
* A point that can store numbers from 0 to 1 (for X and Y independently)
|
||||
* which governs how much this object is affected by the camera .
|
||||
* @type {MicroPoint}
|
||||
*/
|
||||
public scrollFactor: MicroPoint;
|
||||
|
||||
/**
|
||||
* Rectangle container of this object.
|
||||
* @type {Rectangle}
|
||||
*/
|
||||
public frameBounds: Rectangle;
|
||||
|
||||
/**
|
||||
* This objects CollisionMask
|
||||
* @type {CollisionMask}
|
||||
*/
|
||||
public collisionMask: CollisionMask;
|
||||
|
||||
/**
|
||||
* A rectangular area which is object is allowed to exist within. If it travels outside of this area it will perform the outOfBoundsAction.
|
||||
* @type {Quad}
|
||||
*/
|
||||
public worldBounds: Quad;
|
||||
|
||||
/**
|
||||
* A reference to the Canvas this GameObject will render to
|
||||
* @type {HTMLCanvasElement}
|
||||
*/
|
||||
public canvas: HTMLCanvasElement;
|
||||
|
||||
/**
|
||||
* A reference to the Canvas Context2D this GameObject will render to
|
||||
* @type {CanvasRenderingContext2D}
|
||||
*/
|
||||
public context: CanvasRenderingContext2D;
|
||||
|
||||
/**
|
||||
* Texture of this sprite to be rendered.
|
||||
*/
|
||||
private _texture;
|
||||
|
||||
/**
|
||||
* Texture of this sprite is DynamicTexture? (default to false)
|
||||
* @type {boolean}
|
||||
*/
|
||||
private _dynamicTexture: bool = false;
|
||||
|
||||
|
||||
/**
|
||||
* This manages animations of the sprite. You can modify animations though it. (see AnimationManager)
|
||||
* @type AnimationManager
|
||||
*/
|
||||
public animations: AnimationManager;
|
||||
|
||||
/**
|
||||
* The cache key that was used for this texture (if any)
|
||||
*/
|
||||
public cacheKey: string;
|
||||
|
||||
|
||||
/**
|
||||
* Flip the graphic horizontally? (defaults to false)
|
||||
* @type {boolean}
|
||||
*/
|
||||
public flipped: bool = false;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Pre-update is called right before update() on each object in the game loop.
|
||||
*/
|
||||
public preUpdate() {
|
||||
|
||||
this.last.x = this.frameBounds.x;
|
||||
this.last.y = this.frameBounds.y;
|
||||
|
||||
this.collisionMask.preUpdate();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this function to update your class's position and appearance.
|
||||
*/
|
||||
public update() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically called after update() by the game loop.
|
||||
*/
|
||||
public postUpdate() {
|
||||
|
||||
this.animations.update();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.collisionMask.update();
|
||||
|
||||
if (this.inputEnabled)
|
||||
{
|
||||
this.updateInput();
|
||||
}
|
||||
|
||||
this.wasTouching = this.touching;
|
||||
this.touching = Collision.NONE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up memory.
|
||||
*/
|
||||
public destroy() {
|
||||
}
|
||||
|
||||
public set width(value:number) {
|
||||
this.frameBounds.width = value;
|
||||
}
|
||||
|
||||
public set height(value:number) {
|
||||
this.frameBounds.height = value;
|
||||
}
|
||||
|
||||
public get width(): number {
|
||||
return this.frameBounds.width;
|
||||
}
|
||||
|
||||
public get height(): number {
|
||||
return this.frameBounds.height;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 "";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
19
todo/phaser clean up/Properties.js
Normal file
19
todo/phaser clean up/Properties.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
var Shapes;
|
||||
(function (Shapes) {
|
||||
|
||||
var Point = Shapes.Point = (function () {
|
||||
function Point(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
Point.prototype.getDist = function () {
|
||||
return Math.sqrt((this.x * this.x) + (this.y * this.y));
|
||||
};
|
||||
Point.origin = new Point(0, 0);
|
||||
return Point;
|
||||
})();
|
||||
|
||||
})(Shapes || (Shapes = {}));
|
||||
|
||||
var p = new Shapes.Point(3, 4);
|
||||
var dist = p.getDist();
|
36
todo/phaser clean up/Properties.ts
Normal file
36
todo/phaser clean up/Properties.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Phaser - Components - Properties
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
module Phaser.Components {
|
||||
|
||||
export class Properties {
|
||||
|
||||
/**
|
||||
* Handy for storing health percentage or armor points or whatever.
|
||||
* @type {number}
|
||||
*/
|
||||
public health: number;
|
||||
|
||||
/**
|
||||
* Reduces the "health" variable of this sprite by the amount specified in Damage.
|
||||
* Calls kill() if health drops to or below zero.
|
||||
*
|
||||
* @param Damage {number} 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
BIN
todo/phaser clean up/SAT.zip
Normal file
BIN
todo/phaser clean up/SAT.zip
Normal file
Binary file not shown.
187
todo/phaser clean up/Tilemap.js
Normal file
187
todo/phaser clean up/Tilemap.js
Normal file
|
@ -0,0 +1,187 @@
|
|||
var __extends = this.__extends || function (d, b) {
|
||||
function __() { this.constructor = d; }
|
||||
__.prototype = b.prototype;
|
||||
d.prototype = new __();
|
||||
};
|
||||
var Phaser;
|
||||
(function (Phaser) {
|
||||
var Tilemap = (function (_super) {
|
||||
__extends(Tilemap, _super);
|
||||
function Tilemap(game, key, mapData, format, resizeWorld, tileWidth, tileHeight) {
|
||||
if (typeof resizeWorld === "undefined") { resizeWorld = true; }
|
||||
if (typeof tileWidth === "undefined") { tileWidth = 0; }
|
||||
if (typeof tileHeight === "undefined") { tileHeight = 0; }
|
||||
_super.call(this, game);
|
||||
this.collisionCallback = null;
|
||||
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);
|
||||
}
|
||||
}
|
||||
Tilemap.FORMAT_CSV = 0;
|
||||
Tilemap.FORMAT_TILED_JSON = 1;
|
||||
Tilemap.prototype.update = function () {
|
||||
};
|
||||
Tilemap.prototype.render = function (camera, cameraOffsetX, cameraOffsetY) {
|
||||
if(this.cameraBlacklist.indexOf(camera.ID) == -1) {
|
||||
for(var i = 0; i < this.layers.length; i++) {
|
||||
this.layers[i].render(camera, cameraOffsetX, cameraOffsetY);
|
||||
}
|
||||
}
|
||||
};
|
||||
Tilemap.prototype.parseCSV = function (data, key, tileWidth, tileHeight) {
|
||||
var layer = new Phaser.TilemapLayer(this._game, this, key, Phaser.Tilemap.FORMAT_CSV, 'TileLayerCSV' + this.layers.length.toString(), tileWidth, tileHeight);
|
||||
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);
|
||||
};
|
||||
Tilemap.prototype.parseTiledJSON = function (data, key) {
|
||||
data = data.trim();
|
||||
var json = JSON.parse(data);
|
||||
for(var i = 0; i < json.layers.length; i++) {
|
||||
var layer = new Phaser.TilemapLayer(this._game, this, key, Phaser.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);
|
||||
};
|
||||
Tilemap.prototype.generateTiles = function (qty) {
|
||||
for(var i = 0; i < qty; i++) {
|
||||
this.tiles.push(new Phaser.Tile(this._game, this, i, this.currentLayer.tileWidth, this.currentLayer.tileHeight));
|
||||
}
|
||||
};
|
||||
Object.defineProperty(Tilemap.prototype, "widthInPixels", {
|
||||
get: function () {
|
||||
return this.currentLayer.widthInPixels;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(Tilemap.prototype, "heightInPixels", {
|
||||
get: function () {
|
||||
return this.currentLayer.heightInPixels;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Tilemap.prototype.setCollisionCallback = function (context, callback) {
|
||||
this.collisionCallbackContext = context;
|
||||
this.collisionCallback = callback;
|
||||
};
|
||||
Tilemap.prototype.setCollisionRange = function (start, end, collision, resetCollisions, separateX, separateY) {
|
||||
if (typeof collision === "undefined") { collision = Phaser.Collision.ANY; }
|
||||
if (typeof resetCollisions === "undefined") { resetCollisions = false; }
|
||||
if (typeof separateX === "undefined") { separateX = true; }
|
||||
if (typeof separateY === "undefined") { separateY = true; }
|
||||
for(var i = start; i < end; i++) {
|
||||
this.tiles[i].setCollision(collision, resetCollisions, separateX, separateY);
|
||||
}
|
||||
};
|
||||
Tilemap.prototype.setCollisionByIndex = function (values, collision, resetCollisions, separateX, separateY) {
|
||||
if (typeof collision === "undefined") { collision = Phaser.Collision.ANY; }
|
||||
if (typeof resetCollisions === "undefined") { resetCollisions = false; }
|
||||
if (typeof separateX === "undefined") { separateX = true; }
|
||||
if (typeof separateY === "undefined") { separateY = true; }
|
||||
for(var i = 0; i < values.length; i++) {
|
||||
this.tiles[values[i]].setCollision(collision, resetCollisions, separateX, separateY);
|
||||
}
|
||||
};
|
||||
Tilemap.prototype.getTileByIndex = function (value) {
|
||||
if(this.tiles[value]) {
|
||||
return this.tiles[value];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Tilemap.prototype.getTile = function (x, y, layer) {
|
||||
if (typeof layer === "undefined") { layer = 0; }
|
||||
return this.tiles[this.layers[layer].getTileIndex(x, y)];
|
||||
};
|
||||
Tilemap.prototype.getTileFromWorldXY = function (x, y, layer) {
|
||||
if (typeof layer === "undefined") { layer = 0; }
|
||||
return this.tiles[this.layers[layer].getTileFromWorldXY(x, y)];
|
||||
};
|
||||
Tilemap.prototype.getTileFromInputXY = function (layer) {
|
||||
if (typeof layer === "undefined") { layer = 0; }
|
||||
return this.tiles[this.layers[layer].getTileFromWorldXY(this._game.input.getWorldX(), this._game.input.getWorldY())];
|
||||
};
|
||||
Tilemap.prototype.getTileOverlaps = function (object) {
|
||||
return this.currentLayer.getTileOverlaps(object);
|
||||
};
|
||||
Tilemap.prototype.collide = function (objectOrGroup, callback, context) {
|
||||
if (typeof objectOrGroup === "undefined") { objectOrGroup = null; }
|
||||
if (typeof callback === "undefined") { callback = null; }
|
||||
if (typeof context === "undefined") { context = null; }
|
||||
if(callback !== null && context !== null) {
|
||||
this.collisionCallback = callback;
|
||||
this.collisionCallbackContext = context;
|
||||
}
|
||||
if(objectOrGroup == null) {
|
||||
objectOrGroup = this._game.world.group;
|
||||
}
|
||||
if(objectOrGroup.isGroup == false) {
|
||||
this.collideGameObject(objectOrGroup);
|
||||
} else {
|
||||
objectOrGroup.forEachAlive(this, this.collideGameObject, true);
|
||||
}
|
||||
};
|
||||
Tilemap.prototype.collideGameObject = function (object) {
|
||||
if(object !== this && object.immovable == false && object.exists == true && object.allowCollisions != Phaser.Collision.NONE) {
|
||||
this._tempCollisionData = this.collisionLayer.getTileOverlaps(object);
|
||||
if(this.collisionCallback !== null && this._tempCollisionData.length > 0) {
|
||||
this.collisionCallback.call(this.collisionCallbackContext, object, this._tempCollisionData);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Tilemap.prototype.putTile = function (x, y, index, layer) {
|
||||
if (typeof layer === "undefined") { layer = 0; }
|
||||
this.layers[layer].putTile(x, y, index);
|
||||
};
|
||||
return Tilemap;
|
||||
})(Phaser.GameObject);
|
||||
Phaser.Tilemap = Tilemap;
|
||||
})(Phaser || (Phaser = {}));
|
434
todo/phaser clean up/Tilemap.ts
Normal file
434
todo/phaser clean up/Tilemap.ts
Normal file
|
@ -0,0 +1,434 @@
|
|||
/// <reference path="../Game.ts" />
|
||||
/// <reference path="../components/TilemapLayer.ts" />
|
||||
/// <reference path="../components/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 {
|
||||
|
||||
/**
|
||||
* Tilemap constructor
|
||||
* Create a new <code>Tilemap</code>.
|
||||
*
|
||||
* @param game {Phaser.Game} Current game instance.
|
||||
* @param key {string} Asset key for this map.
|
||||
* @param mapData {string} Data of this map. (a big 2d array, normally in csv)
|
||||
* @param format {number} Format of this map data, available: Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON.
|
||||
* @param resizeWorld {boolean} Resize the world bound automatically based on this tilemap?
|
||||
* @param tileWidth {number} Width of tiles in this map.
|
||||
* @param tileHeight {number} Height of tiles in this map.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private _tempCollisionData;
|
||||
|
||||
/**
|
||||
* Tilemap data format enum: CSV.
|
||||
* @type {number}
|
||||
*/
|
||||
public static FORMAT_CSV: number = 0;
|
||||
/**
|
||||
* Tilemap data format enum: Tiled JSON.
|
||||
* @type {number}
|
||||
*/
|
||||
public static FORMAT_TILED_JSON: number = 1;
|
||||
|
||||
/**
|
||||
* Array contains tile objects of this map.
|
||||
* @type {Tile[]}
|
||||
*/
|
||||
public tiles : Tile[];
|
||||
/**
|
||||
* Array contains tilemap layer objects of this map.
|
||||
* @type {TilemapLayer[]}
|
||||
*/
|
||||
public layers : TilemapLayer[];
|
||||
/**
|
||||
* Current tilemap layer.
|
||||
* @type {TilemapLayer}
|
||||
*/
|
||||
public currentLayer: TilemapLayer;
|
||||
/**
|
||||
* The tilemap layer for collision.
|
||||
* @type {TilemapLayer}
|
||||
*/
|
||||
public collisionLayer: TilemapLayer;
|
||||
/**
|
||||
* Tilemap collision callback.
|
||||
* @type {function}
|
||||
*/
|
||||
public collisionCallback = null;
|
||||
/**
|
||||
* Context for the collision callback called with.
|
||||
*/
|
||||
public collisionCallbackContext;
|
||||
/**
|
||||
* Format of this tilemap data. Available values: Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON.
|
||||
* @type {number}
|
||||
*/
|
||||
public mapFormat: number;
|
||||
|
||||
/**
|
||||
* Inherited update method.
|
||||
*/
|
||||
public update() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Render this tilemap to a specific camera with specific offset.
|
||||
* @param camera {Camera} The camera this tilemap will be rendered to.
|
||||
* @param cameraOffsetX {number} X offset of the camera.
|
||||
* @param cameraOffsetY {number} Y offset of the camera.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parset csv map data and generate tiles.
|
||||
* @param data {string} CSV map data.
|
||||
* @param key {string} Asset key for tileset image.
|
||||
* @param tileWidth {number} Width of its tile.
|
||||
* @param tileHeight {number} Height of its tile.
|
||||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parset JSON map data and generate tiles.
|
||||
* @param data {string} JSON map data.
|
||||
* @param key {string} Asset key for tileset image.
|
||||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create tiles of given quantity.
|
||||
* @param qty {number} Quentity of tiles to be generated.
|
||||
*/
|
||||
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
|
||||
|
||||
/**
|
||||
* Set callback to be called when this tilemap collides.
|
||||
* @param context {object} Callback will be called with this context.
|
||||
* @param callback {function} Callback function.
|
||||
*/
|
||||
public setCollisionCallback(context, callback) {
|
||||
|
||||
this.collisionCallbackContext = context;
|
||||
this.collisionCallback = callback;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set collision configs of tiles in a range index.
|
||||
* @param start {number} First index of tiles.
|
||||
* @param end {number} Last index of tiles.
|
||||
* @param collision {number} Bit field of flags. (see Tile.allowCollision)
|
||||
* @param resetCollisions {boolean} Reset collision flags before set.
|
||||
* @param separateX {boolean} Enable seprate at x-axis.
|
||||
* @param separateY {boolean} Enable seprate at y-axis.
|
||||
*/
|
||||
public setCollisionRange(start: number, end: number, collision?:number = Collision.ANY, resetCollisions?: bool = false, separateX?: bool = true, separateY?: bool = true) {
|
||||
|
||||
for (var i = start; i < end; i++)
|
||||
{
|
||||
this.tiles[i].setCollision(collision, resetCollisions, separateX, separateY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set collision configs of tiles with given index.
|
||||
* @param values {number[]} Index array which contains all tile indexes. The tiles with those indexes will be setup with rest parameters.
|
||||
* @param collision {number} Bit field of flags. (see Tile.allowCollision)
|
||||
* @param resetCollisions {boolean} Reset collision flags before set.
|
||||
* @param separateX {boolean} Enable seprate at x-axis.
|
||||
* @param separateY {boolean} Enable seprate at y-axis.
|
||||
*/
|
||||
public setCollisionByIndex(values:number[], collision?:number = Collision.ANY, resetCollisions?: bool = false, separateX?: bool = true, separateY?: bool = true) {
|
||||
|
||||
for (var i = 0; i < values.length; i++)
|
||||
{
|
||||
this.tiles[values[i]].setCollision(collision, resetCollisions, separateX, separateY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Tile Management
|
||||
|
||||
/**
|
||||
* Get the tile by its index.
|
||||
* @param value {number} Index of the tile you want to get.
|
||||
* @return {Tile} The tile with given index.
|
||||
*/
|
||||
public getTileByIndex(value: number):Tile {
|
||||
|
||||
if (this.tiles[value])
|
||||
{
|
||||
return this.tiles[value];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tile located at specific position and layer.
|
||||
* @param x {number} X position of this tile located.
|
||||
* @param y {number} Y position of this tile located.
|
||||
* @param [layer] {number} layer of this tile located.
|
||||
* @return {Tile} The tile with specific properties.
|
||||
*/
|
||||
public getTile(x: number, y: number, layer?: number = 0):Tile {
|
||||
|
||||
return this.tiles[this.layers[layer].getTileIndex(x, y)];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tile located at specific position (in world coordinate) and layer. (thus you give a position of a point which is within the tile)
|
||||
* @param x {number} X position of the point in target tile.
|
||||
* @param x {number} Y position of the point in target tile.
|
||||
* @param [layer] {number} layer of this tile located.
|
||||
* @return {Tile} The tile with specific properties.
|
||||
*/
|
||||
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.getWorldX(), this._game.input.getWorldY())];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tiles overlaps the given object.
|
||||
* @param object {GameObject} Tiles you want to get that overlaps this.
|
||||
* @return {array} Array with tiles informations. (Each contains x, y and the tile.)
|
||||
*/
|
||||
public getTileOverlaps(object: GameObject) {
|
||||
|
||||
return this.currentLayer.getTileOverlaps(object);
|
||||
|
||||
}
|
||||
|
||||
// COLLIDE
|
||||
/**
|
||||
* Check whether this tilemap collides with the given game object or group of objects.
|
||||
* @param objectOrGroup {function} Target object of group you want to check.
|
||||
* @param callback {function} This is called if objectOrGroup collides the tilemap.
|
||||
* @param context {object} Callback will be called with this context.
|
||||
* @return {boolean} Return true if this collides with given object, otherwise return false.
|
||||
*/
|
||||
public collide(objectOrGroup = null, callback = null, context = null) {
|
||||
|
||||
if (callback !== null && context !== null)
|
||||
{
|
||||
this.collisionCallback = callback;
|
||||
this.collisionCallbackContext = context;
|
||||
}
|
||||
|
||||
if (objectOrGroup == null)
|
||||
{
|
||||
objectOrGroup = this._game.world.group;
|
||||
}
|
||||
|
||||
// Group?
|
||||
if (objectOrGroup.isGroup == false)
|
||||
{
|
||||
this.collideGameObject(objectOrGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectOrGroup.forEachAlive(this, this.collideGameObject, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this tilemap collides with the given game object.
|
||||
* @param object {GameObject} Target object you want to check.
|
||||
* @return {boolean} Return true if this collides with given object, otherwise return false.
|
||||
*/
|
||||
public collideGameObject(object: GameObject): bool {
|
||||
|
||||
if (object !== this && object.immovable == false && object.exists == true && object.allowCollisions != Collision.NONE)
|
||||
{
|
||||
this._tempCollisionData = this.collisionLayer.getTileOverlaps(object);
|
||||
|
||||
if (this.collisionCallback !== null && this._tempCollisionData.length > 0)
|
||||
{
|
||||
this.collisionCallback.call(this.collisionCallbackContext, object, this._tempCollisionData);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a tile to a specific layer.
|
||||
* @param x {number} X position of this tile.
|
||||
* @param y {number} Y position of this tile.
|
||||
* @param index {number} The index of this tile type in the core map data.
|
||||
* @param [layer] {number} which layer you want to set the tile to.
|
||||
*/
|
||||
public putTile(x: number, y: number, index: number, layer?: number = 0) {
|
||||
|
||||
this.layers[layer].putTile(x, y, index);
|
||||
|
||||
}
|
||||
|
||||
// Set current layer
|
||||
// Set layer order?
|
||||
// Delete tiles of certain type
|
||||
// Erase tiles
|
||||
|
||||
}
|
||||
|
||||
}
|
715
todo/phaser clean up/fitc/FITC_beyondHittest.txt
Normal file
715
todo/phaser clean up/fitc/FITC_beyondHittest.txt
Normal file
|
@ -0,0 +1,715 @@
|
|||
PART -1: intro/preamble
|
||||
|
||||
[3]**
|
||||
-download the slides at: [++TODO: URL to slides.. metanet/tutorials/fitc05.zip?]
|
||||
|
||||
who am i
|
||||
-one of two people who made N
|
||||
-we've been using flash since v5 (i.e since actionscript was useful and easy to use)
|
||||
|
||||
<short demo of N, just watch a mainmenu replay>**
|
||||
|
||||
-promo blurb: "N is a platform/run-and-jump game which combines oldschool gameplay
|
||||
with modern collision detection + physics simulation"
|
||||
|
||||
-we made N with flash prove that flash/actionscript could be used for "real video games"
|
||||
|
||||
|
||||
[4]** -"the curse of sylvaniah" (by Strille/Luxregina) is another great game which also proves our point:
|
||||
games made in flash can be "real video games"
|
||||
|
||||
|
||||
[5]** -collision detection is a vast feild of research
|
||||
-impossible to cover properly in an hour.
|
||||
-i'll present specific methods well-suited for use in flash/actionscript
|
||||
-some of the ideas we used in N, as well as some of the stuff we've learnt since making N
|
||||
-there is a LOT of stuff to cover
|
||||
|
||||
-i'm going to try to introduce you to the ideas involved without a lot of technical detail
|
||||
-understand the concepts, independent from the implementation of the concept
|
||||
-there WILL be some code and formulas and stuff
|
||||
-it's more important to understand the meaning behind the code and formulas.
|
||||
|
||||
-you can check out our online tutorials if you need to look at source.
|
||||
|
||||
-warning: i'm a programmer. these slides count as "programmer art".
|
||||
|
||||
-ask:
|
||||
-how many people know what a vector is?
|
||||
-how many people know what a dotproduct is?
|
||||
|
||||
|
||||
[6]**
|
||||
-to begin:
|
||||
-this lecture is about collision detection
|
||||
-implicitly, it's about game programming in flash
|
||||
-game programming in flash feels a bit wrong.
|
||||
-it certainly wasn't made for video games.
|
||||
-there is a sense of "we're abusing this platform"
|
||||
-but we're going to write games in flash anyway, so why not try to do it well.
|
||||
-i'll start by trying to convince you about why collision detection matters
|
||||
-then i'll discuss some solutions for dealing with collision detection
|
||||
|
||||
|
||||
|
||||
MOTIVATION:
|
||||
|
||||
-why does collision detection matter? is it only useful for ninja platformers?
|
||||
[7]** -no. a lot of games would benefit from better collision detection/response
|
||||
-everyone's favorite, the top-view racing game
|
||||
-pool, pinball,
|
||||
-basketball/sports (show McShitOut and/or scribball demo)
|
||||
-platforming games
|
||||
[8]** -most importantly: _new_ types of genre-defying games which you're going to invent next week
|
||||
[9]** -having a good collision detection+response system enables a wide range of (otherwise inaccessible) gameplay possibilities.
|
||||
|
||||
|
||||
[10]**
|
||||
-HitTest:
|
||||
-why do we need to learn about collision detection?
|
||||
-doesn't flash already have built-in collision detection?
|
||||
-yes, but it has two major weaknesses
|
||||
1: only returns a yes/no answer
|
||||
2: only works with axis-aligned rectangles
|
||||
|
||||
[11]** -what can you do with a yes/no answer?:
|
||||
[12]** -destroy one/both objects
|
||||
[13]** -move one/both objects to old position
|
||||
[14]** -reverse direction of one/both objects
|
||||
-or any combination of the above
|
||||
|
||||
[15]** -what can't you do with a yes/no answer?:
|
||||
[16]** -friction and bounce
|
||||
[17]** -sliding along obstacles
|
||||
[18]** -rotating to orient to the ground
|
||||
-etc.
|
||||
|
||||
[19]** -what can you do with axis-aligned rectangles?:
|
||||
-anything! ..as long as it involves unrotated rectangles
|
||||
|
||||
[20]** -what can't you do with axis-aligned rectangles?:
|
||||
-circles
|
||||
-concave surfaces
|
||||
-curved or angled surfaces
|
||||
-rotating shapes
|
||||
-etc.
|
||||
|
||||
[21]** -using hittest, if you need more than a yes/no answer about a collision, you can use "tricks":
|
||||
-sample multiple points on an object
|
||||
-from the multiple yes/no results, infer information about the collision direction, etc.
|
||||
|
||||
-if you work hard enough, you _might_ get it to work..
|
||||
|
||||
[22]** -it will be slower than it needs to be (due to the number of calls to hittest)
|
||||
-it won't work 100% of the time (because you're relying on implied/approximated and not actual information)
|
||||
-it just doesn't feel as solid as "the real thing"
|
||||
|
||||
|
||||
[23]** -HitTest is awesome -- if you're living in the 80s
|
||||
-lots of moving rectangles which explode when they touch each other
|
||||
-if you want to actually respond to collisions in a meaningful way, HitTest isn't enough
|
||||
-meaningful collision response requires meaningful information about the collision.
|
||||
-better information, better response, better games, better "feel"
|
||||
-ultimately, "real" (non-HitTest) collision detection enables "physics"
|
||||
|
||||
|
||||
-physics?!
|
||||
[24]** -in video games this year, "physics is the new graphics".. everyone wants more physics in their games.
|
||||
-one common misconception is that "physics" means "slow and complex code". physics doesn't have to be complicated or slow.
|
||||
|
||||
<demo ragdoll>**
|
||||
|
||||
[25]** -"physics" is a much-abused term.
|
||||
-most of the time it just means "things moving".
|
||||
-if you've ever written "position += velocity" or "newpos = oldpos + velocity",
|
||||
you've already been using "physics".
|
||||
-what are you afraid of?
|
||||
|
||||
[26]** -the only math you need to know is some vector algebra/geometry which we'll cover
|
||||
-no trig: trig is horrible
|
||||
-it's very difficult to develop an intuition about it
|
||||
-it's very hard to visualize when thinking about a problem
|
||||
-vectors are your friends
|
||||
-they can be used to replace trig in 99% of situations
|
||||
-they are easy to visualize and develop intuitions about
|
||||
|
||||
[27]** -most importantly: flash vs. SNES
|
||||
-way less graphical power, way more processing power
|
||||
|
||||
-flash can't compete with modern (or even classic) video games when it comes to graphical power
|
||||
-consoles and PCs have dedicated graphics hardware; flash has only got the CPU
|
||||
|
||||
-flash CAN compete in terms of processing power and memory
|
||||
-the SNES (which came out in 1991) had the same processor as an apple IIgs..
|
||||
-even with the overhead of the flashplayer VM, flash outperforms the SNES in terms of both speed and complexity
|
||||
-double-precision floating point, which lets us do a lot of things which simply weren't possible on an SNES
|
||||
-because of the overhead of the flash VM, "expensive" ops like sqrt() aren't
|
||||
really much more expensive than any other math op (+, -, etc.)
|
||||
-this gives us flexibility to pursue different solutions (which might not be tractable on other platforms)
|
||||
-flashplayer has built-in support for sophisticated structures like hashmaps (i.e "objects")
|
||||
and dynamic memory management
|
||||
-this makes it easier for us to explore complex ideas than possible on a SNES
|
||||
|
||||
[28]** -so: flash games have the ability to compete with modern (or classic) video games on the battlefield known as "gameplay"
|
||||
-collision detection and physics are two great tools for developing novel gameplay
|
||||
|
||||
[29]** -some examples of games that are using collision detection and physics to create different types of gameplay
|
||||
[30]**
|
||||
[31]**
|
||||
[32]**
|
||||
|
||||
-hopefully you're now motivated
|
||||
|
||||
|
||||
[33]**
|
||||
PART 0: collision response
|
||||
|
||||
-collision response is important to mention breifly because it provides the motivation for collision detection
|
||||
-see our website for tutorials and links to more info
|
||||
|
||||
-collision response is _why_ you need a collision detection solution that's more informative than HitTest
|
||||
-collision detection provides you with information describing a collision;
|
||||
-if you don't _use_ this information in a meaningful way, CD is moot
|
||||
|
||||
[34]** -collision response "in a nutshell":
|
||||
-there are many different ways to handle collision response
|
||||
-they all of the need to know the same thing
|
||||
|
||||
[35]** -penetration direction, penetration amount
|
||||
-pdir*pamt = penetration vector, projection vector, etc.
|
||||
-i may use "penetration vector" and "projection vector" interchangeably
|
||||
|
||||
[36]** -one thing we want to do when notified of a collision is prevent the two colliding objects from continuing to collide
|
||||
-a simple solution to this is "projection"
|
||||
-given two colliding objects and their penetration vector
|
||||
-translate (move) one object by the penetration vector
|
||||
-OR: translate both objects by 1/2 the penetration vector
|
||||
-etc.. playing with the ratios allows the simulation of objects with different relative mass
|
||||
-i.e heavy objects aren't moved very much
|
||||
|
||||
[37]** -aside from preventing the objects from continuing to overlap, you can modify their properties based on the direction of the collision surface
|
||||
-penetration vector describes the surface direction of the collision
|
||||
-you can measure the velocity of objects parallel to and perpendicular to the surface
|
||||
-we'll cover the math later, it's simple vector projection
|
||||
[38]** -you break the object's velocity down into those two components
|
||||
-scale each component seperately/differently, and recombine them to get the post-collision velocity
|
||||
-this lets you simulate friction/bounce
|
||||
|
||||
-you can also let game logic make decisions based collision information
|
||||
-rotating object graphics so that they align themselves to the ground
|
||||
-inflicting damage for violent collisions
|
||||
(the object's velocity perpendicular to the surface tells you how violent the collision was)
|
||||
|
||||
<demo: level 0-0, ninja skidding around and rotating to match the surface of things>**
|
||||
<demo: level 0-0, ninja falling to death>**
|
||||
|
||||
|
||||
|
||||
|
||||
[39]**
|
||||
PART 1: narrow-phase collision detection, aka object-vs-object testing
|
||||
|
||||
[40]** -so, what we need to do when performing collision detection on a pair of shapes is:
|
||||
(a) determine if the two shapes are colliding, and if so
|
||||
(b) calculate the penetration vector which describes the collision
|
||||
|
||||
[41]** -actually.. that's only half of the collision detection problem.
|
||||
-the other half is knowing which pairs of shapes to test in the first place
|
||||
|
||||
[42]** -these two parts of the collision detection process are often called "narrow" and "broad" phase collision detection
|
||||
-broad = figuring out which pairs of objects we must test
|
||||
-narrow = testing each pair
|
||||
-sort of like sifting through something: start with a coarse filter to elliminate most things, then use a fine-grained filter on the remaining stuff
|
||||
|
||||
-we'll start with narrow-phase and then discuss broad-phase
|
||||
|
||||
-i'll try to answer questions breifly after each section
|
||||
-i'd prefer to stick to specific questions (i.e if i'm not explaining something in detail)
|
||||
-leave larger questions for Q&A at the end of the presentation
|
||||
|
||||
|
||||
-there are several different approaches to object-vs-object tests; the one i'm going to describe is based on something called "the method of seperating axes" <todo: refer to ginoVDB and geomtools books>
|
||||
-it's well-suited for flash
|
||||
-fast (faster than any other method we've seen)
|
||||
-simple (easy to understand, easy to code)
|
||||
-flexible (easy to adapt to many different situations)
|
||||
|
||||
[43]**
|
||||
-the method of seperating axes, in english
|
||||
-there will be a lot of "axis" talk
|
||||
-axis really just means "direction". any time you hear "axis", you can mentally substitute "direction".
|
||||
-1 vector, many vertices
|
||||
-1 axis, many axes
|
||||
|
||||
[44]** -the Method of Seperating Axes is based on the Seperating Axis Theorem:
|
||||
-a mathmatical theorem about the properties of convex polygons
|
||||
[45]** -thus, this method only works for convex shapes
|
||||
-what is a convex shape? probably you've at least got an intuitive understanding of convexity.
|
||||
there are many "practical" definitions:
|
||||
-no internal angles <= 180deg
|
||||
-a line connecting any two points inside the shape is contained within the shape
|
||||
-only lefthand turns when walking CCW around the surface
|
||||
-etc.
|
||||
|
||||
|
||||
[46]** -Seperating Axis Theorem, part 1:
|
||||
-if two convex polygons don't overlap, then there must be a direction along which they are "seperated"
|
||||
-the converse is also true: if there is no direction which seperates two objects, the objects must be overlapping
|
||||
-"seperated" means that, if we look at the world along that direction, there is a space between the two shapes
|
||||
-the direction we look along is called an axis
|
||||
-if the two objects are seperated, it's a seperating axis
|
||||
-you could think of it as a line through the objects; it's offset in diagrams to make it less cluttered/confusing
|
||||
<diagram: show seperated and overlapping cases>
|
||||
|
||||
|
||||
[47]** -Seperating Axis Theorem, part 2:
|
||||
-we don't have to test _all_ directions; if there is a seperating axis, then it must be perpendicular to an edge of one of the shapes
|
||||
-so, instead of testing all possible directions to find a seperating axis,
|
||||
we only test those directions which are perpendicular to the edges of our polygons
|
||||
<diagram: as before, but point out/focus on normal directions>
|
||||
|
||||
-there's a proof for the SAT, but that's (thankfully) outside the scope of this lecture
|
||||
-we didn't invent this method, we just noticed that other game programmers were using it
|
||||
|
||||
|
||||
[48]** -the Method of Seperating Axes is a method of collision detection which is based on SAT:
|
||||
-given two shapes, determine all the potentially seperating axes for those shapes
|
||||
-i.e determine the directions which are perpendicular to each edges of each polygon
|
||||
-test each potentially seperating axis until we find an axis along which the objects are seperated
|
||||
-if we've tested all potentially seperating axes and found none that are seperating the objects,
|
||||
the objects are colliding
|
||||
|
||||
-instead of a single, complicated 2D test (based on minimum distance or whatever), we perform a series of simple 1D tests
|
||||
-each test is along a different direction, or "axis"
|
||||
-each test boils down to a few lines of very simple (and fast) math
|
||||
-we'll get to the math shortly
|
||||
|
||||
-the strength of this method is the "early out"
|
||||
-we don't need to test every potentially seperating axis; as soon as we find an axis which seperates the two shapes,
|
||||
we know (thanks to the SAT) they can't be colliding and we can skip the rest of the axes
|
||||
-this means when two objects aren't colliding, we do less work than when they are
|
||||
-in a typical game, any two objects picked at random are likely NOT colliding,
|
||||
so optimising the not-colliding case makes sense and really speeds things up
|
||||
|
||||
|
||||
|
||||
[49]** -before we get into actual code, let's review some basic vector algebra/geometry
|
||||
-basic vector math: nothing to be afraid of
|
||||
|
||||
[50]** -vectors (difference of two points)
|
||||
|
||||
[51]** -unit vectors/direction
|
||||
-unit vectors: vectors whose length is 1
|
||||
-very useful to use these to represent directions, INSTEAD of angles/radians/etc.
|
||||
-they've got some useful properties which we'll see in a moment
|
||||
-formula/code:
|
||||
-basically, you divide x and y components by the length of the vector
|
||||
-null (0-length) vectors don't work
|
||||
-when you multiple a unit vector by a scalar X, the result is a vector which points in the same
|
||||
direction as the unit vector, but which is X units long
|
||||
-in this presentation, whenever you hear "axis" (and/or "direction"), this means normalized unit vector
|
||||
-the process of taking a vector and scaling it until it's unit-length is called "normalization"
|
||||
-the vector has been normalized
|
||||
-NOT to be confused with the following
|
||||
|
||||
|
||||
[52]** -normal vectors (NOT to be confused with normalized vectors! althouth.. normal vectors are often normalized..)
|
||||
-perpendicular to a vector
|
||||
-formula/code: it's so simple it's weird that the results are meaningful/useful
|
||||
-each vector has two of these, LH and RH
|
||||
|
||||
[53]** -by convention, polygon edges are arranged in CCW order
|
||||
-this means that each edge's RHnorm points "out" of the polygon edge
|
||||
-these are of special importance to us: the RHnorms of each edge of a polygon _are_ the potentially seperating axes we must test
|
||||
|
||||
|
||||
[54]** -dotproduct
|
||||
-in highschool you may have learnt a definition of dotprod involving cosine:
|
||||
-AdotB = |A|*|B|*cos(angle between A and B)
|
||||
-this is irrelevant
|
||||
-dotprod is a measure of the relative directions of two vectors
|
||||
-formula/code: as with normal vectors, it's so simple it's weird that the results are meaningful/useful
|
||||
-the important thing to note is that:
|
||||
-when two vectors point in the same direction, their dp is at maximum value
|
||||
-then they point in opposite directions, their dp is at minimum value
|
||||
-when they're perpendicular to each other, their dp is 0
|
||||
|
||||
[55]** -if vector A is unit length and vector B isn't, the min/max values of their dp are -/+ the length of B
|
||||
-the value of the dp is no longer just some value, it's now "meaningful":
|
||||
-it's the _length_ of vector B when "measured along" the direction described by vector A
|
||||
-"measured along, viewed along, the length of the image of B on A", etc.
|
||||
-this is important for projection
|
||||
|
||||
|
||||
[56]** -vector projection
|
||||
-just one multiplication step added onto the end of a dotprod
|
||||
-as we just learnt, when vector A is unit length, and vector B isn't,
|
||||
AdotB gives you the length of the "image" of B, when measured along A
|
||||
|
||||
-we can make a vector of length AdotB, which is parallel to A
|
||||
-just multiply A (unit vector) by AdotB
|
||||
-that vector is called the projection of B onto A
|
||||
-you can think of it as "B when viewed/measured along the line containing A"
|
||||
-mapping 2D to 1D
|
||||
|
||||
[57]** -this is the core of our method: projecting shapes onto each potentially seperating axis
|
||||
-if we only care about the length of the projected vector (i.e the dotproduct), we can use the dotproduct itself
|
||||
-this is also what we use for friction/bounce
|
||||
-as we saw earlier, you decompose object velocity into two perp. components
|
||||
by projecting them onto the surface direction
|
||||
|
||||
|
||||
[58]** -the method of seperating axes, revisited
|
||||
-the if(overlap) step is "where all the action is"
|
||||
|
||||
[59]** -example: Box vs. Box
|
||||
-figure out which axes we have to test
|
||||
-aside: normally, testing two quadrilaterals would involve testing 8 potentially seperating axes
|
||||
(4 from each quad)
|
||||
-boxes are a special case which exploit the SAT's rules
|
||||
-we need to test all directions which are perpendicular to the surface of each shape
|
||||
-since, for each box, a single direction is perp. to two surfaces,
|
||||
we can perform a single axis test for each pair of opposite box edges
|
||||
-anyway:
|
||||
-calculate the object-object delta vector (vector from center of one object ot center of the other)
|
||||
-for each potentially seperating axis (show all 4 axes, then show each step below on a single axis):
|
||||
-calculate the projected halfsize of each object (projected = when measured along the axis) (BLUE)
|
||||
-calculate the projected length of the delta vector (projected = when measured along the axis) (GREEN)
|
||||
-calculate the difference between the sum of the halfsizes, and the delta vector
|
||||
-if negative, we've found a seperating axis and we can stop: the shapes don't overlap
|
||||
-if positive, objects overlap along the axis, continue testing (RED)
|
||||
[60]** -if, after testing each axis, we still haven't found a seperating axis, then the objects must be colliding
|
||||
|
||||
|
||||
[61]** -what??!? i'm confused..
|
||||
-why are we using this weird concept of "halfsize"?
|
||||
-don't we still end up with only a yes/no answer? i thought this approach was supposed to give us more info
|
||||
-..wait a minute.
|
||||
-this might seem familiar.
|
||||
|
||||
[62]** -one very useful insight for understanding this approach is that it's a generalisation of circle-circle collision detection
|
||||
(which everyone is probably familiar with)
|
||||
|
||||
[63]** -circle-circle <diagram each step>
|
||||
-calculate the object-object delta vector
|
||||
-for each potentially seperating axis (in this case, there's only one: the axis which passes through both circles' centers)
|
||||
-calculate distance between circles
|
||||
-SAT: calculate the projected size of the delta vector (in this case, this is == the length of the delta vector)
|
||||
-calculate sum of radii
|
||||
-SAT: calculate the projected halfsize of each object (in this case, this is == their radius)
|
||||
-calculate the difference between the sum of halfsizes/radii and the delta vector
|
||||
-if positive, objects overlap along the axis
|
||||
|
||||
[64]** -not only does this help us understand what's going on in our SAT test,
|
||||
it also suggests how to get more than a yes/no answer from the results
|
||||
-do whatever we do in the circle-circle case
|
||||
|
||||
-if the circles ARE overlapping
|
||||
-the penetration direction is parallel to the axis
|
||||
-the amount is equal to the difference we calculated (sum-of-radii minus size-of-delta)
|
||||
|
||||
[65]** -Box-vs-Box revisited
|
||||
-it's the same process as with two circles, except that we have to test more than just a single potentially seperating axis
|
||||
-each axis test is analogous to the circle-circle test, they just involve a bit more math, to project things onto the axis..
|
||||
-in the circle case, the object halfwidths and delta vectors are parallel to the axis
|
||||
-as we saw with dotprods, when you project a vector onto an axis that's parallel to the vector, you get the
|
||||
original vector
|
||||
-like multiplying any number by 1
|
||||
-so, for circles, the values are basically "pre-projected" and we skip the projection math
|
||||
-as soon as we find a seperating axis, we're done -- we know the objects don't overlap
|
||||
|
||||
[66]** -as with circles, if the objects ARE overlapping (i.e we tested all axes and none are seperating the two objects),
|
||||
we can extract collision info "for free" from the per-axis calculations we made
|
||||
-the axis with the smallest "difference" (sum-of-halfsizes minus size-of-delta) is the projection direction
|
||||
-the size of the difference is the projection amount
|
||||
-projection direction + projection amount = projection vector. tada!
|
||||
|
||||
|
||||
[67]** -so, we can use this method to collide any two shapes together, provided that for each shape we can quickly determine:
|
||||
a) which directions are perpendicular to the shape's surface
|
||||
(i.e which axes are potentially seperating directions for that shape)
|
||||
b) how to project the shape onto an axis, i.e
|
||||
-the shape's center (when projected onto an axis)
|
||||
-the shape's size/halfsize (when projected onto an axis)
|
||||
|
||||
|
||||
[68]** -example: projecting a box onto an axis
|
||||
-this is code for an arbitrarily rotated box (in the diagrams, we're just keeping the box still and moving the axis..)
|
||||
-it's the same thing/relativity
|
||||
-an important insight for box projection is:
|
||||
the sum of the projections of the halfwidth vectors = projected halfwidth of box
|
||||
<point to diagram of this>
|
||||
|
||||
[69]** -box representation:
|
||||
-position (of box center)
|
||||
-width/height (along object axes)
|
||||
-unit vector (describing orientation of box; we use the convention that the orientation vector points along local x)
|
||||
|
||||
-see our tutorials for examples of how to project different shapes
|
||||
-linesegs should be obvious
|
||||
|
||||
|
||||
[70]** -step through Box-vs-Box code line-by-line, examining/explaining it
|
||||
|
||||
-point out that you COULD make the code more generic/general
|
||||
-each shape has an array of unit vectors representing potential seperating axes
|
||||
-each shape has a function "Project" which return the object's halfsize when projected onto a given axis
|
||||
-however, if you want to it run as fast as possible, writing special code for each possible combination of objects is the best solution
|
||||
|
||||
|
||||
[71]** -what we left out:
|
||||
[66]** might help when explaining this
|
||||
-tracking minimum penetration axis
|
||||
-store all pen amounts and compare them at the end, or keep a "running minimum"
|
||||
-which direction to project?
|
||||
-projdir is parallel to the axis of minimum projection, but could point in two possible directions
|
||||
-use the sign of the delta<dot>axis
|
||||
|
||||
|
||||
[72]**-what about circles?
|
||||
-we haven't mentioned circles or curved surfaces yet, but they're very useful as collision shapes
|
||||
-the main difference between circles and polygons is the behaviour around corners (vertices)
|
||||
-circles "roll" around corners: the collision direction changes smoothly
|
||||
-polygons slide across them: the collision direction remains the same (surface normal)
|
||||
<demo: use tutorialA demo: circle falling/sliding off the top of a square>**
|
||||
<demo: as above, but use an AABB falling/sliding off the top of a square>**
|
||||
|
||||
-another way to look at this difference is that, unlike polygons,
|
||||
there aren't a finite/discrete number of directions perpendicular to a circle's surface
|
||||
-this is a problem, since our approach relies on knowing which directions might be potentially seperating directions
|
||||
-but: since this SAT approach is a sort of generalization of circle-circle collision,
|
||||
surely we can support circles without too much extra work
|
||||
|
||||
[73]** -we can
|
||||
-instead of reiterating what's presented in our online tutorials, i'll just refer you to them
|
||||
-the basic idea is that for a circle you perform the exact same tests as you would for a box, except you sometimes
|
||||
perform a single additional test at the end
|
||||
-to handle the case where the circle is colliding with a "corner" (vertex) of a shape instead of an edge (lineseg)
|
||||
-you don't always have to perform this test
|
||||
-there is a fast and simple way to determine if you have to perform this additional test
|
||||
-you can use information from the axes you've already tested
|
||||
-if the overlap along the box axes is less than the circle's radius, we know the circle is in a corner region
|
||||
<demonstrate the above values/etc. with the diagram>
|
||||
-if the circle's center is in the horiz/vertical regions, we only test the two box axes
|
||||
-we can tell if the circle is in these regions by looking at the results of these 2 axis tests
|
||||
-if the circle's NOT in these regions, we have to test it vs. the nearest box corner
|
||||
-again, which corner to use is easy since part of the 2 axis tests was determining the box->circle delta vector
|
||||
-this delta vector "points" at the box corner
|
||||
|
||||
[74]** -what about non-convex shapes?
|
||||
-this is important, especially for world/level shapes
|
||||
-just represent them as a union of convex shapes
|
||||
-several (possibly overlapping) convex shapes
|
||||
[75]** -tilebased games use the same idea: decompose the world into small chunks
|
||||
[76]** -a different decomposition is: linesegs
|
||||
-this is leading into the next section into broad-phase
|
||||
|
||||
|
||||
|
||||
[77]** -optimisations:
|
||||
-the key is to precompute as much information as possible, so that you don't have to calculate it at runtime
|
||||
-instead you just lookup your precomputed value
|
||||
-almost every game subscribes to the rule: "the vast majority of things in the world are static"
|
||||
-i.e the game code makes a distinction between (static) world/level geometry, and (dynamic) objects
|
||||
-makings things static is a great optimisation because we can precompute almost everything about each static object
|
||||
-triangles and more complex shapes are harder to project than a box
|
||||
-more lines of code
|
||||
-you _can_ still do it on the fly, it's just slower
|
||||
-calculations for circles and boxes are very fast and simple; they make good candidates for dynamic objects
|
||||
-more complex shapes can be used for static objects, since most of the calculations
|
||||
(calculating surface normals aka axis directions, etc.) can be done beforehand instead of at runtime
|
||||
|
||||
|
||||
|
||||
|
||||
[78]** QUESTIONS about Seperating Axis Thereom / Method of Seperating Axes
|
||||
|
||||
[++TODO: figure out how much time we can spend here, and note it down so that, when presenting, we don't get stuck here for too long]
|
||||
|
||||
|
||||
|
||||
|
||||
[79]**
|
||||
PART 2: broad-phase collision detection, aka spatial database
|
||||
-switching gears...
|
||||
|
||||
[80]** -knowing how to test two objects for collision is only part of the solution to the CD problem
|
||||
[81]** -if there are 10 objects in the world, we'd have to perform 10*10=100 tests
|
||||
-it doesn't matter how fast your object-object test is if you're using it 100 times per frame
|
||||
-for N objects, you have to use N^2 tests
|
||||
|
||||
[82]** -we want to be able to very quickly determine which pairs of objects we should test, i.e which pairs MIGHT be colliding
|
||||
-how to figure out what might be colliding?
|
||||
-all the methods i know of for broad-phase CD use the assumption:
|
||||
if two objects are near each other, then they might be colliding
|
||||
-quickly == approximately; we don't need to know for sure, that's the job of the narrow-phase
|
||||
-once we know which pairs MIGHT be colliding, we can pass them to our narrow-phase collision system
|
||||
to figure out if they actually _are_ colliding, and if so, how.
|
||||
-so, we just need to find a way to quickly determine, given an object or a position in the world,
|
||||
all of the other objects nearby
|
||||
|
||||
-this step is _very_ game specific
|
||||
-there is no "magic bullet"
|
||||
|
||||
[83]** -for small numbers of objects (<=5), using HitTest on each possible pair is often "good enough"
|
||||
-you're still doing N^2 tests, but you're not doing too many of them, and they're not too expensive
|
||||
-it's fast, and it tells you what you need to know (that the objects might be colliding)
|
||||
-if HitTest returns true, you know their bounding boxes are overlapping, and can investigate further using complex tests
|
||||
-however, for the sake of argument, SAT code for AABBs (i.e rectangles) can be just as fast as Hittest
|
||||
-the main cost is the overhead of a function call
|
||||
|
||||
|
||||
[84]** -for larger numbers of objects, you need a more sophisticated way to find all the objects near a given point
|
||||
-this problem has been solved in many different ways:
|
||||
-grid: divide space into uniform boxes
|
||||
[85]** -quadtree: recursively subdivide space into 4 equal regions
|
||||
|
||||
[86]** -they all amount to the same thing: partitioning space into discrete chunks, and building a database using those chunks
|
||||
-the data in the database is the location of objects
|
||||
-hence broad-phase collision systems are often called spatial databases
|
||||
|
||||
-the two most important operations on this database are:
|
||||
a) neighborhood query (quickly determining which objects are near a given position)
|
||||
b) updating an entry in the database (i.e moving an object)
|
||||
-optimising (a) is very simple if you don't care about (b)
|
||||
-games which must support large numbers of moving objects must optimise (b)
|
||||
-it's hard to do both at once; this is why broad-phase is so game-specific
|
||||
|
||||
|
||||
[87]** -grids are best for flash
|
||||
-there are many different ways to use grids, but ALL of them are better suited for flash than non-grid-based methods
|
||||
|
||||
-why only grids?
|
||||
|
||||
-grids allow for constant-time neighborhood queries, and constant-time updating
|
||||
-the constant cost is extremely low
|
||||
-for a neighborhood query, you simply find the cell which contains your query point,
|
||||
then look in the surrounding cells
|
||||
-to update the position of an object in the grid, you just need to find the cells which the object touches,
|
||||
which is fast and simple
|
||||
-more on this later
|
||||
|
||||
-all other spatial database approaches are based on search-trees of some sort
|
||||
-the quadtree i showed you LOOKED sort of like a grid, but the implementation looks
|
||||
like a normal tree data structure
|
||||
-each node has 4 children, etc.
|
||||
-when you look something up from a tree, you have to descend to the leaves, performing tests at each level of the tree
|
||||
-each test takes time
|
||||
-grids only require one test, not one test per level of the heirarchy
|
||||
-likewise, inserting something into a tree is more complex than with a grid
|
||||
|
||||
-if grids are so good, why don't other games use them?
|
||||
-most 2D games _do_ use grids
|
||||
-obviously, any tile-based game is using some sort of grid
|
||||
-even doom used grid-based collision
|
||||
|
||||
[88]** -the problem with grids is that they take up a LOT of space, since the entire world must be covered in cells
|
||||
-a 200x100-tile world means a grid with 20000 cells; if each cell needs 256bytes, that's 5MB
|
||||
-in 3D, this only gets worse: 200x100x100 @ 256bytes = 500MB
|
||||
-this is why trees are used; they require far less memory. instead of covering the entire world,
|
||||
you only cover the non-empty parts of the world
|
||||
-the tradeoff is that trees are slower and more complex to query and update
|
||||
|
||||
[89]** -in flash, in 2D, you can afford the extra memory needed by a grid, but you _can't_ afford the extra processing time required by trees
|
||||
|
||||
|
||||
[90]** -all grid operations involve a couple math ops
|
||||
-you can't get any faster than that
|
||||
|
||||
[91]** -using a grid for object-vs-object tests
|
||||
-i'll just provide an outline of the process
|
||||
-see our online tutorials for implementation details and source code
|
||||
|
||||
[92]** -a grid is just an abstract data structure; there are many differnet ways to actually use the structure.
|
||||
-two popular ways are "regular" and "loose" grids
|
||||
<explain the following in english while using diagram to illustrate>
|
||||
|
||||
-regular grid:
|
||||
-every object knows which grid cell(s) it touches
|
||||
-every grid cell knows which object(s) are touching it
|
||||
<refer to diagram>
|
||||
each blue cell must be tested for collision, and each blue cell must be updated when objects move
|
||||
|
||||
-loose grid:
|
||||
-every object knows which grid cell contains it's center
|
||||
-every cell knows which object(s) it contains
|
||||
<refer to diagram>
|
||||
each red cell must be tested for collision, and each blue cell must be updated when objects move
|
||||
|
||||
-regular vs. loose:
|
||||
-less tests vs less time to update moving objects
|
||||
-can handle any sized shape vs shapes must fit in a cell
|
||||
|
||||
|
||||
|
||||
[93]** -using a grid for object-vs-world
|
||||
-as mentioned earlier, most games divide objects into "static" and "dynamic" groups
|
||||
-you CAN simply use the grid to collide dynamic vs. static objects exactly as you
|
||||
would for dynamic vs. dynamic objects (as we just saw)
|
||||
-however, if you know that most of the game world will consist of static shapes,
|
||||
you might want to create a special system for colliding these static shapes against dynamic objects
|
||||
|
||||
|
||||
[94]** -there isn't time to explore all of the possible ways to use a grid for object-vs-world tests
|
||||
-i'll breifly cover 2 approaches
|
||||
-tilebased and geometry-based
|
||||
|
||||
-tilebased collision:
|
||||
-each grid cell stores a tile shape
|
||||
-each moving object collides against all other moving objects and tiles in it's neighborhood
|
||||
-again, our online tutorials cover this topic very well (i'd rather not just repeat info that's already available)
|
||||
-tilebased systems SEEM like a good choice (simple and fast)
|
||||
-in practise they're quite hard to get good behaviour out of
|
||||
-tilebased collision is usually rule-based instead of math-based;
|
||||
rule-based works well for simple dynamic models, but when you start needing smooth
|
||||
physics-based object movement, rule-based collision simply doesn't perform well
|
||||
-you end up doing lots of extra work to get things behaving well
|
||||
-doing lots of extra work defeates the purpose of using a tilebased world in the first place, which was speed and simplicity
|
||||
|
||||
-a different grid-based approach is geometry/lineseg based
|
||||
-the world is made out of polygons
|
||||
-convex or concave, it doesn't matter
|
||||
-as a preprocess, before runtime, you decompose your polygons into their component linesegs
|
||||
-insert each lineseg into a grid
|
||||
-determining which cells to insert a lineseg into can be done in several ways
|
||||
-since it's a preprocess it doesn't really matter how slow this code is
|
||||
-you can simply try lineseg-vs-AABB test for all cells touching the lineseg's bounding box
|
||||
-or you can use raycast code (which we'll touch on soon)
|
||||
-at runtime, object-vs-world collision involves one or two object-vs-lineseg tests
|
||||
-linesegs are the simplest and fastest shapes to collide against
|
||||
-they have only a single potentially seperating axis
|
||||
-performing several object-vs-lineseg tests is MUCH faster than performing
|
||||
several object-vs-tileshape tests
|
||||
-this system can support the exact same levels and shapes as a tilebased system
|
||||
-but it's far simpler
|
||||
-instead of having many different possible tile-shapes to collide against, you have just one shape: lineseg
|
||||
-it's also a lot faster
|
||||
-testing vs. linesegs is faster than vs. timeshapes
|
||||
|
||||
|
||||
|
||||
[95]** -another great advantage that grids have over other spatial databases is: raycasting is very easy
|
||||
-rays are lines with one endpoint
|
||||
-they're used to model fast-moving bullets in many games (doom, quake)
|
||||
-they're also very useful for line-of-sight testing (AI uses these to determine what each enemy can "see")
|
||||
|
||||
[96]** -a very efficient and simple to understand raycasting algorithm is presented in this paper
|
||||
-it's very simple, and very fast
|
||||
-yet again, please see our online tutorials for implementation details
|
||||
|
||||
|
||||
|
||||
[97]**
|
||||
PART 3: misc/conclusion
|
||||
|
||||
-summary:
|
||||
-collision detection is a powerful tool for making fun games
|
||||
-the MSA is a useful tool for narrow-phase collision detection
|
||||
-a uniform grid is a useful tool for broad-phase collision detection
|
||||
|
||||
-QUESTIONS?
|
||||
|
||||
|
||||
|
||||
|
||||
|
BIN
todo/phaser clean up/fitc/FITC_beyondHittest07.swf
Normal file
BIN
todo/phaser clean up/fitc/FITC_beyondHittest07.swf
Normal file
Binary file not shown.
BIN
todo/phaser clean up/fitc/media/N_tutorial_diagrams05.swf
Normal file
BIN
todo/phaser clean up/fitc/media/N_tutorial_diagrams05.swf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
todo/phaser clean up/fitc/media/N_tutorial_diagrams05_vector.swf
Normal file
BIN
todo/phaser clean up/fitc/media/N_tutorial_diagrams05_vector.swf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
todo/phaser space paint s.png
Normal file
BIN
todo/phaser space paint s.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 344 KiB |
46
todo/phaser tests/camera fx/fade.js
Normal file
46
todo/phaser tests/camera fx/fade.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../build/phaser-fx.d.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.loader.addImageFile('background', 'assets/pics/large-color-wheel.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
var car;
|
||||
var fade;
|
||||
function create() {
|
||||
myGame.add.sprite(0, 0, 'background');
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
// Add our effect to the camera
|
||||
fade = myGame.camera.fx.add(Phaser.FX.Camera.Fade);
|
||||
}
|
||||
function update() {
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
car.angularVelocity = -200;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
car.velocity.copyFrom(myGame.motion.velocityFromAngle(car.angle, 300));
|
||||
}
|
||||
// Fade when the car hits the edges, a different colour per edge
|
||||
if(car.x < 0) {
|
||||
fade.start(0x330066, 3);
|
||||
car.x = 0;
|
||||
} else if(car.x > myGame.world.width) {
|
||||
fade.start(0x000066, 3);
|
||||
car.x = myGame.world.width - car.width;
|
||||
}
|
||||
if(car.y < 0) {
|
||||
fade.start(0xffffff, 4);
|
||||
car.y = 0;
|
||||
} else if(car.y > myGame.world.height) {
|
||||
fade.start(0x000000, 3);
|
||||
car.y = myGame.world.height - car.height;
|
||||
}
|
||||
}
|
||||
})();
|
77
todo/phaser tests/camera fx/fade.ts
Normal file
77
todo/phaser tests/camera fx/fade.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../build/phaser-fx.d.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
myGame.loader.addImageFile('background', 'assets/pics/large-color-wheel.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
var car: Phaser.Sprite;
|
||||
var fade: Phaser.FX.Camera.Fade;
|
||||
|
||||
function create() {
|
||||
|
||||
myGame.add.sprite(0, 0, 'background');
|
||||
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
|
||||
// Add our effect to the camera
|
||||
fade = <Phaser.FX.Camera.Fade> myGame.camera.fx.add(Phaser.FX.Camera.Fade);
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
car.angularVelocity = -200;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
car.velocity.copyFrom(myGame.motion.velocityFromAngle(car.angle, 300));
|
||||
}
|
||||
|
||||
// Fade when the car hits the edges, a different colour per edge
|
||||
|
||||
if (car.x < 0)
|
||||
{
|
||||
fade.start(0x330066, 3);
|
||||
car.x = 0;
|
||||
}
|
||||
else if (car.x > myGame.world.width)
|
||||
{
|
||||
fade.start(0x000066, 3);
|
||||
car.x = myGame.world.width - car.width;
|
||||
}
|
||||
|
||||
if (car.y < 0)
|
||||
{
|
||||
fade.start(0xffffff, 4);
|
||||
car.y = 0;
|
||||
}
|
||||
else if (car.y > myGame.world.height)
|
||||
{
|
||||
fade.start(0x000000, 3);
|
||||
car.y = myGame.world.height - car.height;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
46
todo/phaser tests/camera fx/flash.js
Normal file
46
todo/phaser tests/camera fx/flash.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../build/phaser-fx.d.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.loader.addImageFile('background', 'assets/pics/large-color-wheel.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
var car;
|
||||
var flash;
|
||||
function create() {
|
||||
myGame.add.sprite(0, 0, 'background');
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
// Add our effect to the camera
|
||||
flash = myGame.camera.fx.add(Phaser.FX.Camera.Flash);
|
||||
}
|
||||
function update() {
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
car.angularVelocity = -200;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
car.velocity.copyFrom(myGame.motion.velocityFromAngle(car.angle, 300));
|
||||
}
|
||||
// Flash when the car hits the edges, a different colour per edge
|
||||
if(car.x < 0) {
|
||||
flash.start(0xffffff, 1);
|
||||
car.x = 0;
|
||||
} else if(car.x > myGame.world.width) {
|
||||
flash.start(0xff0000, 2);
|
||||
car.x = myGame.world.width - car.width;
|
||||
}
|
||||
if(car.y < 0) {
|
||||
flash.start(0xffff00, 2);
|
||||
car.y = 0;
|
||||
} else if(car.y > myGame.world.height) {
|
||||
flash.start(0xff00ff, 3);
|
||||
car.y = myGame.world.height - car.height;
|
||||
}
|
||||
}
|
||||
})();
|
77
todo/phaser tests/camera fx/flash.ts
Normal file
77
todo/phaser tests/camera fx/flash.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../build/phaser-fx.d.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
myGame.loader.addImageFile('background', 'assets/pics/large-color-wheel.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
var car: Phaser.Sprite;
|
||||
var flash: Phaser.FX.Camera.Flash;
|
||||
|
||||
function create() {
|
||||
|
||||
myGame.add.sprite(0, 0, 'background');
|
||||
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
|
||||
// Add our effect to the camera
|
||||
flash = <Phaser.FX.Camera.Flash> myGame.camera.fx.add(Phaser.FX.Camera.Flash);
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
car.angularVelocity = -200;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
car.velocity.copyFrom(myGame.motion.velocityFromAngle(car.angle, 300));
|
||||
}
|
||||
|
||||
// Flash when the car hits the edges, a different colour per edge
|
||||
|
||||
if (car.x < 0)
|
||||
{
|
||||
flash.start(0xffffff, 1);
|
||||
car.x = 0;
|
||||
}
|
||||
else if (car.x > myGame.world.width)
|
||||
{
|
||||
flash.start(0xff0000, 2);
|
||||
car.x = myGame.world.width - car.width;
|
||||
}
|
||||
|
||||
if (car.y < 0)
|
||||
{
|
||||
flash.start(0xffff00, 2);
|
||||
car.y = 0;
|
||||
}
|
||||
else if (car.y > myGame.world.height)
|
||||
{
|
||||
flash.start(0xff00ff, 3);
|
||||
car.y = myGame.world.height - car.height;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
41
todo/phaser tests/camera fx/mirror.js
Normal file
41
todo/phaser tests/camera fx/mirror.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../build/phaser-fx.d.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
// Just set the world to be the size of the image we're loading in
|
||||
myGame.world.setSize(1216, 896);
|
||||
myGame.loader.addImageFile('backdrop', 'assets/pics/ninja-masters2.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
var mirror;
|
||||
function create() {
|
||||
// What we need is a camera 800x400 pixels in size as the mirror effect will be 200px tall and sit below it.
|
||||
// So we resize our default camera to 400px
|
||||
myGame.camera.height = 400;
|
||||
// Because it's our default camera we need to tell it to disable clipping, otherwise we'll never see the mirror effect render.
|
||||
myGame.camera.disableClipping = true;
|
||||
// Add our effect to the camera
|
||||
mirror = myGame.camera.fx.add(Phaser.FX.Camera.Mirror);
|
||||
// The first 2 parameters are the x and y coordinates of where to display the effect. They are in STAGE coordinates, not World.
|
||||
// The next is a Quad making up the rectangular region of the Camera that we'll create the effect from (in this case the whole camera).
|
||||
// Finally we set the fill color that is put over the top of the mirror effect.
|
||||
mirror.start(0, 400, new Phaser.Quad(0, 0, 800, 400), 'rgba(0, 0, 100, 0.7)');
|
||||
// Experiment with variations on these to see the different mirror effects that can be achieved.
|
||||
//mirror.flipX = true;
|
||||
//mirror.flipY = true;
|
||||
myGame.add.sprite(0, 0, 'backdrop');
|
||||
}
|
||||
function update() {
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
myGame.camera.scroll.x -= 4;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
myGame.camera.scroll.x += 4;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
myGame.camera.scroll.y -= 4;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
|
||||
myGame.camera.scroll.y += 4;
|
||||
}
|
||||
}
|
||||
})();
|
68
todo/phaser tests/camera fx/mirror.ts
Normal file
68
todo/phaser tests/camera fx/mirror.ts
Normal file
|
@ -0,0 +1,68 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../build/phaser-fx.d.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
// Just set the world to be the size of the image we're loading in
|
||||
myGame.world.setSize(1216, 896);
|
||||
|
||||
myGame.loader.addImageFile('backdrop', 'assets/pics/ninja-masters2.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
var mirror: Phaser.FX.Camera.Mirror;
|
||||
|
||||
function create() {
|
||||
|
||||
// What we need is a camera 800x400 pixels in size as the mirror effect will be 200px tall and sit below it.
|
||||
// So we resize our default camera to 400px
|
||||
myGame.camera.height = 400;
|
||||
|
||||
// Because it's our default camera we need to tell it to disable clipping, otherwise we'll never see the mirror effect render.
|
||||
myGame.camera.disableClipping = true;
|
||||
|
||||
// Add our effect to the camera
|
||||
mirror = <Phaser.FX.Camera.Mirror> myGame.camera.fx.add(Phaser.FX.Camera.Mirror);
|
||||
|
||||
// The first 2 parameters are the x and y coordinates of where to display the effect. They are in STAGE coordinates, not World.
|
||||
// The next is a Quad making up the rectangular region of the Camera that we'll create the effect from (in this case the whole camera).
|
||||
// Finally we set the fill color that is put over the top of the mirror effect.
|
||||
mirror.start(0, 400, new Phaser.Quad(0, 0, 800, 400), 'rgba(0, 0, 100, 0.7)');
|
||||
|
||||
// Experiment with variations on these to see the different mirror effects that can be achieved.
|
||||
//mirror.flipX = true;
|
||||
//mirror.flipY = true;
|
||||
|
||||
myGame.add.sprite(0, 0, 'backdrop');
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
myGame.camera.scroll.x -= 4;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
myGame.camera.scroll.x += 4;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
myGame.camera.scroll.y -= 4;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
|
||||
{
|
||||
myGame.camera.scroll.y += 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
32
todo/phaser tests/camera fx/scanlines.js
Normal file
32
todo/phaser tests/camera fx/scanlines.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../build/phaser-fx.d.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.world.setSize(1216, 896);
|
||||
myGame.loader.addImageFile('backdrop', 'assets/pics/ninja-masters2.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
var scanlines;
|
||||
function create() {
|
||||
// Add our effect to the camera
|
||||
scanlines = myGame.camera.fx.add(Phaser.FX.Camera.Scanlines);
|
||||
// We'll have the scanlines spaced out every 2 pixels
|
||||
scanlines.spacing = 2;
|
||||
// This is the color the lines will be drawn in
|
||||
scanlines.color = 'rgba(0, 0, 0, 0.8)';
|
||||
myGame.add.sprite(0, 0, 'backdrop');
|
||||
}
|
||||
function update() {
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
myGame.camera.scroll.x -= 4;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
myGame.camera.scroll.x += 4;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
myGame.camera.scroll.y -= 4;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
|
||||
myGame.camera.scroll.y += 4;
|
||||
}
|
||||
}
|
||||
})();
|
57
todo/phaser tests/camera fx/scanlines.ts
Normal file
57
todo/phaser tests/camera fx/scanlines.ts
Normal file
|
@ -0,0 +1,57 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../build/phaser-fx.d.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
myGame.world.setSize(1216, 896);
|
||||
|
||||
myGame.loader.addImageFile('backdrop', 'assets/pics/ninja-masters2.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
var scanlines: Phaser.FX.Camera.Scanlines;
|
||||
|
||||
function create() {
|
||||
|
||||
// Add our effect to the camera
|
||||
scanlines = <Phaser.FX.Camera.Scanlines> myGame.camera.fx.add(Phaser.FX.Camera.Scanlines);
|
||||
|
||||
// We'll have the scanlines spaced out every 2 pixels
|
||||
scanlines.spacing = 2;
|
||||
|
||||
// This is the color the lines will be drawn in
|
||||
scanlines.color = 'rgba(0, 0, 0, 0.8)';
|
||||
|
||||
myGame.add.sprite(0, 0, 'backdrop');
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
myGame.camera.scroll.x -= 4;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
myGame.camera.scroll.x += 4;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
myGame.camera.scroll.y -= 4;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
|
||||
{
|
||||
myGame.camera.scroll.y += 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
50
todo/phaser tests/camera fx/shake.js
Normal file
50
todo/phaser tests/camera fx/shake.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../build/phaser-fx.d.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.loader.addImageFile('background', 'assets/pics/remember-me.jpg');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
var car;
|
||||
var shake;
|
||||
function create() {
|
||||
myGame.add.sprite(0, 0, 'background');
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
// Add our effect to the camera
|
||||
shake = myGame.camera.fx.add(Phaser.FX.Camera.Shake);
|
||||
myGame.onRenderCallback = render;
|
||||
}
|
||||
function update() {
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
car.angularVelocity = -200;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
car.velocity.copyFrom(myGame.motion.velocityFromAngle(car.angle, 300));
|
||||
}
|
||||
// Shake the camera when the car hits the edges, a different intensity per edge
|
||||
if(car.x < 0) {
|
||||
shake.start();
|
||||
car.x = 0;
|
||||
} else if(car.x > myGame.world.width) {
|
||||
shake.start(0.02);
|
||||
car.x = myGame.world.width - car.width;
|
||||
}
|
||||
if(car.y < 0) {
|
||||
shake.start(0.07, 1);
|
||||
car.y = 0;
|
||||
} else if(car.y > myGame.world.height) {
|
||||
shake.start(0.1);
|
||||
car.y = myGame.world.height - car.height;
|
||||
}
|
||||
}
|
||||
function render() {
|
||||
myGame.camera.renderDebugInfo(32, 32);
|
||||
}
|
||||
})();
|
85
todo/phaser tests/camera fx/shake.ts
Normal file
85
todo/phaser tests/camera fx/shake.ts
Normal file
|
@ -0,0 +1,85 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
/// <reference path="../../build/phaser-fx.d.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
myGame.loader.addImageFile('background', 'assets/pics/remember-me.jpg');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
var car: Phaser.Sprite;
|
||||
var shake: Phaser.FX.Camera.Shake;
|
||||
|
||||
function create() {
|
||||
|
||||
myGame.add.sprite(0, 0, 'background');
|
||||
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
|
||||
// Add our effect to the camera
|
||||
shake = <Phaser.FX.Camera.Shake> myGame.camera.fx.add(Phaser.FX.Camera.Shake);
|
||||
|
||||
myGame.onRenderCallback = render;
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
car.angularVelocity = -200;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
car.velocity.copyFrom(myGame.motion.velocityFromAngle(car.angle, 300));
|
||||
}
|
||||
|
||||
// Shake the camera when the car hits the edges, a different intensity per edge
|
||||
|
||||
if (car.x < 0)
|
||||
{
|
||||
shake.start();
|
||||
car.x = 0;
|
||||
}
|
||||
else if (car.x > myGame.world.width)
|
||||
{
|
||||
shake.start(0.02);
|
||||
car.x = myGame.world.width - car.width;
|
||||
}
|
||||
|
||||
if (car.y < 0)
|
||||
{
|
||||
shake.start(0.07, 1);
|
||||
car.y = 0;
|
||||
}
|
||||
else if (car.y > myGame.world.height)
|
||||
{
|
||||
shake.start(0.1);
|
||||
car.y = myGame.world.height - car.height;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function render() {
|
||||
|
||||
myGame.camera.renderDebugInfo(32, 32);
|
||||
|
||||
}
|
||||
|
||||
})();
|
38
todo/phaser tests/cameras/camera alpha.js
Normal file
38
todo/phaser tests/cameras/camera alpha.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.world.setSize(2240, 2240);
|
||||
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
var car;
|
||||
var miniCam;
|
||||
function create() {
|
||||
myGame.add.sprite(0, 0, 'grid');
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
myGame.camera.follow(car, Phaser.Camera.STYLE_TOPDOWN);
|
||||
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
miniCam = myGame.add.camera(0, 0, 300, 300);
|
||||
miniCam.follow(car, Phaser.Camera.STYLE_TOPDOWN_TIGHT);
|
||||
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
miniCam.showBorder = true;
|
||||
miniCam.alpha = 0.7;
|
||||
}
|
||||
function update() {
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
car.angularAcceleration = 0;
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
car.angularVelocity = -200;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
|
||||
car.velocity.copyFrom(motion);
|
||||
}
|
||||
}
|
||||
})();
|
63
todo/phaser tests/cameras/camera alpha.ts
Normal file
63
todo/phaser tests/cameras/camera alpha.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
myGame.world.setSize(2240, 2240);
|
||||
|
||||
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
var car: Phaser.Sprite;
|
||||
var miniCam: Phaser.Camera;
|
||||
|
||||
function create() {
|
||||
|
||||
myGame.add.sprite(0, 0, 'grid');
|
||||
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
|
||||
myGame.camera.follow(car, Phaser.Camera.STYLE_TOPDOWN);
|
||||
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
|
||||
miniCam = myGame.add.camera(0, 0, 300, 300);
|
||||
miniCam.follow(car, Phaser.Camera.STYLE_TOPDOWN_TIGHT);
|
||||
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
miniCam.showBorder = true;
|
||||
miniCam.alpha = 0.7;
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
car.angularAcceleration = 0;
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
car.angularVelocity = -200;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
|
||||
|
||||
car.velocity.copyFrom(motion);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
33
todo/phaser tests/cameras/camera bounds.js
Normal file
33
todo/phaser tests/cameras/camera bounds.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.world.setSize(1920, 1200);
|
||||
myGame.camera.setBounds(0, 0, 1920, 1200);
|
||||
myGame.loader.addImageFile('backdrop', 'assets/pics/remember-me.jpg');
|
||||
myGame.loader.addImageFile('melon', 'assets/sprites/melon.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
function create() {
|
||||
myGame.add.sprite(0, 0, 'backdrop');
|
||||
for(var i = 0; i < 100; i++) {
|
||||
myGame.add.sprite(Math.random() * myGame.world.width, Math.random() * myGame.world.height, 'melon');
|
||||
}
|
||||
myGame.onRenderCallback = render;
|
||||
}
|
||||
function update() {
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
myGame.camera.scroll.x -= 4;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
myGame.camera.scroll.x += 4;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
myGame.camera.scroll.y -= 4;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
|
||||
myGame.camera.scroll.y += 4;
|
||||
}
|
||||
}
|
||||
function render() {
|
||||
myGame.camera.renderDebugInfo(32, 32);
|
||||
}
|
||||
})();
|
60
todo/phaser tests/cameras/camera bounds.ts
Normal file
60
todo/phaser tests/cameras/camera bounds.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
myGame.world.setSize(1920, 1200);
|
||||
myGame.camera.setBounds(0, 0, 1920, 1200);
|
||||
|
||||
myGame.loader.addImageFile('backdrop', 'assets/pics/remember-me.jpg');
|
||||
myGame.loader.addImageFile('melon', 'assets/sprites/melon.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
function create() {
|
||||
|
||||
myGame.add.sprite(0, 0, 'backdrop');
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
myGame.add.sprite(Math.random() * myGame.world.width, Math.random() * myGame.world.height, 'melon');
|
||||
}
|
||||
|
||||
myGame.onRenderCallback = render;
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
myGame.camera.scroll.x -= 4;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
myGame.camera.scroll.x += 4;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
myGame.camera.scroll.y -= 4;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
|
||||
{
|
||||
myGame.camera.scroll.y += 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function render() {
|
||||
|
||||
myGame.camera.renderDebugInfo(32, 32);
|
||||
|
||||
}
|
||||
|
||||
})();
|
40
todo/phaser tests/cameras/camera position.js
Normal file
40
todo/phaser tests/cameras/camera position.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.world.setSize(3000, 3000);
|
||||
myGame.loader.addImageFile('melon', 'assets/sprites/melon.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
var cam2;
|
||||
function create() {
|
||||
for(var i = 0; i < 1000; i++) {
|
||||
myGame.add.sprite(Math.random() * 3000, Math.random() * 3000, 'melon');
|
||||
}
|
||||
myGame.camera.setPosition(16, 80);
|
||||
myGame.camera.setSize(320, 320);
|
||||
myGame.camera.showBorder = true;
|
||||
myGame.camera.borderColor = 'rgb(255,0,0)';
|
||||
cam2 = myGame.add.camera(380, 100, 400, 400);
|
||||
cam2.showBorder = true;
|
||||
cam2.borderColor = 'rgb(255,255,0)';
|
||||
}
|
||||
function update() {
|
||||
myGame.camera.renderDebugInfo(16, 16);
|
||||
cam2.renderDebugInfo(200, 16);
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
myGame.camera.x -= 4;
|
||||
cam2.x -= 2;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
myGame.camera.x += 4;
|
||||
cam2.x += 2;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
myGame.camera.y -= 4;
|
||||
cam2.y -= 2;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
|
||||
myGame.camera.y += 4;
|
||||
cam2.y += 2;
|
||||
}
|
||||
}
|
||||
})();
|
66
todo/phaser tests/cameras/camera position.ts
Normal file
66
todo/phaser tests/cameras/camera position.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
myGame.world.setSize(3000, 3000);
|
||||
|
||||
myGame.loader.addImageFile('melon', 'assets/sprites/melon.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
var cam2: Phaser.Camera;
|
||||
|
||||
function create() {
|
||||
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
myGame.add.sprite(Math.random() * 3000, Math.random() * 3000, 'melon');
|
||||
}
|
||||
|
||||
myGame.camera.setPosition(16, 80);
|
||||
myGame.camera.setSize(320, 320);
|
||||
myGame.camera.showBorder = true;
|
||||
myGame.camera.borderColor = 'rgb(255,0,0)';
|
||||
|
||||
cam2 = myGame.add.camera(380, 100, 400, 400);
|
||||
cam2.showBorder = true;
|
||||
cam2.borderColor = 'rgb(255,255,0)';
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
myGame.camera.renderDebugInfo(16, 16);
|
||||
cam2.renderDebugInfo(200, 16);
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
myGame.camera.x -= 4;
|
||||
cam2.x -= 2;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
myGame.camera.x += 4;
|
||||
cam2.x += 2;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
myGame.camera.y -= 4;
|
||||
cam2.y -= 2;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
|
||||
{
|
||||
myGame.camera.y += 4;
|
||||
cam2.y += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
34
todo/phaser tests/cameras/camera rotation.js
Normal file
34
todo/phaser tests/cameras/camera rotation.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.world.setSize(3000, 3000);
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car.png');
|
||||
myGame.loader.addImageFile('melon', 'assets/sprites/melon.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
function create() {
|
||||
for(var i = 0; i < 1000; i++) {
|
||||
if(Math.random() > 0.5) {
|
||||
myGame.add.sprite(Math.random() * 3000, Math.random() * 3000, 'car');
|
||||
} else {
|
||||
myGame.add.sprite(Math.random() * 3000, Math.random() * 3000, 'melon');
|
||||
}
|
||||
}
|
||||
myGame.camera.setPosition(100, 100);
|
||||
myGame.camera.setSize(320, 320);
|
||||
}
|
||||
function update() {
|
||||
myGame.camera.renderDebugInfo(600, 32);
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
myGame.camera.rotation -= 2;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
myGame.camera.rotation += 2;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
myGame.camera.scroll.y -= 4;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
|
||||
myGame.camera.scroll.y += 4;
|
||||
}
|
||||
}
|
||||
})();
|
61
todo/phaser tests/cameras/camera rotation.ts
Normal file
61
todo/phaser tests/cameras/camera rotation.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
myGame.world.setSize(3000, 3000);
|
||||
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car.png');
|
||||
myGame.loader.addImageFile('melon', 'assets/sprites/melon.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
function create() {
|
||||
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
if (Math.random() > 0.5)
|
||||
{
|
||||
myGame.add.sprite(Math.random() * 3000, Math.random() * 3000, 'car');
|
||||
}
|
||||
else
|
||||
{
|
||||
myGame.add.sprite(Math.random() * 3000, Math.random() * 3000, 'melon');
|
||||
}
|
||||
}
|
||||
|
||||
myGame.camera.setPosition(100, 100);
|
||||
myGame.camera.setSize(320, 320);
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
myGame.camera.renderDebugInfo(600, 32);
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
myGame.camera.rotation -= 2;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
myGame.camera.rotation += 2;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
myGame.camera.scroll.y -= 4;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN))
|
||||
{
|
||||
myGame.camera.scroll.y += 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
45
todo/phaser tests/cameras/camera scale.js
Normal file
45
todo/phaser tests/cameras/camera scale.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.world.setSize(2240, 2240);
|
||||
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
var car;
|
||||
var miniCam;
|
||||
var bigCam;
|
||||
function create() {
|
||||
myGame.add.sprite(0, 0, 'grid');
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
myGame.camera.follow(car);
|
||||
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
|
||||
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
miniCam = myGame.add.camera(600, 32, 200, 200);
|
||||
miniCam.follow(car, Phaser.Camera.STYLE_LOCKON);
|
||||
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
miniCam.showBorder = true;
|
||||
miniCam.scale.setTo(0.5, 0.5);
|
||||
bigCam = myGame.add.camera(32, 32, 200, 200);
|
||||
bigCam.follow(car, Phaser.Camera.STYLE_LOCKON);
|
||||
bigCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
bigCam.showBorder = true;
|
||||
bigCam.scale.setTo(2, 2);
|
||||
}
|
||||
function update() {
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
car.angularAcceleration = 0;
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
car.angularVelocity = -200;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
|
||||
car.velocity.copyFrom(motion);
|
||||
}
|
||||
}
|
||||
})();
|
71
todo/phaser tests/cameras/camera scale.ts
Normal file
71
todo/phaser tests/cameras/camera scale.ts
Normal file
|
@ -0,0 +1,71 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
myGame.world.setSize(2240, 2240);
|
||||
|
||||
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
var car: Phaser.Sprite;
|
||||
var miniCam: Phaser.Camera;
|
||||
var bigCam: Phaser.Camera;
|
||||
|
||||
function create() {
|
||||
|
||||
myGame.add.sprite(0, 0, 'grid');
|
||||
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
|
||||
myGame.camera.follow(car);
|
||||
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
|
||||
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
|
||||
miniCam = myGame.add.camera(600, 32, 200, 200);
|
||||
miniCam.follow(car, Phaser.Camera.STYLE_LOCKON);
|
||||
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
miniCam.showBorder = true;
|
||||
miniCam.scale.setTo(0.5, 0.5);
|
||||
|
||||
bigCam = myGame.add.camera(32, 32, 200, 200);
|
||||
bigCam.follow(car, Phaser.Camera.STYLE_LOCKON);
|
||||
bigCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
bigCam.showBorder = true;
|
||||
bigCam.scale.setTo(2, 2);
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
car.angularAcceleration = 0;
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
car.angularVelocity = -200;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
|
||||
|
||||
car.velocity.copyFrom(motion);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
47
todo/phaser tests/cameras/camera shadow.js
Normal file
47
todo/phaser tests/cameras/camera shadow.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.world.setSize(2240, 2240);
|
||||
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
var car;
|
||||
var miniCam;
|
||||
var bigCam;
|
||||
function create() {
|
||||
myGame.add.sprite(0, 0, 'grid');
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
myGame.camera.follow(car);
|
||||
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
|
||||
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
miniCam = myGame.add.camera(600, 32, 200, 200);
|
||||
miniCam.follow(car, Phaser.Camera.STYLE_LOCKON);
|
||||
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
miniCam.showBorder = true;
|
||||
miniCam.scale.setTo(0.5, 0.5);
|
||||
miniCam.showShadow = true;
|
||||
bigCam = myGame.add.camera(32, 32, 200, 200);
|
||||
bigCam.follow(car, Phaser.Camera.STYLE_LOCKON);
|
||||
bigCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
bigCam.showBorder = true;
|
||||
bigCam.scale.setTo(2, 2);
|
||||
bigCam.showShadow = true;
|
||||
}
|
||||
function update() {
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
car.angularAcceleration = 0;
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
car.angularVelocity = -200;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
|
||||
car.velocity.copyFrom(motion);
|
||||
}
|
||||
}
|
||||
})();
|
73
todo/phaser tests/cameras/camera shadow.ts
Normal file
73
todo/phaser tests/cameras/camera shadow.ts
Normal file
|
@ -0,0 +1,73 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
myGame.world.setSize(2240, 2240);
|
||||
|
||||
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
var car: Phaser.Sprite;
|
||||
var miniCam: Phaser.Camera;
|
||||
var bigCam: Phaser.Camera;
|
||||
|
||||
function create() {
|
||||
|
||||
myGame.add.sprite(0, 0, 'grid');
|
||||
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
|
||||
myGame.camera.follow(car);
|
||||
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
|
||||
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
|
||||
miniCam = myGame.add.camera(600, 32, 200, 200);
|
||||
miniCam.follow(car, Phaser.Camera.STYLE_LOCKON);
|
||||
miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
miniCam.showBorder = true;
|
||||
miniCam.scale.setTo(0.5, 0.5);
|
||||
miniCam.showShadow = true;
|
||||
|
||||
bigCam = myGame.add.camera(32, 32, 200, 200);
|
||||
bigCam.follow(car, Phaser.Camera.STYLE_LOCKON);
|
||||
bigCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
bigCam.showBorder = true;
|
||||
bigCam.scale.setTo(2, 2);
|
||||
bigCam.showShadow = true;
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
car.angularAcceleration = 0;
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
car.angularVelocity = -200;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
|
||||
|
||||
car.velocity.copyFrom(motion);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
46
todo/phaser tests/cameras/camera texture.js
Normal file
46
todo/phaser tests/cameras/camera texture.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.world.setSize(2240, 2240);
|
||||
myGame.loader.addImageFile('balls', 'assets/sprites/balls.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
var car;
|
||||
var miniCam;
|
||||
var bigCam;
|
||||
function create() {
|
||||
//myGame.add.sprite('grid', 0, 0);
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
myGame.camera.setTexture('balls');
|
||||
myGame.camera.follow(car);
|
||||
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
|
||||
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
//miniCam = myGame.add.camera(600, 32, 200, 200);
|
||||
//miniCam.follow(car, Camera.STYLE_LOCKON);
|
||||
//miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
//miniCam.showBorder = true;
|
||||
//miniCam.scale.setTo(0.5, 0.5);
|
||||
//bigCam = myGame.add.camera(32, 32, 200, 200);
|
||||
//bigCam.follow(car, Camera.STYLE_LOCKON);
|
||||
//bigCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
//bigCam.showBorder = true;
|
||||
//bigCam.scale.setTo(2, 2);
|
||||
}
|
||||
function update() {
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
car.angularAcceleration = 0;
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
car.angularVelocity = -200;
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
var motion = myGame.motion.velocityFromAngle(car.angle, 300);
|
||||
car.velocity.copyFrom(motion);
|
||||
}
|
||||
}
|
||||
})();
|
72
todo/phaser tests/cameras/camera texture.ts
Normal file
72
todo/phaser tests/cameras/camera texture.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
|
||||
(function () {
|
||||
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
|
||||
function init() {
|
||||
|
||||
myGame.world.setSize(2240, 2240);
|
||||
|
||||
myGame.loader.addImageFile('balls', 'assets/sprites/balls.png');
|
||||
myGame.loader.addImageFile('car', 'assets/sprites/car90.png');
|
||||
|
||||
myGame.loader.load();
|
||||
|
||||
}
|
||||
|
||||
var car: Phaser.Sprite;
|
||||
var miniCam: Phaser.Camera;
|
||||
var bigCam: Phaser.Camera;
|
||||
|
||||
function create() {
|
||||
|
||||
//myGame.add.sprite('grid', 0, 0);
|
||||
|
||||
car = myGame.add.sprite(400, 300, 'car');
|
||||
|
||||
myGame.camera.setTexture('balls');
|
||||
myGame.camera.follow(car);
|
||||
myGame.camera.deadzone = new Phaser.Rectangle(64, 64, myGame.stage.width - 128, myGame.stage.height - 128);
|
||||
myGame.camera.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
|
||||
//miniCam = myGame.add.camera(600, 32, 200, 200);
|
||||
//miniCam.follow(car, Camera.STYLE_LOCKON);
|
||||
//miniCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
//miniCam.showBorder = true;
|
||||
//miniCam.scale.setTo(0.5, 0.5);
|
||||
|
||||
//bigCam = myGame.add.camera(32, 32, 200, 200);
|
||||
//bigCam.follow(car, Camera.STYLE_LOCKON);
|
||||
//bigCam.setBounds(0, 0, myGame.world.width, myGame.world.height);
|
||||
//bigCam.showBorder = true;
|
||||
//bigCam.scale.setTo(2, 2);
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
car.velocity.x = 0;
|
||||
car.velocity.y = 0;
|
||||
car.angularVelocity = 0;
|
||||
car.angularAcceleration = 0;
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT))
|
||||
{
|
||||
car.angularVelocity = -200;
|
||||
}
|
||||
else if (myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
|
||||
{
|
||||
car.angularVelocity = 200;
|
||||
}
|
||||
|
||||
if (myGame.input.keyboard.isDown(Phaser.Keyboard.UP))
|
||||
{
|
||||
var motion:Phaser.Point = myGame.motion.velocityFromAngle(car.angle, 300);
|
||||
|
||||
car.velocity.copyFrom(motion);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
36
todo/phaser tests/cameras/focus on.js
Normal file
36
todo/phaser tests/cameras/focus on.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
/// <reference path="../../Phaser/Game.ts" />
|
||||
(function () {
|
||||
var myGame = new Phaser.Game(this, 'game', 800, 600, init, create, update);
|
||||
function init() {
|
||||
myGame.world.setSize(1920, 1920);
|
||||
myGame.loader.addImageFile('grid', 'assets/tests/debug-grid-1920x1920.png');
|
||||
myGame.loader.addImageFile('melon', 'assets/sprites/melon.png');
|
||||
myGame.loader.addImageFile('carrot', 'assets/sprites/carrot.png');
|
||||
myGame.loader.load();
|
||||
}
|
||||
var melon;
|
||||
function create() {
|
||||
// locked to the camera
|
||||
myGame.add.sprite(0, 0, 'grid');
|
||||
melon = myGame.add.sprite(600, 650, 'melon');
|
||||
melon.scrollFactor.setTo(1.5, 1.5);
|
||||
// scrolls x2 camera speed
|
||||
for(var i = 0; i < 100; i++) {
|
||||
var tempSprite = myGame.add.sprite(Math.random() * myGame.world.width, Math.random() * myGame.world.height, 'carrot');
|
||||
tempSprite.scrollFactor.setTo(2, 2);
|
||||
}
|
||||
}
|
||||
function update() {
|
||||
myGame.camera.renderDebugInfo(32, 32);
|
||||
melon.renderDebugInfo(200, 32);
|
||||
if(myGame.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
|
||||
myGame.camera.focusOnXY(640, 640);
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
|
||||
myGame.camera.focusOnXY(1234, 800);
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.UP)) {
|
||||
myGame.camera.focusOnXY(50, 200);
|
||||
} else if(myGame.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
|
||||
myGame.camera.focusOnXY(1700, 1700);
|
||||
}
|
||||
}
|
||||
})();
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue