diff --git a/examples/dirtyRect/gameObj.js b/examples/dirtyRect/entities.js similarity index 100% rename from examples/dirtyRect/gameObj.js rename to examples/dirtyRect/entities.js diff --git a/examples/dirtyRect/index.html b/examples/dirtyRect/index.html index dc2906a977..808ea03eb3 100644 --- a/examples/dirtyRect/index.html +++ b/examples/dirtyRect/index.html @@ -6,8 +6,8 @@
- - + +
diff --git a/examples/dirtyRect/main.js b/examples/dirtyRect/main.js index abf3e5b400..37a23985c4 100755 --- a/examples/dirtyRect/main.js +++ b/examples/dirtyRect/main.js @@ -47,7 +47,7 @@ var jsApp = // init the video - if (!me.video.init('jsapp', 1024, 768, true, 'auto', false)) + if (!me.video.init('jsapp', 1024, 768, true, 'auto')) { alert("Sorry but your browser does not support html 5 canvas."); return; diff --git a/examples/dirtyRect/screenObj.js b/examples/dirtyRect/screens.js old mode 100755 new mode 100644 similarity index 100% rename from examples/dirtyRect/screenObj.js rename to examples/dirtyRect/screens.js diff --git a/examples/platformer/entities.js b/examples/platformer/entities.js index 1919c0309c..de2c026fb4 100644 --- a/examples/platformer/entities.js +++ b/examples/platformer/entities.js @@ -37,10 +37,10 @@ var PlayerEntity = me.ObjectEntity.extend({ me.input.bindKey(me.input.KEY.DOWN, "down"); // walking animatin - this.addAnimation ("walk", [0,2,1]); + this.renderable.addAnimation ("walk", [0,2,1]); // set default one - this.setCurrentAnimation("walk"); + this.renderable.setCurrentAnimation("walk"); }, /* ----- @@ -112,7 +112,7 @@ var PlayerEntity = me.ObjectEntity.extend({ } // check if we moved - if (this.vel.x!=0 || this.vel.y!=0 || this.isFlickering()) { + if (this.vel.x!=0 || this.vel.y!=0 || this.renderable.isFlickering()) { this.parent(); return true; } @@ -125,9 +125,9 @@ var PlayerEntity = me.ObjectEntity.extend({ * ouch */ hurt : function () { - if (!this.flickering) + if (!this.renderable.flickering) { - this.flicker(45); + this.renderable.flicker(45); // flash the screen me.game.viewport.fadeIn("#FFFFFF", 75); me.audio.play("die", false); @@ -151,15 +151,15 @@ var CoinEntity = me.CollectableEntity.extend({ this.parent(x, y , settings); // animation speed - this.animationspeed = 8; + this.renderable.animationspeed = 8; // bounding box //this.updateColRect(8,16,16,16); // walking animatin - this.addAnimation("spin", [0,1,2,3]); + this.renderable.addAnimation("spin", [0,1,2,3]); - this.setCurrentAnimation("spin"); + this.renderable.setCurrentAnimation("spin"); }, @@ -210,16 +210,16 @@ var PathEnemyEntity = me.ObjectEntity.extend({ // custom animation speed ? if (settings.animationspeed) { - this,animationspeed = settings.animationspeed; + this.renderable.animationspeed = settings.animationspeed; } // walking animatin - this.addAnimation ("walk", [0,1]); + this.renderable.addAnimation ("walk", [0,1]); // dead animatin - this.addAnimation ("dead", [2]); + this.renderable.addAnimation ("dead", [2]); // set default one - this.setCurrentAnimation("walk"); + this.renderable.setCurrentAnimation("walk"); }, @@ -252,7 +252,7 @@ var PathEnemyEntity = me.ObjectEntity.extend({ // call the parent function this.parent(); // return true if we moved of if flickering - return (this.vel.x != 0 || this.vel.y != 0 || this.isFlickering()); + return (this.vel.x != 0 || this.vel.y != 0 || this.renderable.isFlickering()); }, /** @@ -267,9 +267,10 @@ var PathEnemyEntity = me.ObjectEntity.extend({ // and not collidable anymore this.collidable = false; // set dead animation - this.setCurrentAnimation("dead"); + this.renderable.setCurrentAnimation("dead"); // make it flicker and call destroy once timer finished - this.flicker(45, function(){me.game.remove(this)}); + var self = this; + this.renderable.flicker(45, function(){me.game.remove(self)}); // dead sfx me.audio.play("enemykill", false); // give some score diff --git a/examples/whack-a-mole/main.js b/examples/whack-a-mole/main.js index f66141e971..61e2b7afac 100755 --- a/examples/whack-a-mole/main.js +++ b/examples/whack-a-mole/main.js @@ -258,7 +258,7 @@ var MoleEntity = me.AnimationSheet.extend( /** * a mole manager (to manage movement, etc..) */ -var MoleManager = me.InvisibleEntity.extend( +var MoleManager = me.ObjectEntity.extend( { moles : [], diff --git a/src/entity/entity.js b/src/entity/entity.js index d1aa38ae9e..063ff38848 100644 --- a/src/entity/entity.js +++ b/src/entity/entity.js @@ -131,10 +131,9 @@ obj.init = function() { // add default entity object - obj.add("me.LevelEntity", me.LevelEntity); obj.add("me.ObjectEntity", me.ObjectEntity); obj.add("me.CollectableEntity", me.CollectableEntity); - obj.add("me.InvisibleEntity", me.InvisibleEntity); + obj.add("me.LevelEntity", me.LevelEntity); }; /** @@ -298,692 +297,778 @@ * or when calling the parent constructor * * @class - * @extends me.AnimationSheet + * @extends me.Rect * @memberOf me * @constructor * @param {int} x the x coordinates of the sprite object * @param {int} y the y coordinates of the sprite object * @param {me.ObjectSettings} settings Object Properties as defined in Tiled
*/ - me.ObjectEntity = me.AnimationSheet - .extend( - /** @scope me.ObjectEntity.prototype */ - { - /** - * Entity "Game Unique Identifier"
- * @public - * @type String - * @name me.ObjectEntity#GUID - */ - GUID : null, - - /** - * define the type of the object
- * default value : none
- * @public - * @type Object - * @name me.ObjectEntity#type - */ - type : 0, - - /** - * flag to enable collision detection for this object
- * default value : false
- * @public - * @type Boolean - * @name me.ObjectEntity#collidable - */ - collidable : false, - - - /** - * Entity collision Box
- * @public - * @type me.Rect - * @name me.ObjectEntity#collisionBox - */ - collisionBox : null, - - /** @private */ - init : function(x, y, settings) { - this.parent(x, y, - (typeof settings.image == "string") ? me.loader.getImage(settings.image) : settings.image, - settings.spritewidth, - settings.spriteheight, - settings.spacing, - settings.margin); - - // check for user defined transparent color - if (settings.transparent_color) { - this.setTransparency(settings.transparent_color); - } + me.ObjectEntity = me.Rect.extend( + /** @scope me.ObjectEntity.prototype */ { + + /** + * Entity "Game Unique Identifier"
+ * @public + * @type String + * @name me.ObjectEntity#GUID + */ + GUID : null, - // set the object GUID value - this.GUID = me.utils.createGUID(); - - // set the object entity name - this.name = settings.name?settings.name.toLowerCase():""; - - /** - * entity current velocity
- * @public - * @type me.Vector2d - * @name me.ObjectEntity#vel - */ - this.vel = new me.Vector2d(); - - /** - * entity current acceleration
- * @public - * @type me.Vector2d - * @name me.ObjectEntity#accel - */ - this.accel = new me.Vector2d(); - - /** - * entity current friction
- * @public - * @type me.Vector2d - * @name me.ObjectEntity#friction - */ - this.friction = new me.Vector2d(); - - /** - * max velocity (to limit entity velocity)
- * @public - * @type me.Vector2d - * @name me.ObjectEntity#maxVel - */ - this.maxVel = new me.Vector2d(1000,1000); - - // some default contants - /** - * Default gravity value of the entity
- * default value : 0.98 (earth gravity)
- * to be set to 0 for RPG, shooter, etc...
- * Note: Gravity can also globally be defined through me.sys.gravity - * @public - * @see me.sys.gravity - * @type Number - * @name me.ObjectEntity#gravity - */ - this.gravity = (me.sys.gravity!=undefined)?me.sys.gravity:0.98; - - // just to identify our object - this.isEntity = true; - - // dead state :) - /** - * dead/living state of the entity
- * default value : true - * @public - * @type Boolean - * @name me.ObjectEntity#alive - */ - this.alive = true; - - // some usefull variable - - /** - * falling state of the object
- * true if the object is falling
- * false if the object is standing on something
- * (!) READ ONLY property - * @public - * @type Boolean - * @name me.ObjectEntity#falling - */ - this.falling = false; - /** - * jumping state of the object
- * equal true if the entity is jumping
- * (!) READ ONLY property - * @public - * @type Boolean - * @name me.ObjectEntity#jumping - */ - this.jumping = true; - - // some usefull slope variable - this.slopeY = 0; - /** - * equal true if the entity is standing on a slope
- * (!) READ ONLY property - * @public - * @type Boolean - * @name me.ObjectEntity#onslope - */ - this.onslope = false; - /** - * equal true if the entity is on a ladder
- * (!) READ ONLY property - * @public - * @type Boolean - * @name me.ObjectEntity#onladder - */ - this.onladder = false; - - // to enable collision detection - this.collidable = settings.collidable || false; - //this.collectable = false; - - this.type = settings.type || 0; - - - // ref to the collision map - this.collisionMap = me.game.collisionMap; - - // create a a default collision rectangle - this.collisionBox = new me.Rect(this.pos, this.width, this.height); - - // to know if our object can break tiles - /** - * Define if an entity can go through breakable tiles
- * default value : false
- * @public - * @type Boolean - * @name me.ObjectEntity#canBreakTile - */ - this.canBreakTile = false; - - /** - * a callback when an entity break a tile
- * @public - * @type Function - * @name me.ObjectEntity#onTileBreak - */ - this.onTileBreak = null; - }, - - /** - * specify the size of the hit box for collision detection
- * (allow to have a specific size for each object)
- * e.g. : object with resized collision box :
- * - * @param {int} x x offset (specify -1 to not change the width) - * @param {int} w width of the hit box - * @param {int} y y offset (specify -1 to not change the height) - * @param {int} h height of the hit box - */ - updateColRect : function(x, w, y, h) { - this.collisionBox.adjustSize(x, w, y, h); - }, - - /** - * onCollision Event function
- * called by the game manager when the object collide with shtg
- * by default, if the object type is Collectable, the destroy function is called - * @param {me.Vector2d} res collision vector - * @param {me.ObjectEntity} obj the other object that hit this object - * @protected - */ - onCollision : function(res, obj) { - // destroy the object if collectable - if (this.collidable - && (this.type == me.game.COLLECTABLE_OBJECT)) - me.game.remove(this); - }, - - /** - * set the entity default velocity
- * note : velocity is by default limited to the same value, see setMaxVelocity if needed
- * @param {Int} x velocity on x axis - * @param {Int} y velocity on y axis - * @protected - */ - - setVelocity : function(x, y) { - this.accel.x = (x != 0) ? x : this.accel.x; - this.accel.y = (y != 0) ? y : this.accel.y; - - // limit by default to the same max value - this.setMaxVelocity(x,y); - }, - - /** - * cap the entity velocity to the specified value
- * @param {Int} x max velocity on x axis - * @param {Int} y max velocity on y axis - * @protected - */ - setMaxVelocity : function(x, y) { - this.maxVel.x = x; - this.maxVel.y = y; - }, - - /** - * set the entity default friction
- * @param {Int} x horizontal friction - * @param {Int} y vertical friction - * @protected - */ - setFriction : function(x, y) { - this.friction.x = x || 0; - this.friction.y = y || 0; - }, + /** + * define the type of the object
+ * default value : none
+ * @public + * @type String + * @name me.ObjectEntity#type + */ + type : 0, + + /** + * flag to enable collision detection for this object
+ * default value : false
+ * @public + * @type Boolean + * @name me.ObjectEntity#collidable + */ + collidable : false, + + + /** + * Entity collision Box
+ * @public + * @type me.Rect + * @name me.ObjectEntity#collisionBox + */ + collisionBox : null, + + /** + * The entity renderable object (if defined) + * @public + * @type me.Renderable + * @name me.ObjectEntity#renderable + */ + renderable : null, + + // z position (for ordering display) + z : 0, + + /** + * the visible state of the object
+ * default value : true + * @public + * @type Boolean + * @name me.ObjectEntity#visible + */ + visible : true, + + /** + * Whether the object is visible and within the viewport
+ * default value : false + * @public + * @readonly + * @type Boolean + * @name me.ObjectEntity#inViewport + */ + inViewport : false, + + /** + * Define if a renderable follows screen coordinates (floating)
+ * or the world coordinates (not floating)
+ * default value : false + * @public + * @type Boolean + * @name me.ObjectEntity#floating + */ + floating: false, + + + /** @private */ + init : function(x, y, settings) { + + // call the parent constructor + this.parent(new me.Vector2d(x, y), + settings.spritewidth || settings.width, + settings.spriteheight || settings.height); + + if (settings.image) { + var image = (typeof settings.image == "string") ? me.loader.getImage(settings.image) : settings.image + this.renderable = new me.AnimationSheet(0, 0, image, + settings.spritewidth, + settings.spriteheight, + settings.spacing, + settings.margin); - /** - * Flip object on horizontal axis - * @param {Boolean} flip enable/disable flip - */ - flipX : function(flip) { - if (flip != this.lastflipX) { - // call the parent function - this.parent(flip); - - // flip the collision box - this.collisionBox.flipX(this.width); - } - }, - - /** - * Flip object on vertical axis - * @param {Boolean} flip enable/disable flip - */ - flipY : function(flip) { - if (flip != this.lastflipY) { - // call the parent function - this.parent(flip); - - // flip the collision box - this.collisionBox.flipY(this.height); - } - }, - - - /** - * helper function for platform games:
- * make the entity move left of right
- * @param {Boolean} left will automatically flip horizontally the entity sprite - * @protected - * @example - * if (me.input.isKeyPressed('left')) - * { - * this.doWalk(true); - * } - * else if (me.input.isKeyPressed('right')) - * { - * this.doWalk(false); - * } - */ - doWalk : function(left) { - this.flipX(left); - this.vel.x += (left) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick; - }, - - /** - * helper function for platform games:
- * make the entity move up and down
- * only valid is the player is on a ladder - * @param {Boolean} up will automatically flip vertically the entity sprite - * @protected - * @example - * if (me.input.isKeyPressed('up')) - * { - * this.doClimb(true); - * } - * else if (me.input.isKeyPressed('down')) - * { - * this.doClimb(false); - * } - */ - doClimb : function(up) { - // add the player x acceleration to the y velocity - if (this.onladder) { - this.vel.y = (up) ? -this.accel.x * me.timer.tick - : this.accel.x * me.timer.tick; - return true; - } - return false; - }, - - - /** - * helper function for platform games:
- * make the entity jump
- * @protected - */ - doJump : function() { - // only jump if standing - if (!this.jumping && !this.falling) { - this.vel.y = -this.maxVel.y * me.timer.tick; - this.jumping = true; - return true; + // check for user defined transparent color + if (settings.transparent_color) { + this.renderable.setTransparency(settings.transparent_color); + } + } + + // set the object GUID value + this.GUID = me.utils.createGUID(); + + // set the object entity name + this.name = settings.name?settings.name.toLowerCase():""; + + /** + * entity current velocity
+ * @public + * @type me.Vector2d + * @name me.ObjectEntity#vel + */ + this.vel = new me.Vector2d(); + + /** + * entity current acceleration
+ * @public + * @type me.Vector2d + * @name me.ObjectEntity#accel + */ + this.accel = new me.Vector2d(); + + /** + * entity current friction
+ * @public + * @type me.Vector2d + * @name me.ObjectEntity#friction + */ + this.friction = new me.Vector2d(); + + /** + * max velocity (to limit entity velocity)
+ * @public + * @type me.Vector2d + * @name me.ObjectEntity#maxVel + */ + this.maxVel = new me.Vector2d(1000,1000); + + // some default contants + /** + * Default gravity value of the entity
+ * default value : 0.98 (earth gravity)
+ * to be set to 0 for RPG, shooter, etc...
+ * Note: Gravity can also globally be defined through me.sys.gravity + * @public + * @see me.sys.gravity + * @type Number + * @name me.ObjectEntity#gravity + */ + this.gravity = (me.sys.gravity!=undefined)?me.sys.gravity:0.98; + + // just to identify our object + this.isEntity = true; + + // dead state :) + /** + * dead/living state of the entity
+ * default value : true + * @public + * @type Boolean + * @name me.ObjectEntity#alive + */ + this.alive = true; + + // some usefull variable + + /** + * falling state of the object
+ * true if the object is falling
+ * false if the object is standing on something
+ * (!) READ ONLY property + * @public + * @type Boolean + * @name me.ObjectEntity#falling + */ + this.falling = false; + /** + * jumping state of the object
+ * equal true if the entity is jumping
+ * (!) READ ONLY property + * @public + * @type Boolean + * @name me.ObjectEntity#jumping + */ + this.jumping = true; + + // some usefull slope variable + this.slopeY = 0; + /** + * equal true if the entity is standing on a slope
+ * (!) READ ONLY property + * @public + * @type Boolean + * @name me.ObjectEntity#onslope + */ + this.onslope = false; + /** + * equal true if the entity is on a ladder
+ * (!) READ ONLY property + * @public + * @type Boolean + * @name me.ObjectEntity#onladder + */ + this.onladder = false; + + // to enable collision detection + this.collidable = settings.collidable || false; + //this.collectable = false; + + this.type = settings.type || 0; + + + // ref to the collision map + this.collisionMap = me.game.collisionMap; + + // create a a default collision rectangle + this.collisionBox = new me.Rect(this.pos, this.width, this.height); + + // to know if our object can break tiles + /** + * Define if an entity can go through breakable tiles
+ * default value : false
+ * @public + * @type Boolean + * @name me.ObjectEntity#canBreakTile + */ + this.canBreakTile = false; + + /** + * a callback when an entity break a tile
+ * @public + * @type Function + * @name me.ObjectEntity#onTileBreak + */ + this.onTileBreak = null; + }, + + /** + * specify the size of the hit box for collision detection
+ * (allow to have a specific size for each object)
+ * e.g. : object with resized collision box :
+ * + * @param {int} x x offset (specify -1 to not change the width) + * @param {int} w width of the hit box + * @param {int} y y offset (specify -1 to not change the height) + * @param {int} h height of the hit box + */ + updateColRect : function(x, w, y, h) { + this.collisionBox.adjustSize(x, w, y, h); + }, + + /** + * onCollision Event function
+ * called by the game manager when the object collide with shtg
+ * by default, if the object type is Collectable, the destroy function is called + * @param {me.Vector2d} res collision vector + * @param {me.ObjectEntity} obj the other object that hit this object + * @protected + */ + onCollision : function(res, obj) { + // destroy the object if collectable + if (this.collidable && (this.type == me.game.COLLECTABLE_OBJECT)) + me.game.remove(this); + }, + + /** + * set the entity default velocity
+ * note : velocity is by default limited to the same value, see setMaxVelocity if needed
+ * @param {Int} x velocity on x axis + * @param {Int} y velocity on y axis + * @protected + */ + + setVelocity : function(x, y) { + this.accel.x = (x != 0) ? x : this.accel.x; + this.accel.y = (y != 0) ? y : this.accel.y; + + // limit by default to the same max value + this.setMaxVelocity(x,y); + }, + + /** + * cap the entity velocity to the specified value
+ * @param {Int} x max velocity on x axis + * @param {Int} y max velocity on y axis + * @protected + */ + setMaxVelocity : function(x, y) { + this.maxVel.x = x; + this.maxVel.y = y; + }, + + /** + * set the entity default friction
+ * @param {Int} x horizontal friction + * @param {Int} y vertical friction + * @protected + */ + setFriction : function(x, y) { + this.friction.x = x || 0; + this.friction.y = y || 0; + }, + + /** + * Flip object on horizontal axis + * @param {Boolean} flip enable/disable flip + */ + flipX : function(flip) { + if (flip != this.lastflipX) { + if (this.renderable) { + // flip the animation + this.renderable.flipX(flip); + } + + // flip the collision box + this.collisionBox.flipX(this.width); + } + }, + + /** + * Flip object on vertical axis + * @param {Boolean} flip enable/disable flip + */ + flipY : function(flip) { + if (flip != this.lastflipY) { + if (this.renderable) { + // flip the animation + this.renderable.flipY(flip); + } + // flip the collision box + this.collisionBox.flipY(this.height); + } + }, + + + /** + * helper function for platform games:
+ * make the entity move left of right
+ * @param {Boolean} left will automatically flip horizontally the entity sprite + * @protected + * @example + * if (me.input.isKeyPressed('left')) + * { + * this.doWalk(true); + * } + * else if (me.input.isKeyPressed('right')) + * { + * this.doWalk(false); + * } + */ + doWalk : function(left) { + this.flipX(left); + this.vel.x += (left) ? -this.accel.x * me.timer.tick : this.accel.x * me.timer.tick; + }, + + /** + * helper function for platform games:
+ * make the entity move up and down
+ * only valid is the player is on a ladder + * @param {Boolean} up will automatically flip vertically the entity sprite + * @protected + * @example + * if (me.input.isKeyPressed('up')) + * { + * this.doClimb(true); + * } + * else if (me.input.isKeyPressed('down')) + * { + * this.doClimb(false); + * } + */ + doClimb : function(up) { + // add the player x acceleration to the y velocity + if (this.onladder) { + this.vel.y = (up) ? -this.accel.x * me.timer.tick + : this.accel.x * me.timer.tick; + return true; + } + return false; + }, + + + /** + * helper function for platform games:
+ * make the entity jump
+ * @protected + */ + doJump : function() { + // only jump if standing + if (!this.jumping && !this.falling) { + this.vel.y = -this.maxVel.y * me.timer.tick; + this.jumping = true; + return true; + } + return false; + }, + + /** + * helper function for platform games:
+ * force to the entity to jump (for double jump)
+ * @protected + */ + forceJump : function() { + this.jumping = this.falling = false; + this.doJump(); + }, + + + /** + * return the distance to the specified entity + * @param {me.ObjectEntity} entity Entity + * @return {float} distance + */ + distanceTo: function(e) + { + // the me.Vector2d object also implements the same function, but + // we have to use here the center of both entities + var dx = (this.pos.x + this.hWidth) - (e.pos.x + e.hWidth); + var dy = (this.pos.y + this.hHeight) - (e.pos.y + e.hHeight); + return Math.sqrt(dx*dx+dy*dy); + }, + + /** + * return the distance to the specified point + * @param {me.Vector2d} vector vector + * @return {float} distance + */ + distanceToPoint: function(v) + { + // the me.Vector2d object also implements the same function, but + // we have to use here the center of both entities + var dx = (this.pos.x + this.hWidth) - (v.x); + var dy = (this.pos.y + this.hHeight) - (v.y); + return Math.sqrt(dx*dx+dy*dy); + }, + + /** + * return the angle to the specified entity + * @param {me.ObjectEntity} entity Entity + * @return {Number} angle in radians + */ + angleTo: function(e) + { + // the me.Vector2d object also implements the same function, but + // we have to use here the center of both entities + var ax = (e.pos.x + e.hWidth) - (this.pos.x + this.hWidth); + var ay = (e.pos.y + e.hHeight) - (this.pos.y + this.hHeight); + return Math.atan2(ay, ax); + }, + + + /** + * return the angle to the specified point + * @param {me.Vector2d} vector vector + * @return {Number} angle in radians + */ + angleToPoint: function(v) + { + // the me.Vector2d object also implements the same function, but + // we have to use here the center of both entities + var ax = (v.x) - (this.pos.x + this.hWidth); + var ay = (v.y) - (this.pos.y + this.hHeight); + return Math.atan2(ay, ax); + }, + + + /** + * handle the player movement on a slope + * and update vel value + * @private + */ + checkSlope : function(tile, left) { + + // first make the object stick to the tile + this.pos.y = tile.pos.y - this.height; + + // normally the check should be on the object center point, + // but since the collision check is done on corner, we must do the same thing here + if (left) + this.slopeY = tile.height - (this.collisionBox.right + this.vel.x - tile.pos.x); + else + this.slopeY = (this.collisionBox.left + this.vel.x - tile.pos.x); + + // cancel y vel + this.vel.y = 0; + // set player position (+ workaround when entering/exiting slopes tile) + this.pos.y += this.slopeY.clamp(0, tile.height); + + }, + + /** + * compute the new velocity value + * @private + */ + computeVelocity : function(vel) { + + // apply gravity (if any) + if (this.gravity) { + // apply a constant gravity (if not on a ladder) + vel.y += !this.onladder?(this.gravity * me.timer.tick):0; + + // check if falling / jumping + this.falling = (vel.y > 0); + this.jumping = this.falling?false:this.jumping; + } + + // apply friction + if (this.friction.x) + vel.x = me.utils.applyFriction(vel.x,this.friction.x); + if (this.friction.y) + vel.y = me.utils.applyFriction(vel.y,this.friction.y); + + // cap velocity + if (vel.y !=0) + vel.y = vel.y.clamp(-this.maxVel.y,this.maxVel.y); + if (vel.x !=0) + vel.x = vel.x.clamp(-this.maxVel.x,this.maxVel.x); + }, + + + + /** + * handle the player movement, "trying" to update his position
+ * @return {me.Vector2d} a collision vector + * @example + * // make the player move + * if (me.input.isKeyPressed('left')) + * { + * this.vel.x -= this.accel.x * me.timer.tick; + * } + * else if (me.input.isKeyPressed('right')) + * { + * this.vel.x += this.accel.x * me.timer.tick; + * } + * // update player position + * var res = this.updateMovement(); + * + * // check for collision result with the environment + * if (res.x != 0) + * { + * // x axis + * if (res.x<0) + * console.log("x axis : left side !"); + * else + * console.log("x axis : right side !"); + * } + * else if(res.y != 0) + * { + * // y axis + * if (res.y<0) + * console.log("y axis : top side !"); + * else + * console.log("y axis : bottom side !"); + * + * // display the tile type + * console.log(res.yprop.type) + * } + * + * // check player status after collision check + * var updated = (this.vel.x!=0 || this.vel.y!=0); + */ + updateMovement : function() { + + this.computeVelocity(this.vel); + + // check for collision + var collision = this.collisionMap.checkCollision(this.collisionBox, this.vel); + + // update some flags + this.onslope = collision.yprop.isSlope || collision.xprop.isSlope; + // clear the ladder flag + this.onladder = false; + + + + // y collision + if (collision.y) { + + // going down, collision with the floor + this.onladder = collision.yprop.isLadder; + + if (collision.y > 0) { + if (collision.yprop.isSolid || (collision.yprop.isPlatform && (this.collisionBox.bottom - 1 <= collision.ytile.pos.y))) { + // adjust position to the corresponding tile + this.pos.y = ~~this.pos.y; + this.vel.y = (this.falling) ?collision.ytile.pos.y - this.collisionBox.bottom: 0 ; + this.falling = false; } - return false; - }, - - /** - * helper function for platform games:
- * force to the entity to jump (for double jump)
- * @protected - */ - forceJump : function() { - this.jumping = this.falling = false; - this.doJump(); - }, - - - /** - * return the distance to the specified entity - * @param {me.ObjectEntity} entity Entity - * @return {float} distance - */ - distanceTo: function(e) - { - // the me.Vector2d object also implements the same function, but - // we have to use here the center of both entities - var dx = (this.pos.x + this.hWidth) - (e.pos.x + e.hWidth); - var dy = (this.pos.y + this.hHeight) - (e.pos.y + e.hHeight); - return Math.sqrt(dx*dx+dy*dy); - }, - - /** - * return the distance to the specified point - * @param {me.Vector2d} vector vector - * @return {float} distance - */ - distanceToPoint: function(v) - { - // the me.Vector2d object also implements the same function, but - // we have to use here the center of both entities - var dx = (this.pos.x + this.hWidth) - (v.x); - var dy = (this.pos.y + this.hHeight) - (v.y); - return Math.sqrt(dx*dx+dy*dy); - }, - - /** - * return the angle to the specified entity - * @param {me.ObjectEntity} entity Entity - * @return {Number} angle in radians - */ - angleTo: function(e) - { - // the me.Vector2d object also implements the same function, but - // we have to use here the center of both entities - var ax = (e.pos.x + e.hWidth) - (this.pos.x + this.hWidth); - var ay = (e.pos.y + e.hHeight) - (this.pos.y + this.hHeight); - return Math.atan2(ay, ax); - }, - - - /** - * return the angle to the specified point - * @param {me.Vector2d} vector vector - * @return {Number} angle in radians - */ - angleToPoint: function(v) - { - // the me.Vector2d object also implements the same function, but - // we have to use here the center of both entities - var ax = (v.x) - (this.pos.x + this.hWidth); - var ay = (v.y) - (this.pos.y + this.hHeight); - return Math.atan2(ay, ax); - }, - - - /** - * handle the player movement on a slope - * and update vel value - * @private - */ - checkSlope : function(tile, left) { - - // first make the object stick to the tile - this.pos.y = tile.pos.y - this.height; - - // normally the check should be on the object center point, - // but since the collision check is done on corner, we must do the same thing here - if (left) - this.slopeY = tile.height - (this.collisionBox.right + this.vel.x - tile.pos.x); - else - this.slopeY = (this.collisionBox.left + this.vel.x - tile.pos.x); - - // cancel y vel - this.vel.y = 0; - // set player position (+ workaround when entering/exiting slopes tile) - this.pos.y += this.slopeY.clamp(0, tile.height); - - }, - - /** - * compute the new velocity value - * @private - */ - computeVelocity : function(vel) { - - // apply gravity (if any) - if (this.gravity) { - // apply a constant gravity (if not on a ladder) - vel.y += !this.onladder?(this.gravity * me.timer.tick):0; - - // check if falling / jumping - this.falling = (vel.y > 0); - this.jumping = this.falling?false:this.jumping; + else if (collision.yprop.isSlope && !this.jumping) { + // we stop falling + this.checkSlope(collision.ytile, collision.yprop.isLeftSlope); + this.falling = false; } - - // apply friction - if (this.friction.x) - vel.x = me.utils.applyFriction(vel.x,this.friction.x); - if (this.friction.y) - vel.y = me.utils.applyFriction(vel.y,this.friction.y); - - // cap velocity - if (vel.y !=0) - vel.y = vel.y.clamp(-this.maxVel.y,this.maxVel.y); - if (vel.x !=0) - vel.x = vel.x.clamp(-this.maxVel.x,this.maxVel.x); - }, - - - - /** - * handle the player movement, "trying" to update his position
- * @return {me.Vector2d} a collision vector - * @example - * // make the player move - * if (me.input.isKeyPressed('left')) - * { - * this.vel.x -= this.accel.x * me.timer.tick; - * } - * else if (me.input.isKeyPressed('right')) - * { - * this.vel.x += this.accel.x * me.timer.tick; - * } - * // update player position - * var res = this.updateMovement(); - * - * // check for collision result with the environment - * if (res.x != 0) - * { - * // x axis - * if (res.x<0) - * console.log("x axis : left side !"); - * else - * console.log("x axis : right side !"); - * } - * else if(res.y != 0) - * { - * // y axis - * if (res.y<0) - * console.log("y axis : top side !"); - * else - * console.log("y axis : bottom side !"); - * - * // display the tile type - * console.log(res.yprop.type) - * } - * - * // check player status after collision check - * var updated = (this.vel.x!=0 || this.vel.y!=0); - */ - updateMovement : function() { - - this.computeVelocity(this.vel); - - // check for collision - var collision = this.collisionMap.checkCollision(this.collisionBox, this.vel); - - // update some flags - this.onslope = collision.yprop.isSlope || collision.xprop.isSlope; - // clear the ladder flag - this.onladder = false; - - - - // y collision - if (collision.y) { - - // going down, collision with the floor - this.onladder = collision.yprop.isLadder; - - if (collision.y > 0) { - if (collision.yprop.isSolid || (collision.yprop.isPlatform && (this.collisionBox.bottom - 1 <= collision.ytile.pos.y))) { - // adjust position to the corresponding tile - this.pos.y = ~~this.pos.y; - this.vel.y = (this.falling) ?collision.ytile.pos.y - this.collisionBox.bottom: 0 ; - this.falling = false; - } - else if (collision.yprop.isSlope && !this.jumping) { - // we stop falling - this.checkSlope(collision.ytile, collision.yprop.isLeftSlope); - this.falling = false; - } - else if (collision.yprop.isBreakable) { - if (this.canBreakTile) { - // remove the tile - me.game.currentLevel.clearTile(collision.ytile.col, collision.ytile.row); - if (this.onTileBreak) - this.onTileBreak(); - } - else { - // adjust position to the corresponding tile - this.pos.y = ~~this.pos.y; - this.vel.y = (this.falling) ?collision.ytile.pos.y - this.collisionBox.bottom: 0; - this.falling = false; - } - } + else if (collision.yprop.isBreakable) { + if (this.canBreakTile) { + // remove the tile + me.game.currentLevel.clearTile(collision.ytile.col, collision.ytile.row); + if (this.onTileBreak) + this.onTileBreak(); } - // going up, collision with ceiling - else if (collision.y < 0) { - if (!collision.yprop.isPlatform && !collision.yprop.isLadder) { - this.falling = true; - // cancel the y velocity - this.vel.y = 0; - } + else { + // adjust position to the corresponding tile + this.pos.y = ~~this.pos.y; + this.vel.y = (this.falling) ?collision.ytile.pos.y - this.collisionBox.bottom: 0; + this.falling = false; } } + } + // going up, collision with ceiling + else if (collision.y < 0) { + if (!collision.yprop.isPlatform && !collision.yprop.isLadder) { + this.falling = true; + // cancel the y velocity + this.vel.y = 0; + } + } + } - // x collision - if (collision.x) { + // x collision + if (collision.x) { - this.onladder = collision.xprop.isLadder ; + this.onladder = collision.xprop.isLadder ; - if (collision.xprop.isSlope && !this.jumping) { - this.checkSlope(collision.xtile, collision.xprop.isLeftSlope); - this.falling = false; - } else { - // can walk through the platform & ladder - if (!collision.xprop.isPlatform && !collision.xprop.isLadder) { - if (collision.xprop.isBreakable && this.canBreakTile) { - // remove the tile - me.game.currentLevel.clearTile(collision.xtile.col, collision.xtile.row); - if (this.onTileBreak) { - this.onTileBreak(); - } - } else { - this.vel.x = 0; - } + if (collision.xprop.isSlope && !this.jumping) { + this.checkSlope(collision.xtile, collision.xprop.isLeftSlope); + this.falling = false; + } else { + // can walk through the platform & ladder + if (!collision.xprop.isPlatform && !collision.xprop.isLadder) { + if (collision.xprop.isBreakable && this.canBreakTile) { + // remove the tile + me.game.currentLevel.clearTile(collision.xtile.col, collision.xtile.row); + if (this.onTileBreak) { + this.onTileBreak(); } + } else { + this.vel.x = 0; } } + } + } - // update player position - this.pos.add(this.vel); + // update player position + this.pos.add(this.vel); - // returns the collision "vector" - return collision; + // returns the collision "vector" + return collision; - }, + }, + + /** + * Checks if this entity collides with others entities. + * @public + * @function + * @param {Boolean} [multiple=false] check for multiple collision + * @return {me.Vector2d} collision vector or an array of collision vector (if multiple collision){@link me.Rect#collideVsAABB} + * @example + * // update player movement + * this.updateMovement(); + * + * // check for collision with other objects + * res = this.collide(); + * + * // check if we collide with an enemy : + * if (res && (res.obj.type == me.game.ENEMY_OBJECT)) + * { + * if (res.x != 0) + * { + * // x axis + * if (res.x<0) + * console.log("x axis : left side !"); + * else + * console.log("x axis : right side !"); + * } + * else + * { + * // y axis + * if (res.y<0) + * console.log("y axis : top side !"); + * else + * console.log("y axis : bottom side !"); + * } + * } + */ + collide : function(multiple) { + return me.game.collide(this, multiple || false); + }, + + /** + * Checks if the specified entity collides with others entities of the specified type. + * @public + * @function + * @param {String} type Entity type to be tested for collision + * @param {Boolean} [multiple=false] check for multiple collision + * @return {me.Vector2d} collision vector or an array of collision vector (multiple collision){@link me.Rect#collideVsAABB} + */ + collideType : function(type, multiple) { + return me.game.collideType(this, type, multiple || false); + }, + + /** @private */ + update : function() { + if (this.renderable) { + return this.renderable.update(); + } + return false; + }, + + /** + * object draw
+ * not to be called by the end user
+ * called by the game manager on each game loop + * @protected + * @param {Context2d} context 2d Context on which draw our object + **/ + draw : function(context) { + // draw the sprite if defined + if (this.renderable) { + //translate display since renderable + //postion is relative to the entity + context.translate(this.pos.x, this.pos.y); + this.renderable.draw(context); + context.translate(-this.pos.x, -this.pos.y); + } + // check if debug mode is enabled + if (me.debug.renderHitBox) { + // draw the collisionBox + this.collisionBox.draw(context, "red"); - /** - * Checks if this entity collides with others entities. - * @public - * @function - * @param {Boolean} [multiple=false] check for multiple collision - * @return {me.Vector2d} collision vector or an array of collision vector (if multiple collision){@link me.Rect#collideVsAABB} - * @example - * // update player movement - * this.updateMovement(); - * - * // check for collision with other objects - * res = this.collide(); - * - * // check if we collide with an enemy : - * if (res && (res.obj.type == me.game.ENEMY_OBJECT)) - * { - * if (res.x != 0) - * { - * // x axis - * if (res.x<0) - * console.log("x axis : left side !"); - * else - * console.log("x axis : right side !"); - * } - * else - * { - * // y axis - * if (res.y<0) - * console.log("y axis : top side !"); - * else - * console.log("y axis : bottom side !"); - * } - * } - */ - collide : function(multiple) { - return me.game.collide(this, multiple || false); - }, - - /** - * Checks if the specified entity collides with others entities of the specified type. - * @public - * @function - * @param {String} type Entity type to be tested for collision - * @param {Boolean} [multiple=false] check for multiple collision - * @return {me.Vector2d} collision vector or an array of collision vector (multiple collision){@link me.Rect#collideVsAABB} - */ - collideType : function(type, multiple) { - return me.game.collideType(this, type, multiple || false); - }, + // draw entity current velocity + var x = ~~(this.pos.x + this.hWidth); + var y = ~~(this.pos.y + this.hHeight); - /** - * object draw
- * not to be called by the end user
- * called by the game manager on each game loop - * @protected - * @param {Context2d} context 2d Context on which draw our object - **/ - draw : function(context) { - // call parent function - this.parent(context); - - // check if debug mode is enabled - if (me.debug.renderHitBox) { - // draw the collisionBox - this.collisionBox.draw(context, "red"); - - // draw entity current velocity - var x = ~~(this.pos.x + this.hWidth); - var y = ~~(this.pos.y + this.hHeight); - - context.lineWidth = 1; - context.beginPath(); - context.moveTo(x , y); - context.lineTo(x + ~~(this.vel.x * this.hWidth), y + ~~(this.vel.y * this.hHeight)); - context.stroke(); - } - } + context.lineWidth = 1; + context.beginPath(); + context.moveTo(x , y); + context.lineTo(x + ~~(this.vel.x * this.hWidth), y + ~~(this.vel.y * this.hHeight)); + context.stroke(); + } + }, + + /** + * Destroy function
+ * @private + */ + destroy : function() { + // free some property objects + if (this.renderable) { + this.renderable.destroy.apply(this.renderable, arguments); + this.renderable = null; + } + this.onDestroyEvent.apply(this, arguments); + this.pos = null; + this.collisionBox = null; + }, + + /** + * OnDestroy Notification function
+ * Called by engine before deleting the object + */ + onDestroyEvent : function() { + ;// to be extended ! + } }); @@ -1017,120 +1102,6 @@ } }); - /************************************************************************************/ - /* */ - /* a non visible entity */ - /* NOT FINISHED */ - /************************************************************************************/ - /** - * @class - * @extends me.Rect - * @memberOf me - * @constructor - * @param {int} x the x coordinates of the object - * @param {int} y the y coordinates of the object - * @param {me.ObjectSettings} settings object settings - */ - me.InvisibleEntity = me.Rect - .extend( - /** @scope me.InvisibleEntity.prototype */ - { - - /** - * Entity "Game Unique Identifier"
- * @public - * @type String - * @name me.InvisibleEntity#GUID - */ - GUID : null, - - // for z ordering - z : 0, - collisionBox : null, - - /** @private */ - init : function(x, y, settings) { - // call the parent constructor - this.parent(new me.Vector2d(x, y), settings.width, settings.height); - - // create a a default collision rectangle - this.collisionBox = new me.Rect(this.pos, settings.width, settings.height); - - // set the object GUID value - this.GUID = me.utils.createGUID(); - - // set the object entity name - this.name = settings.name?settings.name.toLowerCase():""; - - this.visible = true; - - this.collidable = true; - - // just to identify our object - this.isEntity = true; - - }, - - /** - * specify the size of the hit box for collision detection
- * (allow to have a specific size for each object)
- * e.g. : object with resized collision box :
- * - * @param {int} x x offset (specify -1 to not change the width) - * @param {int} w width of the hit box - * @param {int} y y offset (specify -1 to not change the height) - * @param {int} h height of the hit box - */ - updateColRect : function(x, w, y, h) { - this.collisionBox.adjustSize(x, w, y, h); - }, - - /** - * onCollision Event function
- * called by the game manager when the object collide with shtg - * @param {me.Vector2d} res collision vector - * @param {me.ObjectEntity} obj the other object that hit this object - * @protected - */ - onCollision : function(res, obj) { - ;// to be extended - }, - - /** - * Destroy function - * @private - */ - destroy : function() { - // call the destroy notification function - this.onDestroyEvent.apply(this, arguments); - }, - - /** - * OnDestroy Notification function
- * Called by engine before deleting the object - */ - onDestroyEvent : function() { - ;// to be extended ! - }, - - /** @private */ - update : function() { - return false; - }, - - /** @private */ - draw : function(context) { - if (me.debug.renderHitBox) { - // draw the sprite rectangle - context.strokeStyle = "blue"; - context.strokeRect(this.pos.x, this.pos.y, this.width, this.height); - - this.collisionBox.draw(context); - } - - } - }); - /************************************************************************************/ /* */ /* a level entity */ @@ -1138,14 +1109,14 @@ /************************************************************************************/ /** * @class - * @extends me.InvisibleEntity + * @extends me.ObjectEntity * @memberOf me * @constructor * @param {int} x the x coordinates of the object * @param {int} y the y coordinates of the object * @param {me.ObjectSettings} settings object settings */ - me.LevelEntity = me.InvisibleEntity.extend( + me.LevelEntity = me.ObjectEntity.extend( /** @scope me.LevelEntity.prototype */ { /** @private */ @@ -1157,10 +1128,11 @@ this.fade = settings.fade; this.duration = settings.duration; this.fading = false; - + + this.collidable = true; + // a temp variable this.gotolevel = settings.to; - }, /** diff --git a/src/entity/sprite.js b/src/entity/sprite.js index 8afb615a8b..4eb80ea9f4 100644 --- a/src/entity/sprite.js +++ b/src/entity/sprite.js @@ -8,11 +8,68 @@ (function($) { /** - * A Simple object to display a sprite on screen. + * A base class for renderable objects. * @class * @extends me.Rect * @memberOf me * @constructor + * @param {me.Vector2d} position of the renderable object + * @param {int} object width + * @param {int} object height + */ + me.Renderable = me.Rect.extend( + /** @scope me.Renderable.prototype */ + { + // to identify the object as a renderable object + isRenderable: true, + + /** + * Define if a renderable follows screen coordinates (floating)
+ * or the world coordinates (not floating)
+ * default value : false + * @public + * @type Boolean + * @name me.Renderable#floating + */ + floating: false, + + /** + * @ignore + */ + init : function(pos, width, height) { + // call the parent constructor + this.parent(pos, width, height); + }, + + /** + * update function + * called by the game manager on each game loop + * @protected + * @return false + **/ + update : function() { + return false; + }, + + /** + * object draw + * called by the game manager on each game loop + * @protected + * @param {Context2d} context 2d Context on which draw our object + **/ + draw : function(context, color) { + // draw the parent rectangle + this.parent(context, color); + } + }); + + + /** + * A Simple object to display a sprite on screen. + * @class + * @extends me.Renderable + * @memberOf me + * @constructor * @param {int} x the x coordinates of the sprite object * @param {int} y the y coordinates of the sprite object * @param {me.loader#getImage} image reference to the Sprite Image @@ -22,7 +79,7 @@ * // create a static Sprite Object * mySprite = new me.SpriteObject (100, 100, me.loader.getImage("mySpriteImage")); */ - me.SpriteObject = me.Rect.extend( + me.SpriteObject = me.Renderable.extend( /** @scope me.SpriteObject.prototype */ { // default scale ratio of the object @@ -89,16 +146,6 @@ */ alpha: 1.0, - /** - * Define if a renderable follows screen coordinates (floating)
- * or the world coordinates (not floating)
- * default value : false - * @public - * @type Boolean - * @name me.SpriteObject#floating - */ - floating: false, - // image reference image : null, @@ -326,7 +373,7 @@ if (me.debug.renderHitBox) { // draw the sprite rectangle - this.parent(context, "blue"); + this.parent(context); } }, @@ -532,8 +579,6 @@ * @protected */ update : function() { - // call the parent function - this.parent(); // update animation if necessary if (this.visible && !this.animationpause && (this.fpscount++ > this.current.animationspeed)) { this.setAnimationFrame(++this.current.idx); @@ -549,9 +594,9 @@ else if (typeof(this.resetAnim) == "function") this.resetAnim(); } - return true; + return this.parent() || true; } - return false; + return this.parent(); } });