Skip to content

Commit

Permalink
Closes #239 Optimize Actor drawing
Browse files Browse the repository at this point in the history
Also fixed some bugs in Camera
Also partial work on CollisionMaps
  • Loading branch information
eonarheim committed Mar 26, 2014
1 parent abd4a27 commit f757a79
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 49 deletions.
3 changes: 2 additions & 1 deletion Excalibur.sublime-project
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"file_exclude_patterns" : [
"src/spec/*.js",
"sandbox/*.js",
"src/engine/*.js"
"src/engine/*.js",
"*.csproj"
],
"folder_exclude_patterns" : [
"js",
Expand Down
57 changes: 40 additions & 17 deletions src/engine/Camera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ module ex {
* @method setActorToFollow
* @param actor {Actor} The actor to follow
*/
setActorToFollow(actor: Actor) {
public setActorToFollow(actor: Actor) {
this.follow = actor;
}

Expand All @@ -46,7 +46,7 @@ module ex {
* @method getFocus
* @returns Point
*/
getFocus() {
public getFocus() {
// this should always be overridden
if (this.follow) {
return new Point(0, 0);
Expand All @@ -61,7 +61,7 @@ module ex {
* @param x {number} The x coordinate of the focal point
* @param y {number} The y coordinate of the focal point
*/
setFocus(x: number, y: number) {
public setFocus(x: number, y: number) {
if (!this.follow) {
this.focus.x = x;
this.focus.y = y;
Expand All @@ -75,7 +75,7 @@ module ex {
* @param magnitudeY {number} the y magnitude of the shake
* @param duration {number} the duration of the shake
*/
shake(magnitudeX: number, magnitudeY: number, duration: number) {
public shake(magnitudeX: number, magnitudeY: number, duration: number) {
this.isShaking = true;
this.shakeMagnitudeX = magnitudeX;
this.shakeMagnitudeY = magnitudeY;
Expand All @@ -89,7 +89,7 @@ module ex {
* @param scale {number} the scale of the zoom
* @param [duration] {number} the duration of the zoom
*/
zoom(scale: number, duration?: number) {
public zoom(scale: number, duration?: number) {
this.isZooming = true;
this.maxZoomScale = scale;
this.zoomDuration = duration | 0;
Expand All @@ -101,7 +101,13 @@ module ex {
if (duration) {
this.zoomIncrement = -1 * this.zoomIncrement;
} else {
this.zoomIncrement = -0.01;
this.isZooming = false;
this.setCurrentZoomScale(this.maxZoomScale);
}
}else{
if(!duration){
this.isZooming = false;
this.setCurrentZoomScale(this.maxZoomScale);
}
}

Expand All @@ -110,10 +116,10 @@ module ex {

/**
* gets the current zoom scale
* @method getCurrentZoomScale
* @method getZoom
* @returns {Number} the current zoom scale
*/
getCurrentZoomScale() {
public getZoom() {
return this.currentZoomScale;
}

Expand All @@ -134,8 +140,8 @@ module ex {

var canvasWidth = this.engine.ctx.canvas.width;
var canvasHeight = this.engine.ctx.canvas.height;
var newCanvasWidth = canvasWidth * this.getCurrentZoomScale();
var newCanvasHeight = canvasHeight * this.getCurrentZoomScale();
var newCanvasWidth = canvasWidth * this.getZoom();
var newCanvasHeight = canvasHeight * this.getZoom();

if (this.isDoneShaking()) {
this.isShaking = false;
Expand All @@ -155,15 +161,25 @@ module ex {
this.isZooming = false;
this.elapsedZoomTime = 0;
this.zoomDuration = 0;
this.setCurrentZoomScale(this.maxZoomScale);

} else {
this.elapsedZoomTime += delta;

this.setCurrentZoomScale(this.getCurrentZoomScale() + this.zoomIncrement * delta / 1000);
this.setCurrentZoomScale(this.getZoom() + this.zoomIncrement * delta / 1000);
}

this.engine.ctx.translate(-((newCanvasWidth - canvasWidth)/2), -((newCanvasHeight - canvasHeight)/2));
this.engine.ctx.scale(this.getCurrentZoomScale(), this.getCurrentZoomScale());
//this.engine.ctx.translate(-((newCanvasWidth - canvasWidth)/2), -((newCanvasHeight - canvasHeight)/2));
this.engine.ctx.scale(this.getZoom(), this.getZoom());
}

public debugDraw(ctx: CanvasRenderingContext2D){
var focus = this.getFocus();
ctx.fillStyle = 'yellow';
ctx.beginPath();
ctx.arc(this.follow.x + this.follow.getWidth()/2, 0, 15, 0, Math.PI*2);
ctx.closePath();
ctx.fill();
}

private isDoneShaking(): boolean {
Expand Down Expand Up @@ -193,15 +209,22 @@ module ex {
*/
export class SideCamera extends BaseCamera {

/**
* Returns the focal point of the camera in world space
* @method getFocus
* @returns point
*/
getFocus() {
if (this.follow) {
// return new Point(-this.follow.x + this.engine.width / 2.0, 0);
return new Point((-this.follow.x * this.getCurrentZoomScale()) + (this.engine.width * this.getCurrentZoomScale()) / 2.0, 0);
return new Point(((-this.follow.x - this.follow.getWidth()/2) * this.getZoom()) + (this.engine.getWidth() * this.getZoom()) / 2.0, 0);
} else {
return this.focus;
}
}



}

/**
Expand All @@ -214,14 +237,14 @@ module ex {
export class TopCamera extends BaseCamera {

/**
* Returns the focal point of the camera
* Returns the focal point of the camera in world space
* @method getFocus
* @returns Point
*/
getFocus() {
if (this.follow) {
return new Point((-this.follow.x * this.getCurrentZoomScale()) + (this.engine.width * this.getCurrentZoomScale()) / 2.0,
(-this.follow.y * this.getCurrentZoomScale()) + (this.engine.height * this.getCurrentZoomScale()) / 2.0);
return new Point(((-this.follow.x - this.follow.getWidth() / 2) * this.getZoom()) + (this.engine.getWidth() * this.getZoom()) / 2.0,
((-this.follow.y - this.follow.getHeight() / 2) * this.getZoom()) + (this.engine.getHeight() * this.getZoom()) / 2.0);
} else {
return this.focus;
}
Expand Down
93 changes: 93 additions & 0 deletions src/engine/CollisionMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/// <reference path="Core.ts" />


module ex {


export class CollisionData {
constructor(public solid: boolean, public spriteId: number){}
}

export class CollisionMap {
private _collidingX: number = -1;
private _collidingY: number = -1;

constructor(
public x: number,
public y: number,
public cellWidth: number,
public cellHeight: number,
public rows: number,
public cols: number,
public spriteSheet: SpriteSheet,
public data: CollisionData[]){
}

public collidesActor(actor: Actor): boolean{
return (this.collidesPoint(actor.x, actor.y) ||
this.collidesPoint(actor.x + actor.getWidth(), actor.y)||
this.collidesPoint(actor.x + actor.getWidth(), actor.y + actor.getHeight())||
this.collidesPoint(actor.x, actor.y + actor.getHeight()));

}
public collidesPoint(x: number, y: number): boolean{
var x = Math.floor(x/this.cellWidth);
var y = Math.floor(y/this.cellHeight);
var cell = this.getCell(x, y);
if(cell){
this._collidingX = x;
this._collidingY = y;
return cell.solid;
}

return false;
}

public getCell(x: number, y: number): CollisionData{
return this.data[x+y*this.cols];
}

public draw(ctx: CanvasRenderingContext2D, delta: number){
ctx.save();
ctx.translate(this.x, this.y);
for(var x = 0; x < this.cols; x++){
for(var y = 0; y < this.rows; y++){
var spriteId = this.getCell(x,y).spriteId;
if(spriteId > -1){
this.spriteSheet.getSprite(spriteId).draw(ctx, x*this.cellWidth, y*this.cellHeight);
}
}
}
ctx.restore();
}

public debugDraw(ctx: CanvasRenderingContext2D){
var width = this.cols * this.cellWidth;
var height = this.rows * this.cellHeight;

ctx.save();
ctx.translate(this.x, this.y);

ctx.strokeStyle = Color.Red.toString();
for(var x = 0; x < this.cols+1; x++){
ctx.beginPath();
ctx.moveTo(this.x + x*this.cellWidth, this.y)
ctx.lineTo(this.x + x*this.cellWidth, this.y + height);
ctx.stroke();
}
for(var y = 0; y < this.rows+1; y++){
ctx.beginPath();
ctx.moveTo(this.x, this.y + y*this.cellHeight);
ctx.lineTo(this.x + width, this.y + y*this.cellHeight);
ctx.stroke()
}

if(this._collidingY > -1 && this._collidingX > -1){
ctx.fillStyle = ex.Color.Cyan.toString();
ctx.fillRect(this._collidingX * this.cellWidth, this._collidingY * this.cellHeight, this.cellWidth, this.cellHeight);
}
ctx.restore();

}
}
}
48 changes: 39 additions & 9 deletions src/engine/Core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
/// <reference path="Promises.ts" />
/// <reference path="Util.ts" />
/// <reference path="Binding.ts" />
/// <reference path="CollisionMap.ts" />

module ex {

Expand Down Expand Up @@ -601,8 +602,10 @@ module ex {
this.displayMode = DisplayMode.Fixed;
}
this.logger.debug("Engine viewport is size " + width + " x " + height);
this.width = this.canvas.width = width;
this.height = this.canvas.height = height;
this.width = width;
this.canvas.width = width;
this.height = height;
this.canvas.height = height;

} else if (!displayMode) {
this.logger.debug("Engine viewport is fullscreen");
Expand Down Expand Up @@ -653,6 +656,15 @@ module ex {
this.currentScene.removeChild(actor);
}


public addCollisionMap(collisionMap: CollisionMap){
this.currentScene.addCollisionMap(collisionMap);
}

public removeCollisionMap(collisionMap: CollisionMap){
this.currentScene.removeCollisionMap(collisionMap);
}

/**
* Adds an excalibur timer to the current scene.
* @param timer {Timer} The timer to add to the current scene.
Expand Down Expand Up @@ -717,6 +729,9 @@ module ex {
* @returns number The width of the drawing surface in pixels.
*/
getWidth(): number {
if(this.camera){
return this.width/this.camera.getZoom();
}
return this.width;
}
/**
Expand All @@ -725,6 +740,9 @@ module ex {
* @returns number The height of the drawing surface in pixels.
*/
getHeight(): number {
if(this.camera){
return this.height/this.camera.getZoom();
}
return this.height;
}

Expand All @@ -734,14 +752,18 @@ module ex {
* @param point {Point} screen coordinate to convert
*/
public screenToWorldCoordinates(point: Point): Point {
var newX = Math.floor(point.x * this.canvas.width / this.canvas.clientWidth);
var newY = Math.floor(point.y * this.canvas.height / this.canvas.clientHeight);
// todo set these back this.canvas.clientWidth
var newX = point.x;
var newY = point.y;

if (this.camera) {
var focus = this.camera.getFocus();
newX -= focus.x;
newY -= focus.y;
}

newX = Math.floor((newX / this.canvas.clientWidth) * this.getWidth());
newY = Math.floor((newY / this.canvas.clientHeight) * this.getHeight());
return new Point(newX, newY);
}

Expand All @@ -752,14 +774,21 @@ module ex {
*
*/
public worldToScreenCoordinates(point: Point): Point {
var screenX = Math.floor(point.x / (this.canvas.width / this.canvas.clientWidth));
var screenY = Math.floor(point.y / (this.canvas.height / this.canvas.clientHeight));
// todo set these back this.canvas.clientWidth
// this isn't correct on zoom
var screenX = point.x;
var screenY = point.y;

if(this.camera){
var focus = this.camera.getFocus();
screenX += focus.x;
screenY += focus.y;

screenX += focus.x * (this.getWidth() / this.canvas.clientWidth);
screenY += focus.y * (this.getHeight() / this.canvas.clientHeight);
}

screenX = Math.floor((screenX / this.getWidth()) * this.canvas.clientWidth);
screenY = Math.floor((screenY / this.getHeight()) * this.canvas.clientHeight);

return new Point(screenX, screenY);
}

Expand Down Expand Up @@ -1112,7 +1141,8 @@ module ex {

if (this.isDebug) {
this.ctx.strokeStyle = 'yellow'
this.currentScene.debugDraw(this.ctx);
this.currentScene.debugDraw(this.ctx);
this.camera.debugDraw(this.ctx);
}


Expand Down
4 changes: 2 additions & 2 deletions src/engine/Drawing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ module ex {
*/
public getSprite(index: number): Sprite {
if (index >= 0 && index < this.sprites.length) {
return this.sprites[index].clone();
return this.sprites[index];
}
}
}
Expand Down Expand Up @@ -393,7 +393,7 @@ module ex {
}

private loadPixels(){
if(this.texture.image && !this.pixelsLoaded){
if(this.texture.isLoaded() && !this.pixelsLoaded){
this.spriteCtx.drawImage(this.texture.image, this.sx, this.sy, this.swidth, this.sheight, 0, 0, this.swidth, this.sheight);
//this.pixelData = this.spriteCtx.getImageData(0, 0, this.swidth, this.sheight);

Expand Down
Loading

0 comments on commit f757a79

Please sign in to comment.