/*
* Manages the object interactions explicitly given to the grid object. Defines object
* behaviors such as movement, pathfinding, etc. Does not define interactions for objs
* not explicitly given to the Grid to manage.
*
*/
/**
* Adds an object to the Grid system. Movement & positioning of this object are then
* controlled through the Grid object itself.
* @param {Renderable} obj - The object to be added. MUST have an associated Xform, else the function will error.
* @returns {number} The ID to use to retrieve this object in the grid to perform future functions on it. -1 If object
* couldn't be added.
*/
Grid.prototype.addObjectToGrid = function(obj) {
// Error chk: Given object must have an Xform to modify position.
try {
obj.getXform();
} catch (error) {
console.log(error);
return -1;
}
// Add object to mObject array. Put the object in the first available spot.
var id;
var added = false;
for (id = 0; id < this.mObjects.length; id++) {
if (this.mObjects[id] === null) {
this.mObjects[id] = obj;
added = true;
break;
}
}
// mObjects was not large enough to hold the object; push it to the end.
if (!added) {
this.mObjects.push(obj);
id = this.mObjects.length - 1;
}
var pos = obj.getXform().getPosition();
var tileIndex = this.getTileAtWC(pos[0], pos[1]);
var tile = null;
// Invalid init tile position
if (tileIndex[0] === -1 && tileIndex[1] === -1) {
var indexX = 0;
var indexY = 0;
tile = this.getTileAtIndex(indexX, indexY);
// Keep looking for a new default tile until we find one that is not occupied.
while (tile.getCollision()) {
indexX++;
tile = this.getTileAtIndex(indexX, indexY);
// Entire X row searched and no available spots; move up a row.
if (tile === null) {
indexX = 0;
indexY++;
tile = this.getTileAtIndex(indexX, indexY);
}
// Termination case if all grid tiles have been checked & are full. ******
if (indexY === (this.mGridH - 1) && indexX === (this.mGridW - 1) && tile === null) {
console.log("Object could not be added; Grid is full!");
return -1;
}
}
} else {
tile = this.getTileAtIndex(tileIndex[0], tileIndex[1]);
}
// We now have our tile to tie the object to; Send it to its position & enable collision.
obj.getXform().setPosition(tile.getXPosWC(), tile.getYPosWC());
tile.setCollision(true);
// Leaving having the size of the object fit within a grid bound up to the game dev to do.
// Addition successful. Return id.
return id;
};
// Given the id of an object belonging to the grid, removes the object from grid control.
// Note, this does not remove the object from existence, rather just removes its direct
// ties to the grid.
// Returns true if removal was successful, false otherwise.
// Requires the array to stay at the same size, else ids may no longer return expected objs.
/**
* Removes the desired object from Grid system control. This does not remove the object from the
* world.
* @param {number} id - The id of an object currently existing in the grid.
* @returns {boolean} True if the object corresponding to id was removed, false otherwise.
*/
Grid.prototype.removeObjectFromGrid = function(id) {
if (this.mObjects[id] === null) {
return false;
}
this.mObjects[id] = null;
return true;
};
/**
* Attempts to move the specified object from its current tile position to a given
* tile index. Does not check for any collision in the tiles between the current tile
* and the desired tile to move to, only checks the desired tile collision property.
* @param {number} id - The id of the object to move.
* @param {number} x - The x coordinate of the Grid index to move to.
* @param {number} y - The y coordinate of the Grid index to move to.
* @returns {boolean} True if the move was successful, false otherwise.
*/
Grid.prototype.changeObjectPosition = function(id, x, y) {
var obj = this.mObjects[id];
if (obj === null || obj === undefined) {
return false;
}
var pos = this.getIDPosition(id);
// Tile object is currently in.
var tile = this.getTileAtIndex(pos[0], pos[1]);
var newTile = this.getTileAtIndex(x, y);
if (newTile === null || newTile.getCollision()) { //Invalid tile coord given, or has collision already
return false;
}
obj.getXform().setPosition(newTile.getXPosWC(), newTile.getYPosWC());
tile.setCollision(false);
newTile.setCollision(true);
return true;
};
// A bit redundant w/ above function at the moment, should probably rework a bit.
/**
* Moves the object specified by the given ID one space in the given direction. Considers collision
* property and current walls of the tile to move into.
* @param {number} id - The id of the object to move.
* @param {Direction} direction - The direction to move the object one tile space.
* @returns {boolean} True if move was successful, false otherwise.
*/
Grid.prototype.moveObjectPositionDir = function(id, direction) {
var obj = this.mObjects[id];
if (obj === null || obj === undefined) {
return false;
}
var pos = this.getIDPosition(id);
// Tile object is currently in.
var tile = this.getTileAtIndex(pos[0], pos[1]);
// Wall check
var walls = tile.getWalls();
for (var i = 0; i < walls.length; i++) {
if (direction[0] === walls[i][0] && direction[1] === walls[i][1]) { // Given direction has a wall, prevent movement.
return false;
}
}
var newTile = this.getTileAtIndex(pos[0] + direction[0], pos[1] + direction[1]);
if (newTile === null || newTile.getCollision()) { //Invalid tile coord given, or has collision already
return false;
}
obj.getXform().setPosition(newTile.getXPosWC(), newTile.getYPosWC());
tile.setCollision(false);
newTile.setCollision(true);
return true;
};
// Returns the position of the specified object in Grid coordinates.
// Returns [-1, -1] if the given ID is invalid.
/**
* Gets the Grid index position of the specified object.
* @param {number} id - The id of the object to get the index position of.
* @return {array} The x & y coordinates in the Grid index of the object, [-1, -1] if object was not found.
*/
Grid.prototype.getIDPosition = function(id) {
if (this.mObjects[id] === null) {
return [-1, -1];
}
var pos = this.mObjects[id].getXform().getPosition();
// Object already exists within Grid, so we can assume this will be a valid tile.
return this.getTileAtWC(pos[0], pos[1]);
};