/*global FM*/
/**
* An object type can be associated to a game object. Then all game objects of a
* certain type can be processed uniformally through the object type object.
* @class FM.ObjectType
* @param {string} pName The name of the object type.
* @constructor
* @author Simon Chauvin.
*/
FM.ObjectType = function (pName) {
"use strict";
/**
* Name of the type.
* @type string
* @private
*/
this.name = pName;
/**
* Specify if the game objects of the current type are alive.
* @type boolean
* @private
*/
this.alive = true;
/**
* Specify if the game objects of the current type are visible.
* @type boolean
* @private
*/
this.visible = true;
/**
* Specify the depth at which the game objects of the current type are drawn.
* @type int
* @private
*/
this.zIndex = 1;
/**
* Specify the different degrees of scrolling of game objects with this type.
* @type FM.Vector
* @private
*/
this.scrollFactor = new FM.Vector(1, 1);
/**
* Other types of game objects the current type has to collide with.
* @type Array
* @private
*/
this.collidesWith = [];
};
FM.ObjectType.prototype.constructor = FM.ObjectType;
/**
* Check if the game objects of the current type overlap with the game objects
* of the given type.
* @method FM.ObjectType#overlapsWithType
* @memberOf FM.ObjectType
* @param {FM.ObjectType} pType The type to test if it overlaps with the
* current one.
* @return {FM.Collision} Collision object if there is overlapping.
*/
FM.ObjectType.prototype.overlapsWithType = function (pType) {
"use strict";
var state = FM.Game.getCurrentState(),
quad = state.getQuad(),
gameObjects = state.members,
otherGameObjects,
i,
j,
hasType,
hasOtherType,
gameObject,
otherGameObject,
physic,
otherPhysic,
collision = null,
collisionTemp = null;
for (i = 0; i < gameObjects.length; i = i + 1) {
gameObject = gameObjects[i];
physic = gameObject.components[FM.ComponentTypes.PHYSIC];
hasType = gameObject.hasType(this);
hasOtherType = gameObject.hasType(pType);
if (physic && (hasType || hasOtherType)) {
otherGameObjects = quad.retrieve(gameObject);
for (j = 0; j < otherGameObjects.length; j = j + 1) {
otherGameObject = otherGameObjects[j];
otherPhysic = otherGameObject.components[FM.ComponentTypes.PHYSIC];
if (otherPhysic && gameObject.getId() !== otherGameObject.getId()
&& ((hasType && otherGameObject.hasType(pType))
|| (hasOtherType && otherGameObject.hasType(this)))) {
collisionTemp = physic.overlapsWithObject(otherPhysic);
if (collisionTemp) {
collision = collisionTemp;
}
}
}
}
}
return collision;
};
/**
* Check if the game objects of the current type are overlapping with a
* specified game object.
* @method FM.ObjectType#overlapsWithObject
* @memberOf FM.ObjectType
* @param {FM.GameObject} pGameObject Game object to test with the game objects
* of the current type.
* @return {FM.Collision} Collision object if there is overlapping.
*/
FM.ObjectType.prototype.overlapsWithObject = function (pGameObject) {
"use strict";
var gameObjects = FM.Game.getCurrentState().getQuad().retrieve(pGameObject),
i,
otherGameObject,
physic = pGameObject.components[FM.ComponentTypes.PHYSIC],
otherPhysic,
collision = null,
collisionTemp = null;
if (physic) {
for (i = 0; i < gameObjects.length; i = i + 1) {
otherGameObject = gameObjects[i];
otherPhysic = otherGameObject.components[FM.ComponentTypes.PHYSIC];
if (otherPhysic && pGameObject.getId() !== otherGameObject.getId() && otherGameObject.hasType(this)) {
collisionTemp = physic.overlapsWithObject(otherPhysic);
if (collisionTemp) {
collision = collisionTemp;
}
}
}
} else {
if (FM.Parameters.debug) {
console.log("WARNING: you need to specify a game object with a physic component for checking overlaps.");
}
}
return collision;
};
/**
* Ensure that the game objects of the current type collide with a specified one.
* @method FM.ObjectType#addTypeToCollideWith
* @memberOf FM.ObjectType
* @param {FM.ObjectType} pType The type to collide with to add to all game
* objects of this type.
*/
FM.ObjectType.prototype.addTypeToCollideWith = function (pType) {
"use strict";
this.collidesWith.push(pType);
var gameObjects = FM.Game.getCurrentState().members,
i,
gameObject,
physic;
for (i = 0; i < gameObjects.length; i = i + 1) {
gameObject = gameObjects[i];
physic = gameObject.components[FM.ComponentTypes.PHYSIC];
if (physic && gameObject.hasType(this)) {
physic.addTypeToCollideWith(pType);
}
}
};
/**
* Remove a type that was supposed to collide with all the game objects of this type.
* @method FM.ObjectType#removeTypeToCollideWith
* @memberOf FM.ObjectType
* @param {FM.ObjectType} pType The type to collide with to remove from all
* game objects of this type.
*/
FM.ObjectType.prototype.removeTypeToCollideWith = function (pType) {
"use strict";
this.collidesWith.splice(this.collidesWith.indexOf(pType), 1);
var gameObjects = FM.Game.getCurrentState().members,
i,
gameObject,
physic;
for (i = 0; i < gameObjects.length; i = i + 1) {
gameObject = gameObjects[i];
physic = gameObject.components[FM.ComponentTypes.PHYSIC];
if (physic && gameObject.hasType(this)) {
physic.removeTypeToCollideWith(pType);
}
}
};
/**
* Set the z-index of every game objects of the current type.
* @method FM.ObjectType#setZIndex
* @memberOf FM.ObjectType
* @param {int} pZIndex The z index at which all game objects of this type must
* be.
*/
FM.ObjectType.prototype.setZIndex = function (pZIndex) {
"use strict";
this.zIndex = pZIndex;
var gameObjects = FM.Game.getCurrentState().members,
i,
gameObject;
for (i = 0; i < gameObjects.length; i = i + 1) {
gameObject = gameObjects[i];
if (gameObject.hasType(this)) {
gameObject.zIndex = this.zIndex;
}
}
};
/**
* Set the scrollFactor of every game objects of the current type.
* @method FM.ObjectType#setScrollFactor
* @memberOf FM.ObjectType
* @param {FM.Vector} pScrollFactor The factor of scrolling to apply to all
* game objects of this type.
*/
FM.ObjectType.prototype.setScrollFactor = function (pScrollFactor) {
"use strict";
this.scrollFactor = pScrollFactor;
var gameObjects = FM.Game.getCurrentState().members,
i,
gameObject;
for (i = 0; i < gameObjects.length; i = i + 1) {
gameObject = gameObjects[i];
if (gameObject.hasType(this)) {
gameObject.scrollFactor = this.scrollFactor;
}
}
};
/**
* Kill all the game objects of this type.
* @method FM.ObjectType#kill
* @memberOf FM.ObjectType
*/
FM.ObjectType.prototype.kill = function () {
"use strict";
this.alive = false;
};
/**
* Hide all the game objects of this type.
* @method FM.ObjectType#hide
* @memberOf FM.ObjectType
*/
FM.ObjectType.prototype.hide = function () {
"use strict";
this.visible = false;
};
/**
* Revive all the game objects of this type.
* @method FM.ObjectType#revive
* @memberOf FM.ObjectType
*/
FM.ObjectType.prototype.revive = function () {
"use strict";
this.alive = true;
};
/**
* Show all the game objects of this type.
* @method FM.ObjectType#show
* @memberOf FM.ObjectType
*/
FM.ObjectType.prototype.show = function () {
"use strict";
this.visible = true;
};
/**
* Check if the game objects of this type are alive.
* @method FM.ObjectType#isAlive
* @memberOf FM.ObjectType
* @return {boolean} Whether all the game objects of this type are alive.
*/
FM.ObjectType.prototype.isAlive = function () {
"use strict";
return this.alive;
};
/**
* Check if the game object of this type are visible.
* @method FM.ObjectType#isVisible
* @memberOf FM.ObjectType
* @return {boolean} Whether all the game objects of this type are visible.
*/
FM.ObjectType.prototype.isVisible = function () {
"use strict";
return this.visible;
};
/**
* Retrieve the name of the type.
* @method FM.ObjectType#getName
* @memberOf FM.ObjectType
* @return {string} The name of the type.
*/
FM.ObjectType.prototype.getName = function () {
"use strict";
return this.name;
};
/**
* Destroy the type.
* @method FM.ObjectType#destroy
* @memberOf FM.ObjectType
*/
FM.ObjectType.prototype.destroy = function () {
"use strict";
this.name = null;
this.alive = null;
this.visible = null;
this.zIndex = null;
this.scrollFactor.destroy();
this.scrollFactor = null;
this.collidesWith = null;
};