diff --git a/21g30t1e75.js b/21g30t1e75.js index 069f03b..455d4b0 100644 --- a/21g30t1e75.js +++ b/21g30t1e75.js @@ -27,6 +27,11 @@ GameLib.CustomCode.ORIENTATION_RIGHT = 3; GameLib.CustomCode.FOOD_SPEED_INITIAL = 3; GameLib.CustomCode.MAX_FOOD_ITEMS = 6; +GameLib.CustomCode.POWERUP_WAIT_TIME_MIN = 5; +GameLib.CustomCode.POWERUP_WAIT_TIME_MAX = 10; +GameLib.CustomCode.POWERUP_DURATION = 7; +GameLib.CustomCode.MAX_POWERUP_ITEMS = 3; + GameLib.CustomCode.FOOD_BACON = 0; GameLib.CustomCode.FOOD_CHEESE = 1; GameLib.CustomCode.FOOD_ONION = 2; @@ -34,10 +39,19 @@ GameLib.CustomCode.FOOD_ONION_RING = 3; GameLib.CustomCode.FOOD_PATTY = 4; GameLib.CustomCode.FOOD_TOMATO = 5; -GameLib.CustomCode.OCCUPIED_TYPE_NONE = 0; -GameLib.CustomCode.OCCUPIED_TYPE_SNAKE_BODY = 1; -GameLib.CustomCode.OCCUPIED_TYPE_FOOD = 2; -GameLib.CustomCode.OCCUPIED_TYPE_POWERUP = 3; +GameLib.CustomCode.BODY_TYPE_BREAD_BACON = 0; +GameLib.CustomCode.BODY_TYPE_BREAD_CHEESE = 1; +GameLib.CustomCode.BODY_TYPE_BREAD_ONION = 2; +GameLib.CustomCode.BODY_TYPE_BREAD_ONION_RING = 3; +GameLib.CustomCode.BODY_TYPE_BREAD_PATTY = 4; +GameLib.CustomCode.BODY_TYPE_BREAD_HEAD = 5; +GameLib.CustomCode.BODY_TYPE_BREAD_TAIL = 6; +GameLib.CustomCode.BODY_TYPE_BREAD_CORNER = 7; + +GameLib.CustomCode.OBJECT_TYPE_NONE = 0; +GameLib.CustomCode.OBJECT_TYPE_SNAKE_BODY = 1; +GameLib.CustomCode.OBJECT_TYPE_FOOD = 2; +GameLib.CustomCode.OBJECT_TYPE_POWERUP = 3; /** * Get runtime @@ -58,22 +72,6 @@ this.geometryBody = GameLib.EntityManager.Instance.findComponentById('8f5q7k5ozp GameLib.CustomCode.BODY_SCALE_X = this.geometryBody.width; GameLib.CustomCode.BODY_SCALE_Y = this.geometryBody.height; -/** - * Images - * -this.imageBreadHead = GameLib.EntityManager.Instance.findComponentById('swkla3wpp'); -this.imageBreadTail = GameLib.EntityManager.Instance.findComponentById('se6qlnmojd'); -this.imageBreadPatty = GameLib.EntityManager.Instance.findComponentById('01r51k9ptr'); -this.imageBreadCorner = GameLib.EntityManager.Instance.findComponentById('iljpuouaok'); - -this.imageBacon = GameLib.EntityManager.Instance.findComponentById('t4lb4hr4ue'); -this.imageCheese = GameLib.EntityManager.Instance.findComponentById('y2611hx41r'); -this.imageOnion = GameLib.EntityManager.Instance.findComponentById('g3z1wg2vt8'); -this.imageOnionRing = GameLib.EntityManager.Instance.findComponentById('ztcyy0bgk5'); -this.imagePatty = GameLib.EntityManager.Instance.findComponentById('4lf0fw24su'); -this.imageTomato = GameLib.EntityManager.Instance.findComponentById('ptvwmo8l38'); -*/ - /** * Materials */ @@ -91,6 +89,9 @@ this.materialBreadPatty = GameLib.EntityManager.Instance.findComponentById('k6a this.materialBreadHead = GameLib.EntityManager.Instance.findComponentById('heu4f7zzuh'); this.materialBreadTail = GameLib.EntityManager.Instance.findComponentById('mm2yq9rmpf'); this.materialBreadCorner = GameLib.EntityManager.Instance.findComponentById('ju9r1bw6cb'); +this.materialPowerupSpeed = GameLib.EntityManager.Instance.findComponentById('fb32uutj9q'); +this.materialPowerupLife = GameLib.EntityManager.Instance.findComponentById('6tld70a6zu'); +this.materialPowerupSlow = GameLib.EntityManager.Instance.findComponentById('ulgntj8nta'); /** * Other Objects (Scene) @@ -104,11 +105,19 @@ this.animationRotation = GameLib.EntityManager.Instance.findComponentById('z628k */ this.snake = []; this.grid = [[]]; + this.speed = GameLib.CustomCode.SPEED_INITIAL; this.advanceTime = 0; + this.foodTime = 0; this.foodSpeed = GameLib.CustomCode.FOOD_SPEED_INITIAL; this.food = []; + +this.powerupTime = 0; +this.nextPowerupTime = GameLib.Utils.GetRandomIntInclusive( + GameLib.CustomCode.POWERUP_WAIT_TIME_MIN, + GameLib.CustomCode.POWERUP_WAIT_TIME_MAX +); this.powerups = []; /** @@ -130,22 +139,22 @@ GameLib.CustomCode.prototype.visualizeGrid = function (color) { this.starsGeometry = new THREE.Geometry(); - this.grid.map( - function(x, xIndex) { - x.map( - function(y, yIndex) { - this.starsGeometry.vertices.push( - new THREE.Vector3( - (xIndex * GameLib.CustomCode.BODY_SCALE_X) + GameLib.CustomCode.GRID_OFFSET_X, - (yIndex * GameLib.CustomCode.BODY_SCALE_Y) + GameLib.CustomCode.GRID_OFFSET_Y, - 5 - ) - ); - }.bind(this) - ) - }.bind(this) - ); - + this.grid.map( + function(x, xIndex) { + x.map( + function(y, yIndex) { + this.starsGeometry.vertices.push( + new THREE.Vector3( + (xIndex * GameLib.CustomCode.BODY_SCALE_X) + GameLib.CustomCode.GRID_OFFSET_X, + (yIndex * GameLib.CustomCode.BODY_SCALE_Y) + GameLib.CustomCode.GRID_OFFSET_Y, + 5 + ) + ); + }.bind(this) + ) + }.bind(this) + ); + var starsMaterial = new THREE.PointsMaterial({color: color, size: 0.1}); this.starsMesh = new THREE.Points(this.starsGeometry, starsMaterial); @@ -156,17 +165,17 @@ GameLib.CustomCode.prototype.visualizeGrid = function (color) { GameLib.CustomCode.prototype.createGameMesh = function(material, visible) { - if (GameLib.Utils.UndefinedOrNull(visible)) { - visible = true; - } - + if (GameLib.Utils.UndefinedOrNull(visible)) { + visible = true; + } + var mesh = new GameLib.D3.Mesh( this.runtime.graphics, { geometry : this.geometryBody, materials : [material], - visible : visible, - useQuaternion : false + visible : visible, + useQuaternion : false } ) @@ -176,6 +185,315 @@ GameLib.CustomCode.prototype.createGameMesh = function(material, visible) { }.bind(this) +/** + * GameLib.CustomCode.Object + * @param objectType + * @param type + * @param mesh + * @param position + * @param index + * @constructor + */ +GameLib.CustomCode.GameObject = function( + objectType, + type, + mesh, + position, + index +) { + if (GameLib.Utils.UndefinedOrNull(objectType)) { + objectType = GameLib.CustomCode.OBJECT_TYPE_NONE; + } + this.objectType = objectType; + + if (GameLib.Utils.UndefinedOrNull(type)) { + type = -1; + } + this.type = type; + + if (GameLib.Utils.UndefinedOrNull(mesh)) { + mesh = null; + } + this.mesh = mesh; + + if (GameLib.Utils.UndefinedOrNull(position)) { + position = null; + } + this.position = position; + + if (GameLib.Utils.UndefinedOrNull(index)) { + index = -1; + } + this.index = index; +} + +/** + * Disposes of the mesh object and resets this object to its defaults + */ +GameLib.CustomCode.GameObject.prototype.dispose = function(removeMesh) { + + if (GameLib.Utils.UndefinedOrNull(removeMesh)) { + removeMesh = true; + } + + if (this.mesh && removeMesh) { + this.mesh.geometry = null; + this.mesh.materials = null; + this.mesh.remove(); + this.mesh = null; + } + + this.objectType = GameLib.CustomCode.OBJECT_TYPE_NONE; + + this.type = -1; + + this.position = null; + + this.index = -1; +}; + +/** + * Applies the object position to the mesh taking into account the offset and scale of the body + * @param updateInstance + */ +GameLib.CustomCode.GameObject.prototype.applyToMesh = function(updateInstance) { + if (this.mesh) { + + this.mesh.position.x = (this.position.x * GameLib.CustomCode.BODY_SCALE_X) + GameLib.CustomCode.GRID_OFFSET_X; + this.mesh.position.y = (this.position.y * GameLib.CustomCode.BODY_SCALE_Y) + GameLib.CustomCode.GRID_OFFSET_Y; + this.mesh.position.z = 0.1; + + if (updateInstance) { + this.mesh.updateInstance('position'); + } + } +}; + +/** + * Scans through the grid, gets all empty positions, and chooses a random one + * @type {function(this:snakeEntityLoaded)} + */ +GameLib.CustomCode.prototype.getFreeGridPosition = function() { + + var x = GameLib.Utils.GetRandomInt(0, GameLib.CustomCode.GRID_WIDTH); + var y = GameLib.Utils.GetRandomInt(0, GameLib.CustomCode.GRID_HEIGHT); + + return { + x : x, + y : y + }; + +}.bind(this); + +/** + * + * @type {function(this:snakeEntityLoaded)} + */ +GameLib.CustomCode.prototype.createGameObject = function( + objectType, + type, + position, + orientation +) { + + if (GameLib.Utils.UndefinedOrNull(type)) { + type = null; + } + + var mesh = null; + var array = null; + + if (objectType === GameLib.CustomCode.OBJECT_TYPE_POWERUP) { + type = GameLib.Utils.GetRandomIntInclusive(0, 3); + switch (type) { + case GameLib.CustomCode.POWERUP_LIFE : + mesh = this.createGameMesh(this.materialPowerupLife); + break; + case GameLib.CustomCode.POWERUP_SLOW : + mesh = this.createGameMesh(this.materialPowerupSlow); + break; + case GameLib.CustomCode.POWERUP_SPEED : + mesh = this.createGameMesh(this.materialPowerupSpeed); + break; + default : + throw new Error('unhandled power up type : ' + type) + } + + array = this.powerups; + } + + if (objectType === GameLib.CustomCode.OBJECT_TYPE_FOOD) { + type = GameLib.Utils.GetRandomIntInclusive(0, 5); + switch (foodType) { + case GameLib.CustomCode.FOOD_BACON : + mesh = this.createGameMesh(this.materialBacon); + break; + case GameLib.CustomCode.FOOD_CHEESE : + mesh = this.createGameMesh(this.materialCheese); + break; + case GameLib.CustomCode.FOOD_ONION : + mesh = this.createGameMesh(this.materialOnion); + break; + case GameLib.CustomCode.FOOD_ONION_RING : + mesh = this.createGameMesh(this.materialOnionRing); + break; + case GameLib.CustomCode.FOOD_PATTY : + mesh = this.createGameMesh(this.materialPatty); + break; + case GameLib.CustomCode.FOOD_TOMATO : + mesh = this.createGameMesh(this.materialTomato); + break; + default : + throw new Error('unhandled food type : ' + type) + } + + /** + * We apply the scale to the food meshes too - since they appear too big when normal + */ + mesh.scale.x = 0.8; + mesh.scale.y = 0.8; + mesh.updateInstance('scale'); + + array = this.food; + } + + if (objectType === GameLib.CustomCode.OBJECT_TYPE_SNAKE_BODY) { + + switch (type) { + case GameLib.CustomCode.BODY_TYPE_BREAD_BACON : + mesh = this.createGameMesh(this.materialBreadBacon); + break; + case GameLib.CustomCode.BODY_TYPE_BREAD_CHEESE : + mesh = this.createGameMesh(this.materialBreadCheese); + break; + case GameLib.CustomCode.BODY_TYPE_BREAD_ONION : + mesh = this.createGameMesh(this.materialBreadOnion); + break; + case GameLib.CustomCode.BODY_TYPE_BREAD_ONION_RING : + mesh = this.createGameMesh(this.materialBreadOnionRing); + break; + case GameLib.CustomCode.BODY_TYPE_BREAD_PATTY : + mesh = this.createGameMesh(this.materialBreadPatty); + break; + case GameLib.CustomCode.BODY_TYPE_BREAD_HEAD : + mesh = this.createGameMesh(this.materialBreadHead); + break; + case GameLib.CustomCode.BODY_TYPE_BREAD_TAIL : + mesh = this.createGameMesh(this.materialBreadTail); + break; + case GameLib.CustomCode.BODY_TYPE_BREAD_CORNER : + mesh = this.createGameMesh(this.materialBreadCorner); + break; + default : + throw new Error('unhandled body type : ' + type) + } + + array = this.snake; + } + + var gameObject = null; + + switch (objectType) { + case GameLib.CustomCode.OBJECT_TYPE_FOOD: + case GameLib.CustomCode.OBJECT_TYPE_POWERUP: + gameObject = new GameLib.CustomCode.GameObject( + objectType, + type, + mesh, + position, + array.length + ) + gameObject.applyToMesh(true); + break; + case GameLib.CustomCode.OBJECT_TYPE_SNAKE_BODY: + gameObject = new GameLib.CustomCode.SnakeBody( + type, + mesh, + position, + array.length, + orientation + ) + gameObject.applyToMesh(true); + break; + default: + throw new Error('unhandled object type: ' + objectType); + } + + /** + * Update the grid with this object + */ + var currentGameObject = this.grid[gameObject.position.x][gameObject.position.y]; + + /** + * If there is a powerup at this position - remove it + */ + if (currentGameObject.objectType === GameLib.CustomCode.OBJECT_TYPE_POWERUP) { + this.powerups.splice( + this.powerups.indexof(currentGameObject), + 1 + ); + } + + /** + * If there is food at this position - remove it + */ + if (currentGameObject.objectType === GameLib.CustomCode.OBJECT_TYPE_FOOD) { + this.food.splice( + this.food.indexof(currentGameObject), + 1 + ); + } + + /** + * If there is an existing snake body at this position - explode! + */ + if (currentGameObject.objectType === GameLib.CustomCode.OBJECT_TYPE_SNAKE_BODY) { + console.warn('should not reach this code if collision detection is perfect'); + this.explode(currentGameObject.position); + return; + } + + this.grid[gameObject.position.x][gameObject.position.y].dispose(); + this.grid[gameObject.position.x][gameObject.position.y] = gameObject; + + /** + * Save a reference to this object to the specific object array + */ + array.push(gameObject); + + /** + * If we have too many objects - dispose of the first on in the queue (fifo) + */ + if (this.food.length > GameLib.CustomCode.MAX_FOOD_ITEMS) { + gameObject = this.food.shift(); + this.grid[gameObject.position.x][gameObject.position.y].dispose(); + } + + if (this.powerups.length > GameLib.CustomCode.MAX_POWERUP_ITEMS_ITEMS) { + gameObject = this.powerups.shift(); + this.grid[gameObject.position.x][gameObject.position.y].dispose(); + } + +}.bind(this); + +GameLib.CustomCode.prototype.createPowerup = function(delta) { + + this.powerupTime += delta; + + if (this.powerupTime > this.nextPowerupTime) { + this.powerupTime = 0; + } else { + return; + } + + this.createGameObject( + GameLib.CustomCode.OBJECT_TYPE_POWERUP, + null, + this.getFreeGridPosition() + ); + +}.bind(this); + GameLib.CustomCode.prototype.createFood = function(delta) { this.foodTime += delta; @@ -186,110 +504,46 @@ GameLib.CustomCode.prototype.createFood = function(delta) { return; } - var foodType = GameLib.Utils.GetRandomIntInclusive(0, 5); + this.createGameObject( + GameLib.CustomCode.OBJECT_TYPE_FOOD, + null, + this.getFreeGridPosition() + ); - var mesh = null; - - switch (foodType) { - case GameLib.CustomCode.FOOD_BACON : - mesh = this.createGameMesh(this.materialBacon); - break; - case GameLib.CustomCode.FOOD_CHEESE : - mesh = this.createGameMesh(this.materialCheese); - break; - case GameLib.CustomCode.FOOD_ONION : - mesh = this.createGameMesh(this.materialOnion); - break; - case GameLib.CustomCode.FOOD_ONION_RING : - mesh = this.createGameMesh(this.materialOnionRing); - break; - case GameLib.CustomCode.FOOD_PATTY : - mesh = this.createGameMesh(this.materialPatty); - break; - case GameLib.CustomCode.FOOD_TOMATO : - mesh = this.createGameMesh(this.materialTomato); - break; - default : - console.warn('unhandled food type'); - break; - } - - var positionX = GameLib.Utils.GetRandomInt(0, GameLib.CustomCode.GRID_WIDTH); - var positionY = GameLib.Utils.GetRandomInt(0, GameLib.CustomCode.GRID_HEIGHT); - - mesh.position.x = (positionX * GameLib.CustomCode.BODY_SCALE_X) + GameLib.CustomCode.GRID_OFFSET_X; - mesh.position.y = (positionY * GameLib.CustomCode.BODY_SCALE_Y) + GameLib.CustomCode.GRID_OFFSET_Y; - - /** - * We apply the scale to the mesh too - since they appear too big when normal - */ - mesh.scale.x = 0.8; - mesh.scale.y = 0.8; - - mesh.visible = true; - - mesh.updateInstance('position'); - mesh.updateInstance('scale'); - mesh.updateInstance('visible'); - - this.food.push( - { - type : foodType, - mesh : mesh, - position : { - x : positionX, - y : positionY - } - } - ) - - if (this.food.length > GameLib.CustomCode.MAX_FOOD_ITEMS) { - var deleteme = this.food.shift(); - deleteme.mesh.geometry = null; - deleteme.mesh.materials = null; - deleteme.mesh.remove(); - } - - this.rebuildGrid(); - }.bind(this); /** * GameLib.CustomCode.SnakeBody + * @param type * @param mesh * @param position + * @param index * @param orientation * @param flip * @param backupMesh + * @param isTail * @constructor */ GameLib.CustomCode.SnakeBody = function( + type, mesh, position, + index, orientation, flip, backupMesh, - isTail + isTail ) { - if (GameLib.Utils.UndefinedOrNull(mesh)) { - throw new Error('no mesh specified'); - } - this.mesh = mesh; - - this.mesh.position.z = 0.1; - - this.mesh.updateInstance('position'); - this.mesh.updateInstance('visible'); - - if (GameLib.Utils.UndefinedOrNull(position)) { - position = { - x : Math.round(GameLib.CustomCode.GRID_WIDTH / 2), - y : Math.round(GameLib.CustomCode.GRID_HEIGHT / 2) - }; - } - this.position = position; + GameLib.CustomCode.GameObject.call( + this, + GameLib.Object.OBJECT_TYPE_SNAKE_BODY, + type, + mesh, + position, + index + ); if (GameLib.Utils.UndefinedOrNull(orientation)) { orientation = GameLib.CustomCode.ORIENTATION_UP; @@ -306,25 +560,27 @@ GameLib.CustomCode.SnakeBody = function( } this.backupMesh = backupMesh; - if (GameLib.Utils.UndefinedOrNull(isTail)) { + if (GameLib.Utils.UndefinedOrNull(isTail)) { isTail = false; } this.isTail = isTail; - + this.applyToMesh(); }; -GameLib.CustomCode.SnakeBody.prototype.applyToMesh = function() { +GameLib.CustomCode.SnakeBody.prototype = Object.create(GameLib.CustomCode.GameObject.prototype); +GameLib.CustomCode.SnakeBody.prototype.constructor = GameLib.CustomCode.GameObject; - this.mesh.position.x = (this.position.x * GameLib.CustomCode.BODY_SCALE_X) + GameLib.CustomCode.GRID_OFFSET_X; - this.mesh.position.y = (this.position.y * GameLib.CustomCode.BODY_SCALE_Y) + GameLib.CustomCode.GRID_OFFSET_Y; +GameLib.CustomCode.SnakeBody.prototype.applyToMesh = function(updateInstance) { - this.mesh.rotation.z = this.orientation * Math.PI / 2; + GameLib.CustomCode.GameObject.prototype.applyToMesh.call(this, updateInstance); + + this.mesh.rotation.z = this.orientation * Math.PI / 2; if (this.backupMesh) { this.mesh.rotation.z += ((Math.PI / 2) * this.flip); - this.mesh.updateInstance('position'); - this.mesh.updateInstance('rotation'); + this.mesh.updateInstance('position'); + this.mesh.updateInstance('rotation'); } this.mesh.updateInstance('rotation'); @@ -332,51 +588,51 @@ GameLib.CustomCode.SnakeBody.prototype.applyToMesh = function() { GameLib.CustomCode.SnakeBody.prototype.advance = function(orientation, flip) { - var crash = false; - - switch (orientation) { - case GameLib.CustomCode.ORIENTATION_UP : - if ((this.position.y + 1) >= GameLib.CustomCode.GRID_HEIGHT) { - crash = true; - } else { - this.position.y += 1; - } - break; - case GameLib.CustomCode.ORIENTATION_DOWN : - if ((this.position.y - 1) < 0) { - crash = true; - } else { - this.position.y -= 1; - } - break; - case GameLib.CustomCode.ORIENTATION_LEFT : - if ((this.position.x - 1) < 0) { - crash = true; - } else { - this.position.x -= 1; - } - break; - case GameLib.CustomCode.ORIENTATION_RIGHT : - if ((this.position.x + 1) >= GameLib.CustomCode.GRID_WIDTH) { - crash = true; - } else { - this.position.x += 1; - } - break; - default : - console.warn('unknown orientation'); - break; - } - - if (!crash) { - console.log('check against body'); - } else { - console.log('crashed!'); - } - + var crash = false; + + switch (orientation) { + case GameLib.CustomCode.ORIENTATION_UP : + if ((this.position.y + 1) >= GameLib.CustomCode.GRID_HEIGHT) { + crash = true; + } else { + this.position.y += 1; + } + break; + case GameLib.CustomCode.ORIENTATION_DOWN : + if ((this.position.y - 1) < 0) { + crash = true; + } else { + this.position.y -= 1; + } + break; + case GameLib.CustomCode.ORIENTATION_LEFT : + if ((this.position.x - 1) < 0) { + crash = true; + } else { + this.position.x -= 1; + } + break; + case GameLib.CustomCode.ORIENTATION_RIGHT : + if ((this.position.x + 1) >= GameLib.CustomCode.GRID_WIDTH) { + crash = true; + } else { + this.position.x += 1; + } + break; + default : + console.warn('unknown orientation'); + break; + } + + if (crash) { + console.log('crashed!'); + } + this.orientation = orientation; this.flip = flip; + + return !crash; } GameLib.CustomCode.prototype.initializeGrid = function() { @@ -386,61 +642,86 @@ GameLib.CustomCode.prototype.initializeGrid = function() { for (var x = 0; x < GameLib.CustomCode.GRID_WIDTH; x++) { this.grid[x] = []; for (var y = 0; y < GameLib.CustomCode.GRID_HEIGHT; y++) { - this.grid[x][y] = { - occupied : false, - type : GameLib.CustomCode.OCCUPIED_TYPE_NONE, - index : -1 - } + this.grid[x][y] = new GameLib.CustomCode.GameObject(); } } }.bind(this); -GameLib.CustomCode.prototype.rebuildGrid = function() { +// GameLib.CustomCode.prototype.rebuildGrid = function() { +// +// this.initializeGrid(); +// +// /** +// * First add all the snake body parts +// */ +// this.snake.map( +// function(body, index) { +// this.grid[body.position.x][body.position.y] = { +// occupied: true, +// type : GameLib.CustomCode.OBJECT_TYPE_SNAKE_BODY, +// index : index +// } +// }.bind(this) +// ); +// +// /** +// * Then add all the food bits +// */ +// this.food.map( +// function(food, index) { +// this.grid[food.position.x][food.position.y] = { +// occupied: true, +// type : GameLib.CustomCode.OBJECT_TYPE_FOOD, +// index : index +// } +// }.bind(this) +// ); +// +// /** +// * And also all the power ups +// */ +// this.powerups.map( +// function(powerup, index) { +// this.grid[powerup.position.x][powerup.position.y] = { +// occupied: true, +// type : GameLib.CustomCode.OBJECT_TYPE_POWERUP, +// index : index +// } +// }.bind(this) +// ); +// +// }.bind(this); - this.initializeGrid(); - - /** - * First add all the snake body parts - */ - this.snake.map( - function(body, index) { - this.grid[body.position.x][body.position.y] = { - occupied: true, - type : GameLib.CustomCode.OCCUPIED_TYPE_SNAKE_BODY, - index : index - } - }.bind(this) - ); - - /** - * Then add all the food bits - */ - this.food.map( - function(food, index) { - this.grid[food.position.x][food.position.y] = { - occupied: true, - type : GameLib.CustomCode.OCCUPIED_TYPE_FOOD, - index : index - } - }.bind(this) - ); - - /** - * And also all the power ups - */ - this.powerups.map( - function(powerup, index) { - this.grid[powerup.position.x][powerup.position.y] = { - occupied: true, - type : GameLib.CustomCode.OCCUPIED_TYPE_POWERUP, - index : index - } - }.bind(this) - ); - -}.bind(this); +/** + * Explode the snake + * @param position + */ +GameLib.CustomCode.prototype.explode = function(position) { + console.log('explode snake at position : ' + position.x + ', ' + position.y); +} + +/** + * Extend the snake with information from gameObject + * @param gameObject + */ +GameLib.CustomCode.prototype.extend = function(gameObject) { + console.log('extend'); +}; + +/** + * Powerup the snake with information from gameObject + * @param gameObject + */ +GameLib.CustomCode.prototype.powerup = function(gameObject) { + console.log('powerup'); +}; + +/** + * Move the snake forward and do collision detection + * @type {function(this:snakeEntityLoaded)} + */ GameLib.CustomCode.prototype.advanceSnake = function(delta) { this.advanceTime += delta; @@ -468,11 +749,65 @@ GameLib.CustomCode.prototype.advanceSnake = function(delta) { flip : body.flip } - body.advance( + var advanced = body.advance( this.state.orientation, - this.state.flip + this.state.flip, + this.grid ); + if (!advanced) { + + this.explode(body.position); + + } else { + + var gameObject = this.grid[body.position.x][body.position.y]; + + switch (gameObject.objectType) { + case GameLib.CustomCode.OBJECT_TYPE_SNAKE_BODY : + this.explode(body.position); + break; + case GameLib.CustomCode.OBJECT_TYPE_FOOD : + this.extend(gameObject); + break; + case GameLib.CustomCode.OBJECT_TYPE_POWERUP: + this.powerup(gameObject); + break; + default: + /** + * Update the grid with the body + */ + this.grid[body.position.x][body.position.y] = body; + break; + } + + /** + * Food or powerup objects need to be destroyed before being replaced with a body object + */ + if ( + gameObject.objectType === GameLib.CustomCode.OBJECT_TYPE_FOOD || + gameObject.objectType === GameLib.CustomCode.OBJECT_TYPE_POWERUP + ) { + + if (gameObject.objectType === GameLib.CustomCode.OBJECT_TYPE_FOOD) { + this.food.splice( + this.food.indexOf(gameObject), + 1 + ); + } else { + this.powerups.splice( + this.powerups.indexOf(gameObject), + 1 + ); + } + + gameObject.dispose(); + + this.grid[body.position.x][body.position.y] = body; + } + + } + backup.orientation = body.orientation; backup.flip = body.flip; } @@ -488,11 +823,24 @@ GameLib.CustomCode.prototype.advanceSnake = function(delta) { flip : body.flip } + /** + * Create a new empty object at the current grid position (free it up) + */ + this.grid[body.position.x][body.position.y] = new GameLib.CustomCode.GameObject(); + + /** + * Assign the new location to the body + */ body.position.x = backup.position.x; body.position.y = backup.position.y; body.orientation = backup.orientation; body.flip = backup.flip; + /** + * Update the grid with our new body + */ + this.grid[body.position.x][body.position.y] = body; + if (body.backupMesh) { /** * We used to be a corner, change back @@ -513,75 +861,68 @@ GameLib.CustomCode.prototype.advanceSnake = function(delta) { body.mesh.updateInstance('visible'); body.mesh.updateInstance('position'); - } + } - if ( - body.orientation !== temp.orientation - ) { + if (body.orientation !== temp.orientation) { if ((index ) < this.snake.length) { /** * Our orientation changed - we should make a corner - */ - body.orientation = temp.orientation; - - body.applyToMesh(); - - body.orientation = backup.orientation; - + */ + body.orientation = temp.orientation; + + body.applyToMesh(); + + body.orientation = backup.orientation; + body.backupMesh = body.mesh; - - if (temp.orientation === GameLib.CustomCode.ORIENTATION_UP) { - body.backupMesh.position.y -= 0.5 * GameLib.CustomCode.BODY_SCALE_Y; - } - - if (temp.orientation === GameLib.CustomCode.ORIENTATION_DOWN) { - body.backupMesh.position.y += 0.5 * GameLib.CustomCode.BODY_SCALE_Y; - } - - if (temp.orientation === GameLib.CustomCode.ORIENTATION_LEFT) { - body.backupMesh.position.x += 0.5 * GameLib.CustomCode.BODY_SCALE_X; - } - - if (temp.orientation === GameLib.CustomCode.ORIENTATION_RIGHT) { - body.backupMesh.position.x -= 0.5 * GameLib.CustomCode.BODY_SCALE_X; - } - - //body.backupMesh.visible = false; + + if (temp.orientation === GameLib.CustomCode.ORIENTATION_UP) { + body.backupMesh.position.y -= 0.5 * GameLib.CustomCode.BODY_SCALE_Y; + } + + if (temp.orientation === GameLib.CustomCode.ORIENTATION_DOWN) { + body.backupMesh.position.y += 0.5 * GameLib.CustomCode.BODY_SCALE_Y; + } + + if (temp.orientation === GameLib.CustomCode.ORIENTATION_LEFT) { + body.backupMesh.position.x += 0.5 * GameLib.CustomCode.BODY_SCALE_X; + } + + if (temp.orientation === GameLib.CustomCode.ORIENTATION_RIGHT) { + body.backupMesh.position.x -= 0.5 * GameLib.CustomCode.BODY_SCALE_X; + } + + //body.backupMesh.visible = false; //body.backupMesh.updateInstance('visible'); - - body.mesh = this.createGameMesh(this.materialBreadCorner); - - body.mesh.position.z = 5; - - body.mesh.updateInstance('position'); - - body.mesh.visible = true; - - body.mesh.updateInstance('visible'); + + body.mesh = this.createGameMesh(this.materialBreadCorner); + + body.mesh.position.z = 5; + + body.mesh.updateInstance('position'); + + body.mesh.visible = true; + + body.mesh.updateInstance('visible'); } - + } - - backup = temp; + + backup = temp; } - //if (!body.isTail) { - + //if (!body.isTail) { + body.applyToMesh(); - //} + //} }.bind(this) ) - this.state.turning = false; + this.state.turning = false; - /** - * At this point - we advanced the whole snake - time to rebuild the grid - */ - this.rebuildGrid(); - }.bind(this); GameLib.Event.Subscribe( @@ -599,22 +940,22 @@ GameLib.Event.Subscribe( } ) - this.food.map( + this.food.map( function(food) { food.mesh.geometry = null; food.mesh.materials = null; food.mesh.remove(); } ) - - this.powerups.map( - function(powerup) { - powerup.mesh.geometry = null; + + this.powerups.map( + function(powerup) { + powerup.mesh.geometry = null; powerup.mesh.materials = null; powerup.mesh.remove(); - } - ); - + } + ); + this.state = { orientation : GameLib.CustomCode.ORIENTATION_UP }; @@ -651,38 +992,45 @@ GameLib.Event.Subscribe( y : 1 }, 0, - 0, - null, - true + 0, + null, + true ) ]; - - this.snake[0].mesh.updateInstance('position'); - this.snake[1].mesh.updateInstance('position'); - this.snake[2].mesh.updateInstance('position'); - this.snake[3].mesh.updateInstance('position'); - - this.animation.meshes.push(this.snake[0].mesh); - this.animation.meshes.push(this.snake[1].mesh); - this.animation.meshes.push(this.snake[2].mesh); - this.animation.meshes.push(this.snake[3].mesh); - - //this.snake[2].mesh.instance.add(this.snake[3].mesh.instance); - //this.animationRotation.meshes.push(this.snake[3].mesh); - - this.initializeGrid(); + + this.snake[0].mesh.updateInstance('position'); + this.snake[1].mesh.updateInstance('position'); + this.snake[2].mesh.updateInstance('position'); + this.snake[3].mesh.updateInstance('position'); + + this.animation.meshes.push(this.snake[0].mesh); + this.animation.meshes.push(this.snake[1].mesh); + this.animation.meshes.push(this.snake[2].mesh); + this.animation.meshes.push(this.snake[3].mesh); + + //this.snake[2].mesh.instance.add(this.snake[3].mesh.instance); + //this.animationRotation.meshes.push(this.snake[3].mesh); + + this.initializeGrid(); //this.visualizeGrid(); /** * Other Settings */ - this.advanceTime = 0; + this.advanceTime = 0; this.speed = GameLib.CustomCode.SPEED_INITIAL; - this.foodTime = 0; - this.foodSpeed = GameLib.CustomCode.FOOD_SPEED_INITIAL; - this.food = []; - this.powerups = []; - + + this.foodTime = 0; + this.foodSpeed = GameLib.CustomCode.FOOD_SPEED_INITIAL; + this.food = []; + + this.powerupTime = 0; + this.nextPowerupTime = GameLib.Utils.GetRandomIntInclusive( + GameLib.CustomCode.POWERUP_WAIT_TIME_MIN, + GameLib.CustomCode.POWERUP_WAIT_TIME_MAX + ); + this.powerups = []; + /** * Re-initialize our other custom code components */