2013-04-18 13:16:18 +00:00
|
|
|
/// <reference path="../gameobjects/Sprite.ts" />
|
2013-04-18 14:48:06 +00:00
|
|
|
/// <reference path="../Game.ts" />
|
2013-04-18 13:16:18 +00:00
|
|
|
|
|
|
|
/**
|
2013-04-18 15:49:08 +00:00
|
|
|
* Phaser - Camera
|
|
|
|
*
|
|
|
|
* A Camera is your view into the game world. It has a position, size, scale and rotation and renders only those objects
|
|
|
|
* within its field of view. The game automatically creates a single Stage sized camera on boot, but it can be changed and
|
|
|
|
* additional cameras created via the CameraManager.
|
2013-04-18 13:16:18 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
module Phaser {
|
|
|
|
|
|
|
|
export class Camera {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Instantiates a new camera at the specified location, with the specified size and zoom level.
|
|
|
|
*
|
|
|
|
* @param X X location of the camera's display in pixels. Uses native, 1:1 resolution, ignores zoom.
|
|
|
|
* @param Y Y location of the camera's display in pixels. Uses native, 1:1 resolution, ignores zoom.
|
|
|
|
* @param Width The width of the camera display in pixels.
|
|
|
|
* @param Height The height of the camera display in pixels.
|
|
|
|
* @param Zoom The initial zoom level of the camera. A zoom level of 2 will make all pixels display at 2x resolution.
|
|
|
|
*/
|
|
|
|
constructor(game: Game, id: number, x: number, y: number, width: number, height: number) {
|
|
|
|
|
|
|
|
this._game = game;
|
|
|
|
|
|
|
|
this.ID = id;
|
|
|
|
this._stageX = x;
|
|
|
|
this._stageY = y;
|
|
|
|
|
|
|
|
// The view into the world canvas we wish to render
|
|
|
|
this.worldView = new Rectangle(0, 0, width, height);
|
|
|
|
|
|
|
|
this.checkClip();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private _game: Game;
|
|
|
|
|
|
|
|
private _clip: bool = false;
|
|
|
|
private _stageX: number;
|
|
|
|
private _stageY: number;
|
|
|
|
private _rotation: number = 0;
|
|
|
|
private _target: Sprite = null;
|
|
|
|
private _sx: number = 0;
|
|
|
|
private _sy: number = 0;
|
|
|
|
|
|
|
|
private _fxFlashColor: string;
|
|
|
|
private _fxFlashComplete = null;
|
|
|
|
private _fxFlashDuration: number = 0;
|
|
|
|
private _fxFlashAlpha: number = 0;
|
|
|
|
|
|
|
|
private _fxFadeColor: string;
|
|
|
|
private _fxFadeComplete = null;
|
|
|
|
private _fxFadeDuration: number = 0;
|
|
|
|
private _fxFadeAlpha: number = 0;
|
|
|
|
|
|
|
|
private _fxShakeIntensity: number = 0;
|
|
|
|
private _fxShakeDuration: number = 0;
|
|
|
|
private _fxShakeComplete = null;
|
|
|
|
private _fxShakeOffset: Point = new Point(0, 0);
|
|
|
|
private _fxShakeDirection: number = 0;
|
|
|
|
private _fxShakePrevX: number = 0;
|
|
|
|
private _fxShakePrevY: number = 0;
|
|
|
|
|
|
|
|
public static STYLE_LOCKON: number = 0;
|
|
|
|
public static STYLE_PLATFORMER: number = 1;
|
|
|
|
public static STYLE_TOPDOWN: number = 2;
|
|
|
|
public static STYLE_TOPDOWN_TIGHT: number = 3;
|
|
|
|
|
|
|
|
public static SHAKE_BOTH_AXES: number = 0;
|
|
|
|
public static SHAKE_HORIZONTAL_ONLY: number = 1;
|
|
|
|
public static SHAKE_VERTICAL_ONLY: number = 2;
|
|
|
|
|
|
|
|
public ID: number;
|
|
|
|
public worldView: Rectangle;
|
|
|
|
public totalSpritesRendered: number;
|
|
|
|
public scale: Point = new Point(1, 1);
|
|
|
|
public scroll: Point = new Point(0, 0);
|
|
|
|
public bounds: Rectangle = null;
|
|
|
|
public deadzone: Rectangle = null;
|
|
|
|
|
|
|
|
// Camera Border
|
|
|
|
public showBorder: bool = false;
|
|
|
|
public borderColor: string = 'rgb(255,255,255)';
|
|
|
|
|
|
|
|
// Camera Background Color
|
|
|
|
public opaque: bool = true;
|
|
|
|
private _bgColor: string = 'rgb(0,0,0)';
|
|
|
|
private _bgTexture;
|
|
|
|
private _bgTextureRepeat: string = 'repeat';
|
|
|
|
|
|
|
|
// Camera Shadow
|
|
|
|
public showShadow: bool = false;
|
|
|
|
public shadowColor: string = 'rgb(0,0,0)';
|
|
|
|
public shadowBlur: number = 10;
|
|
|
|
public shadowOffset: Point = new Point(4, 4);
|
|
|
|
|
|
|
|
public visible: bool = true;
|
|
|
|
public alpha: number = 1;
|
|
|
|
|
|
|
|
// The x/y position of the current input event in world coordinates
|
|
|
|
public inputX: number = 0;
|
|
|
|
public inputY: number = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The camera is filled with this color and returns to normal at the given duration.
|
|
|
|
*
|
|
|
|
* @param Color The color you want to use in 0xRRGGBB format, i.e. 0xffffff for white.
|
|
|
|
* @param Duration How long it takes for the flash to fade.
|
|
|
|
* @param OnComplete An optional function you want to run when the flash finishes. Set to null for no callback.
|
|
|
|
* @param Force Force an already running flash effect to reset.
|
|
|
|
*/
|
|
|
|
public flash(color: number = 0xffffff, duration: number = 1, onComplete = null, force: bool = false) {
|
|
|
|
|
|
|
|
if (force === false && this._fxFlashAlpha > 0)
|
|
|
|
{
|
|
|
|
// You can't flash again unless you force it
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (duration <= 0)
|
|
|
|
{
|
|
|
|
duration = 1;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
var red = color >> 16 & 0xFF;
|
|
|
|
var green = color >> 8 & 0xFF;
|
|
|
|
var blue = color & 0xFF;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this._fxFlashColor = 'rgba(' + red + ',' + green + ',' + blue + ',';
|
|
|
|
this._fxFlashDuration = duration;
|
|
|
|
this._fxFlashAlpha = 1;
|
|
|
|
this._fxFlashComplete = onComplete;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
/**
|
|
|
|
* The camera is gradually filled with this color.
|
|
|
|
*
|
|
|
|
* @param Color The color you want to use in 0xRRGGBB format, i.e. 0xffffff for white.
|
|
|
|
* @param Duration How long it takes for the flash to fade.
|
|
|
|
* @param OnComplete An optional function you want to run when the flash finishes. Set to null for no callback.
|
|
|
|
* @param Force Force an already running flash effect to reset.
|
|
|
|
*/
|
|
|
|
public fade(color: number = 0x000000, duration: number = 1, onComplete = null, force: bool = false) {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (force === false && this._fxFadeAlpha > 0)
|
|
|
|
{
|
|
|
|
// You can't fade again unless you force it
|
|
|
|
return;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (duration <= 0)
|
|
|
|
{
|
|
|
|
duration = 1;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
var red = color >> 16 & 0xFF;
|
|
|
|
var green = color >> 8 & 0xFF;
|
|
|
|
var blue = color & 0xFF;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this._fxFadeColor = 'rgba(' + red + ',' + green + ',' + blue + ',';
|
|
|
|
this._fxFadeDuration = duration;
|
|
|
|
this._fxFadeAlpha = 0.01;
|
|
|
|
this._fxFadeComplete = onComplete;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
/**
|
|
|
|
* A simple screen-shake effect.
|
|
|
|
*
|
|
|
|
* @param Intensity Percentage of screen size representing the maximum distance that the screen can move while shaking.
|
|
|
|
* @param Duration The length in seconds that the shaking effect should last.
|
|
|
|
* @param OnComplete A function you want to run when the shake effect finishes.
|
|
|
|
* @param Force Force the effect to reset (default = true, unlike flash() and fade()!).
|
|
|
|
* @param Direction Whether to shake on both axes, just up and down, or just side to side (use class constants SHAKE_BOTH_AXES, SHAKE_VERTICAL_ONLY, or SHAKE_HORIZONTAL_ONLY).
|
|
|
|
*/
|
|
|
|
public shake(intensity: number = 0.05, duration: number = 0.5, onComplete = null, force: bool = true, direction: number = Camera.SHAKE_BOTH_AXES) {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (!force && ((this._fxShakeOffset.x != 0) || (this._fxShakeOffset.y != 0)))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// If a shake is not already running we need to store the offsets here
|
|
|
|
if (this._fxShakeOffset.x == 0 && this._fxShakeOffset.y == 0)
|
|
|
|
{
|
|
|
|
this._fxShakePrevX = this._stageX;
|
|
|
|
this._fxShakePrevY = this._stageY;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this._fxShakeIntensity = intensity;
|
|
|
|
this._fxShakeDuration = duration;
|
|
|
|
this._fxShakeComplete = onComplete;
|
|
|
|
this._fxShakeDirection = direction;
|
|
|
|
this._fxShakeOffset.setTo(0, 0);
|
2013-04-12 16:19:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
/**
|
|
|
|
* Just turns off all the camera effects instantly.
|
|
|
|
*/
|
|
|
|
public stopFX() {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this._fxFlashAlpha = 0;
|
|
|
|
this._fxFadeAlpha = 0;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this._fxShakeDuration !== 0)
|
|
|
|
{
|
|
|
|
this._fxShakeDuration = 0;
|
|
|
|
this._fxShakeOffset.setTo(0, 0);
|
|
|
|
this._stageX = this._fxShakePrevX;
|
|
|
|
this._stageY = this._fxShakePrevY;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public follow(target: Sprite, style?: number = Camera.STYLE_LOCKON) {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this._target = target;
|
|
|
|
var helper: number;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
switch (style)
|
|
|
|
{
|
|
|
|
case Camera.STYLE_PLATFORMER:
|
|
|
|
var w: number = this.width / 8;
|
|
|
|
var h: number = this.height / 3;
|
|
|
|
this.deadzone = new Rectangle((this.width - w) / 2, (this.height - h) / 2 - h * 0.25, w, h);
|
|
|
|
break;
|
|
|
|
case Camera.STYLE_TOPDOWN:
|
|
|
|
helper = Math.max(this.width, this.height) / 4;
|
|
|
|
this.deadzone = new Rectangle((this.width - helper) / 2, (this.height - helper) / 2, helper, helper);
|
|
|
|
break;
|
|
|
|
case Camera.STYLE_TOPDOWN_TIGHT:
|
|
|
|
helper = Math.max(this.width, this.height) / 8;
|
|
|
|
this.deadzone = new Rectangle((this.width - helper) / 2, (this.height - helper) / 2, helper, helper);
|
|
|
|
break;
|
|
|
|
case Camera.STYLE_LOCKON:
|
|
|
|
default:
|
|
|
|
this.deadzone = null;
|
|
|
|
break;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public focusOnXY(x: number, y: number) {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
x += (x > 0) ? 0.0000001 : -0.0000001;
|
|
|
|
y += (y > 0) ? 0.0000001 : -0.0000001;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this.scroll.x = Math.round(x - this.worldView.halfWidth);
|
|
|
|
this.scroll.y = Math.round(y - this.worldView.halfHeight);
|
2013-04-12 16:19:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public focusOn(point: Point) {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
point.x += (point.x > 0) ? 0.0000001 : -0.0000001;
|
|
|
|
point.y += (point.y > 0) ? 0.0000001 : -0.0000001;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this.scroll.x = Math.round(point.x - this.worldView.halfWidth);
|
|
|
|
this.scroll.y = Math.round(point.y - this.worldView.halfHeight);
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
/**
|
|
|
|
* Specify the boundaries of the world or where the camera is allowed to move.
|
|
|
|
*
|
|
|
|
* @param X The smallest X value of your world (usually 0).
|
|
|
|
* @param Y The smallest Y value of your world (usually 0).
|
|
|
|
* @param Width The largest X value of your world (usually the world width).
|
|
|
|
* @param Height The largest Y value of your world (usually the world height).
|
|
|
|
* @param UpdateWorld Whether the global quad-tree's dimensions should be updated to match (default: false).
|
|
|
|
*/
|
|
|
|
public setBounds(X: number = 0, Y: number = 0, Width: number = 0, Height: number = 0, UpdateWorld: bool = false) {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.bounds == null)
|
|
|
|
{
|
|
|
|
this.bounds = new Rectangle();
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this.bounds.setTo(X, Y, Width, Height);
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
//if(UpdateWorld)
|
2013-04-18 14:48:06 +00:00
|
|
|
// G.worldBounds.copyFrom(bounds);
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this.update();
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public update() {
|
|
|
|
|
|
|
|
if (this._target !== null)
|
|
|
|
{
|
|
|
|
if (this.deadzone == null)
|
|
|
|
{
|
|
|
|
this.focusOnXY(this._target.x + this._target.origin.x, this._target.y + this._target.origin.y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var edge: number;
|
|
|
|
var targetX: number = this._target.x + ((this._target.x > 0) ? 0.0000001 : -0.0000001);
|
|
|
|
var targetY: number = this._target.y + ((this._target.y > 0) ? 0.0000001 : -0.0000001);
|
|
|
|
|
|
|
|
edge = targetX - this.deadzone.x;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.scroll.x > edge)
|
|
|
|
{
|
|
|
|
this.scroll.x = edge;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
edge = targetX + this._target.width - this.deadzone.x - this.deadzone.width;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.scroll.x < edge)
|
|
|
|
{
|
|
|
|
this.scroll.x = edge;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
edge = targetY - this.deadzone.y;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.scroll.y > edge)
|
|
|
|
{
|
|
|
|
this.scroll.y = edge;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
edge = targetY + this._target.height - this.deadzone.y - this.deadzone.height;
|
|
|
|
|
|
|
|
if (this.scroll.y < edge)
|
|
|
|
{
|
|
|
|
this.scroll.y = edge;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Make sure we didn't go outside the camera's bounds
|
|
|
|
if (this.bounds !== null)
|
|
|
|
{
|
|
|
|
if (this.scroll.x < this.bounds.left)
|
2013-04-12 16:19:56 +00:00
|
|
|
{
|
2013-04-18 13:16:18 +00:00
|
|
|
this.scroll.x = this.bounds.left;
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.scroll.x > this.bounds.right - this.width)
|
2013-04-12 16:19:56 +00:00
|
|
|
{
|
2013-04-18 13:16:18 +00:00
|
|
|
this.scroll.x = this.bounds.right - this.width;
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.scroll.y < this.bounds.top)
|
|
|
|
{
|
|
|
|
this.scroll.y = this.bounds.top;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.scroll.y > this.bounds.bottom - this.height)
|
2013-04-12 16:19:56 +00:00
|
|
|
{
|
2013-04-18 13:16:18 +00:00
|
|
|
this.scroll.y = this.bounds.bottom - this.height;
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this.worldView.x = this.scroll.x;
|
|
|
|
this.worldView.y = this.scroll.y;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Input values
|
|
|
|
this.inputX = this.worldView.x + this._game.input.x;
|
|
|
|
this.inputY = this.worldView.y + this._game.input.y;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Update the Flash effect
|
|
|
|
if (this._fxFlashAlpha > 0)
|
2013-04-12 16:19:56 +00:00
|
|
|
{
|
2013-04-18 13:16:18 +00:00
|
|
|
this._fxFlashAlpha -= this._game.time.elapsed / this._fxFlashDuration;
|
|
|
|
this._fxFlashAlpha = this._game.math.roundTo(this._fxFlashAlpha, -2);
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this._fxFlashAlpha <= 0)
|
|
|
|
{
|
|
|
|
this._fxFlashAlpha = 0;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this._fxFlashComplete !== null)
|
|
|
|
{
|
|
|
|
this._fxFlashComplete();
|
|
|
|
}
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
2013-04-14 01:31:00 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Update the Fade effect
|
|
|
|
if (this._fxFadeAlpha > 0)
|
2013-04-12 16:19:56 +00:00
|
|
|
{
|
2013-04-18 13:16:18 +00:00
|
|
|
this._fxFadeAlpha += this._game.time.elapsed / this._fxFadeDuration;
|
|
|
|
this._fxFadeAlpha = this._game.math.roundTo(this._fxFadeAlpha, -2);
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this._fxFadeAlpha >= 1)
|
2013-04-12 16:19:56 +00:00
|
|
|
{
|
2013-04-18 13:16:18 +00:00
|
|
|
this._fxFadeAlpha = 1;
|
|
|
|
|
|
|
|
if (this._fxFadeComplete !== null)
|
|
|
|
{
|
|
|
|
this._fxFadeComplete();
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Update the "shake" special effect
|
|
|
|
if (this._fxShakeDuration > 0)
|
2013-04-12 16:19:56 +00:00
|
|
|
{
|
2013-04-18 13:16:18 +00:00
|
|
|
this._fxShakeDuration -= this._game.time.elapsed;
|
|
|
|
this._fxShakeDuration = this._game.math.roundTo(this._fxShakeDuration, -2);
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this._fxShakeDuration <= 0)
|
|
|
|
{
|
|
|
|
this._fxShakeDuration = 0;
|
|
|
|
this._fxShakeOffset.setTo(0, 0);
|
|
|
|
this._stageX = this._fxShakePrevX;
|
|
|
|
this._stageY = this._fxShakePrevY;
|
|
|
|
|
|
|
|
if (this._fxShakeComplete != null)
|
|
|
|
{
|
|
|
|
this._fxShakeComplete();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2013-04-12 16:19:56 +00:00
|
|
|
{
|
2013-04-18 13:16:18 +00:00
|
|
|
if ((this._fxShakeDirection == Camera.SHAKE_BOTH_AXES) || (this._fxShakeDirection == Camera.SHAKE_HORIZONTAL_ONLY))
|
|
|
|
{
|
|
|
|
//this._fxShakeOffset.x = ((this._game.math.random() * this._fxShakeIntensity * this.worldView.width * 2 - this._fxShakeIntensity * this.worldView.width) * this._zoom;
|
|
|
|
this._fxShakeOffset.x = (this._game.math.random() * this._fxShakeIntensity * this.worldView.width * 2 - this._fxShakeIntensity * this.worldView.width);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((this._fxShakeDirection == Camera.SHAKE_BOTH_AXES) || (this._fxShakeDirection == Camera.SHAKE_VERTICAL_ONLY))
|
|
|
|
{
|
|
|
|
//this._fxShakeOffset.y = (this._game.math.random() * this._fxShakeIntensity * this.worldView.height * 2 - this._fxShakeIntensity * this.worldView.height) * this._zoom;
|
|
|
|
this._fxShakeOffset.y = (this._game.math.random() * this._fxShakeIntensity * this.worldView.height * 2 - this._fxShakeIntensity * this.worldView.height);
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
2013-04-18 13:16:18 +00:00
|
|
|
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
2013-04-18 13:16:18 +00:00
|
|
|
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public render() {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.visible === false && this.alpha < 0.1)
|
2013-04-12 16:19:56 +00:00
|
|
|
{
|
2013-04-18 13:16:18 +00:00
|
|
|
return;
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if ((this._fxShakeOffset.x != 0) || (this._fxShakeOffset.y != 0))
|
|
|
|
{
|
|
|
|
//this._stageX = this._fxShakePrevX + (this.worldView.halfWidth * this._zoom) + this._fxShakeOffset.x;
|
|
|
|
//this._stageY = this._fxShakePrevY + (this.worldView.halfHeight * this._zoom) + this._fxShakeOffset.y;
|
|
|
|
this._stageX = this._fxShakePrevX + (this.worldView.halfWidth) + this._fxShakeOffset.x;
|
|
|
|
this._stageY = this._fxShakePrevY + (this.worldView.halfHeight) + this._fxShakeOffset.y;
|
|
|
|
//console.log('shake', this._fxShakeDuration, this._fxShakeIntensity, this._fxShakeOffset.x, this._fxShakeOffset.y);
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
//if (this._rotation !== 0 || this._clip || this.scale.x !== 1 || this.scale.y !== 1)
|
|
|
|
//{
|
|
|
|
//this._game.stage.context.save();
|
|
|
|
//}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// It may be safe/quicker to just save the context every frame regardless
|
|
|
|
this._game.stage.context.save();
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.alpha !== 1)
|
|
|
|
{
|
|
|
|
this._game.stage.context.globalAlpha = this.alpha;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this._sx = this._stageX;
|
|
|
|
this._sy = this._stageY;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Shadow
|
|
|
|
if (this.showShadow)
|
|
|
|
{
|
|
|
|
this._game.stage.context.shadowColor = this.shadowColor;
|
|
|
|
this._game.stage.context.shadowBlur = this.shadowBlur;
|
|
|
|
this._game.stage.context.shadowOffsetX = this.shadowOffset.x;
|
|
|
|
this._game.stage.context.shadowOffsetY = this.shadowOffset.y;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Scale on
|
|
|
|
if (this.scale.x !== 1 || this.scale.y !== 1)
|
|
|
|
{
|
|
|
|
this._game.stage.context.scale(this.scale.x, this.scale.y);
|
|
|
|
this._sx = this._sx / this.scale.x;
|
|
|
|
this._sy = this._sy / this.scale.y;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Rotation - translate to the mid-point of the camera
|
|
|
|
if (this._rotation !== 0)
|
|
|
|
{
|
|
|
|
this._game.stage.context.translate(this._sx + this.worldView.halfWidth, this._sy + this.worldView.halfHeight);
|
|
|
|
this._game.stage.context.rotate(this._rotation * (Math.PI / 180));
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// now shift back to where that should actually render
|
|
|
|
this._game.stage.context.translate(-(this._sx + this.worldView.halfWidth), -(this._sy + this.worldView.halfHeight));
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Background
|
|
|
|
if (this.opaque == true)
|
|
|
|
{
|
|
|
|
if (this._bgTexture)
|
|
|
|
{
|
|
|
|
this._game.stage.context.fillStyle = this._bgTexture;
|
|
|
|
this._game.stage.context.fillRect(this._sx, this._sy, this.worldView.width, this.worldView.height);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this._game.stage.context.fillStyle = this._bgColor;
|
|
|
|
this._game.stage.context.fillRect(this._sx, this._sy, this.worldView.width, this.worldView.height);
|
|
|
|
}
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Shadow off
|
|
|
|
if (this.showShadow)
|
|
|
|
{
|
|
|
|
this._game.stage.context.shadowBlur = 0;
|
|
|
|
this._game.stage.context.shadowOffsetX = 0;
|
|
|
|
this._game.stage.context.shadowOffsetY = 0;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Clip the camera so we don't get sprites appearing outside the edges
|
|
|
|
if (this._clip)
|
|
|
|
{
|
|
|
|
this._game.stage.context.beginPath();
|
|
|
|
this._game.stage.context.rect(this._sx, this._sy, this.worldView.width, this.worldView.height);
|
|
|
|
this._game.stage.context.closePath();
|
|
|
|
this._game.stage.context.clip();
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this._game.world.group.render(this, this._sx, this._sy);
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.showBorder)
|
|
|
|
{
|
|
|
|
this._game.stage.context.strokeStyle = this.borderColor;
|
|
|
|
this._game.stage.context.lineWidth = 1;
|
|
|
|
this._game.stage.context.rect(this._sx, this._sy, this.worldView.width, this.worldView.height);
|
|
|
|
this._game.stage.context.stroke();
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// "Flash" FX
|
|
|
|
if (this._fxFlashAlpha > 0)
|
2013-04-12 16:19:56 +00:00
|
|
|
{
|
2013-04-18 13:16:18 +00:00
|
|
|
this._game.stage.context.fillStyle = this._fxFlashColor + this._fxFlashAlpha + ')';
|
2013-04-12 16:19:56 +00:00
|
|
|
this._game.stage.context.fillRect(this._sx, this._sy, this.worldView.width, this.worldView.height);
|
|
|
|
}
|
2013-04-18 13:16:18 +00:00
|
|
|
|
|
|
|
// "Fade" FX
|
|
|
|
if (this._fxFadeAlpha > 0)
|
2013-04-12 16:19:56 +00:00
|
|
|
{
|
2013-04-18 13:16:18 +00:00
|
|
|
this._game.stage.context.fillStyle = this._fxFadeColor + this._fxFadeAlpha + ')';
|
2013-04-12 16:19:56 +00:00
|
|
|
this._game.stage.context.fillRect(this._sx, this._sy, this.worldView.width, this.worldView.height);
|
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// Scale off
|
|
|
|
if (this.scale.x !== 1 || this.scale.y !== 1)
|
|
|
|
{
|
|
|
|
this._game.stage.context.scale(1, 1);
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this._rotation !== 0 || this._clip)
|
|
|
|
{
|
|
|
|
this._game.stage.context.translate(0, 0);
|
|
|
|
//this._game.stage.context.restore();
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
// maybe just do this every frame regardless?
|
|
|
|
this._game.stage.context.restore();
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.alpha !== 1)
|
|
|
|
{
|
|
|
|
this._game.stage.context.globalAlpha = 1;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public set backgroundColor(color: string) {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this._bgColor = color;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public get backgroundColor(): string {
|
|
|
|
return this._bgColor;
|
2013-04-12 16:19:56 +00:00
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public setTexture(key: string, repeat?: string = 'repeat') {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this._bgTexture = this._game.stage.context.createPattern(this._game.cache.getImage(key), repeat);
|
|
|
|
this._bgTextureRepeat = repeat;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public setPosition(x: number, y: number) {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this._stageX = x;
|
|
|
|
this._stageY = y;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this.checkClip();
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public setSize(width: number, height: number) {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this.worldView.width = width;
|
|
|
|
this.worldView.height = height;
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this.checkClip();
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public renderDebugInfo(x: number, y: number, color?: string = 'rgb(255,255,255)') {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
this._game.stage.context.fillStyle = color;
|
|
|
|
this._game.stage.context.fillText('Camera ID: ' + this.ID + ' (' + this.worldView.width + ' x ' + this.worldView.height + ')', x, y);
|
|
|
|
this._game.stage.context.fillText('X: ' + this._stageX + ' Y: ' + this._stageY + ' Rotation: ' + this._rotation, x, y + 14);
|
|
|
|
this._game.stage.context.fillText('World X: ' + this.scroll.x.toFixed(1) + ' World Y: ' + this.scroll.y.toFixed(1), x, y + 28);
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this.bounds)
|
|
|
|
{
|
|
|
|
this._game.stage.context.fillText('Bounds: ' + this.bounds.width + ' x ' + this.bounds.height, x, y + 56);
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public get x(): number {
|
|
|
|
return this._stageX;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public set x(value: number) {
|
|
|
|
this._stageX = value;
|
|
|
|
this.checkClip();
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public get y(): number {
|
|
|
|
return this._stageY;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public set y(value: number) {
|
|
|
|
this._stageY = value;
|
|
|
|
this.checkClip();
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public get width(): number {
|
|
|
|
return this.worldView.width;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public set width(value: number) {
|
|
|
|
this.worldView.width = value;
|
|
|
|
this.checkClip();
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public get height(): number {
|
|
|
|
return this.worldView.height;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public set height(value: number) {
|
|
|
|
this.worldView.height = value;
|
|
|
|
this.checkClip();
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public get rotation(): number {
|
|
|
|
return this._rotation;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
public set rotation(value: number) {
|
|
|
|
this._rotation = this._game.math.wrap(value, 360, 0);
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
private checkClip() {
|
2013-04-12 16:19:56 +00:00
|
|
|
|
2013-04-18 13:16:18 +00:00
|
|
|
if (this._stageX !== 0 || this._stageY !== 0 || this.worldView.width < this._game.stage.width || this.worldView.height < this._game.stage.height)
|
|
|
|
{
|
|
|
|
this._clip = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this._clip = false;
|
|
|
|
}
|
2013-04-12 16:19:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|