Difference between revisions of "Team:Carnegie Mellon/game"
Line 1: | Line 1: | ||
<html> | <html> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | <head> | |
− | + | <title>Luciferase: The Game</title> | |
+ | |||
+ | <script type="text/JavaScript"> //constants | ||
+ | /* Option Variables */ | ||
+ | var MSPF = 33; //MilliSeconds per frame | ||
+ | var DISPLAYNAMES = false; | ||
− | + | /* Board Variables */ | |
− | + | var BOUNDARIES = [10000,10000]; | |
− | + | /* Cell variables */ | |
− | + | var CELLIMAGELOCATION = ["https://static.igem.org/mediawiki/2015/8/89/Cell1.png"]; | |
+ | var STARTRADIUS = 25; //pixels | ||
+ | var STARTSPEED = 25*33/MSPF; | ||
+ | var SPLITRADIUS = 200; //distance cells can fly when being split | ||
+ | var MINSPLITRADIUS = 200; //minimum size to be split | ||
+ | var MAXSIZE = 500; | ||
+ | var EATINGRATIO = .80; | ||
− | + | /* Light variables */ | |
+ | var SUBSTRATEIMAGELOCATION = "substrate.png"; | ||
+ | var STARTLUMINANCE = 100; | ||
+ | var LIGHTDECREASERATE = 60/MSPF; | ||
+ | var MAXLUMINANCE = 1000; | ||
− | + | /* Spike variables */ | |
− | + | var SPIKEIMAGELOCATION = "spike.gif"; | |
− | + | /* Game Variables */ | |
− | + | var FOODSTARTSPAWN = 100; | |
− | + | var FOODSPAWNRATE = 66/MSPF; | |
+ | var FOODSIZE = 20; | ||
+ | |||
+ | var SUBSTRATESIZE = 100; | ||
+ | var SUBSTRATESTARTSPAWN = 50; | ||
+ | var SUBSTRATESPAWNRATE = 33/MSPF; | ||
+ | var SUBSTRATEVALUE = 100; | ||
+ | |||
+ | var SPIKESIZE = 500; | ||
+ | var SPIKESTARTSPAWN = 0;//10; | ||
+ | var SPIKESPAWNRATE = 0;//0.1/MSPF; | ||
+ | |||
+ | var BACKGROUNDCOLOR = "MidnightBlue"; | ||
+ | |||
+ | /* AI Variables */ | ||
+ | var AIPLAYERSEXIST = true; | ||
+ | var AISTARTSPAWN = 50; | ||
+ | var AIPROXIMITY = 500; | ||
+ | </script> | ||
+ | |||
+ | <script type="text/JavaScript"> //cells | ||
+ | var _cells = new Array(); | ||
+ | var _cellCount = 0; | ||
+ | var _touchPadding = 15; | ||
+ | |||
+ | function getRandomLocationOnBoard(){ | ||
+ | return [Math.round(Math.random()*(BOUNDARIES[0]-2*STARTRADIUS)+STARTRADIUS), | ||
+ | Math.round(Math.random()*(BOUNDARIES[1]-2*STARTRADIUS)+STARTRADIUS)]; | ||
+ | } | ||
+ | |||
+ | function getRandomCell(){ | ||
+ | var num = Math.floor(Math.random()*CELLIMAGELOCATION.length); | ||
+ | return CELLIMAGELOCATION[num]; | ||
+ | } | ||
+ | |||
+ | function Cell(isComputer, name){ | ||
+ | this.radius = STARTRADIUS; | ||
+ | this.center = getRandomLocationOnBoard(); | ||
+ | this.speed = STARTSPEED; | ||
+ | this.isComputer = isComputer; | ||
+ | this.name = name; | ||
+ | this.movementVector = [0,0]; | ||
+ | this.luminescence = this.radius+STARTLUMINANCE; | ||
+ | this.children = new Array(); | ||
+ | this.parent = -1; | ||
+ | this.moveImageTo = | ||
+ | function(cx,cy){ | ||
+ | if(this.name != "mainPlayer"){ | ||
+ | var player = getMyCell(); | ||
+ | var left = (this.center[0]-this.radius)-(player.center[0]-width/2); | ||
+ | var top = (this.center[1]-this.radius)-(player.center[1]-height/2); | ||
+ | this.object.style.left=left+"px"; | ||
+ | this.object.style.top=top+"px"; | ||
+ | }else{ | ||
+ | var left = (width/2-this.radius); | ||
+ | var top = (height/2-this.radius); | ||
+ | this.object.style.left=left+"px"; | ||
+ | this.object.style.top=top+"px"; | ||
+ | updateDarkness(this); | ||
+ | } | ||
+ | }; | ||
+ | this.spawnCell = | ||
+ | function(){ | ||
+ | var newImage = document.createElement("img"); | ||
+ | document.getElementById("gameWrapper").appendChild(newImage); | ||
+ | newImage.setAttribute('src',CELLIMAGELOCATION[0]); | ||
+ | newImage.setAttribute('id',this.name); | ||
+ | newImage.style.position="absolute"; | ||
+ | newImage.style.width=(this.radius*2)+"px"; | ||
+ | newImage.style.height=(this.radius*2)+"px"; | ||
+ | var temp = Math.round(this.radius-2); | ||
+ | newImage.style.zIndex = temp.toString(); | ||
+ | this.object = newImage; | ||
+ | if(this.name=="mainPlayer"){ | ||
+ | newImage.style.top = (width/2-this.radius)+"px"; | ||
+ | newImage.style.left = (height/2-this.radius)+"px"; | ||
+ | }else{ | ||
+ | this.moveImageTo(this.center[0],this.center[1]); | ||
+ | } | ||
+ | _cellCount ++; | ||
+ | _cells.push(this); | ||
+ | }; | ||
+ | this.distance = | ||
+ | function(thing){ //works with cells and food | ||
+ | var r1 = this.radius; | ||
+ | var r2 = thing.radius; | ||
+ | var c1 = this.center; | ||
+ | var c2 = thing.center; | ||
+ | var dist = Math.sqrt((c1[0]-c2[0])*(c1[0]-c2[0])+(c1[1]-c2[1])*(c1[1]-c2[1])); | ||
+ | return dist; | ||
+ | }; | ||
+ | this.isTouching = | ||
+ | function(thing){ //works with cells and food | ||
+ | return (this.distance(thing)<this.radius+thing.radius+_touchPadding); | ||
+ | }; | ||
+ | this.split = | ||
+ | function(){ | ||
+ | if(this.radius>MINSPLITRADIUS){ | ||
+ | var r1=((Math.random()-0.5)*2*SPLITRADIUS),r2=((Math.random()-0.5)*2*SPLITRADIUS), | ||
+ | r3=((Math.random()-0.5)*2*SPLITRADIUS),r4=((Math.random()-0.5)*2*SPLITRADIUS); | ||
+ | |||
+ | var newCell = new Cell(false,this.name); | ||
+ | newCell.spawnCell(); | ||
+ | newCell.resize(this.radius/2); | ||
+ | this.resize(this.radius/2); | ||
+ | if(this.parent == -1){ | ||
+ | newCell.parent = this; | ||
+ | }else{ | ||
+ | newCell.parent = this.parent; | ||
+ | } | ||
+ | this.children.push(newCell); | ||
+ | |||
+ | this.updateVector(this.center[0]+r1,this.center[1]+r2); | ||
+ | newCell.updateVector(newCell.center[0]+r3,newCell.center[1]+r4); | ||
+ | this.move(); | ||
+ | newCell.move(); | ||
+ | |||
+ | } | ||
+ | }; | ||
+ | this.resize = | ||
+ | function(newRadius){ | ||
+ | this.radius = newRadius; | ||
+ | this.object.style.width = (this.radius*2)+"px"; | ||
+ | this.object.style.height = (this.radius*2)+"px"; | ||
+ | this.moveImageTo(this.center[0],this.center[1]); | ||
+ | var temp = Math.round(this.radius-2); | ||
+ | this.object.style.zIndex = temp.toString(); | ||
+ | temp = Math.round(this.radius+2); | ||
+ | this.speed = Math.round(STARTSPEED*MSPF/33-this.radius/(STARTSPEED*MSPF/33)+this.radius*this.radius/60000)*33/MSPF; | ||
+ | }; | ||
+ | this.destroy = | ||
+ | function(){ | ||
+ | //alert(this.name + " was eaten!"); | ||
+ | if(this.object==undefined){ return;} | ||
+ | |||
+ | if(this.isComputer && this.children.length==0 && this.parent == -1){ | ||
+ | spawnAIComputer(); | ||
+ | } | ||
+ | |||
+ | this.object.parentNode.removeChild(this.object); | ||
+ | delete this.object; | ||
+ | if(DISPLAYNAMES){ | ||
+ | this.text.parentNode.removeChild(this.text); | ||
+ | delete this.text; | ||
+ | } | ||
+ | |||
+ | _cellCount--; | ||
+ | |||
+ | if(this.children.length!=0){ | ||
+ | var child = -1; | ||
+ | for(var i=0;i<this.children.length;i++){ | ||
+ | if(this.children[i].object!=undefined){ | ||
+ | var last = this.children[this.children.length-1]; | ||
+ | child = this.children[i]; //Buggy what if child is null | ||
+ | this.children[this.children.length-1]=child; | ||
+ | this.children[i]=last; | ||
+ | this.children.length-=1; | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | if(child == -1){ | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | this.radius = child.radius; | ||
+ | this.center = child.center; | ||
+ | this.speed = child.speed; | ||
+ | this.luminescence = child.luminescence; | ||
+ | this.object = child.object; | ||
+ | if(DISPLAYNAMES){this.text = child.text;} | ||
+ | this.parent = -1; | ||
+ | |||
+ | for(var i=0;i<this.children.length;i++){ | ||
+ | this.children[i].parent = this; | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | this.tryToCollectSubstrate = | ||
+ | function(){ | ||
+ | var substrates = Substrate.GetSubstrates(); | ||
+ | for(var i=0;i<substrates.length;i++){ | ||
+ | if(substrates[i].object!=undefined && this.isTouching(substrates[i])){ | ||
+ | this.luminescence += SUBSTRATEVALUE; | ||
+ | if(this.luminescence > MAXLUMINANCE){ | ||
+ | this.luminescence = MAXLUMINANCE; | ||
+ | } | ||
+ | substrates[i].destroy(); | ||
+ | } | ||
+ | } | ||
+ | if(this.luminescence>STARTLUMINANCE+this.radius){ | ||
+ | this.luminescence -= LIGHTDECREASERATE; | ||
+ | } | ||
+ | }; | ||
+ | this.tryToEatFood = | ||
+ | function(){ | ||
+ | var foods = Food.GetFood(); | ||
+ | for(var i=0;i<foods.length;i++){ | ||
+ | if(foods[i].object!=undefined && this.isTouching(foods[i])){ | ||
+ | this.resize(this.radius+foods[i].radius/2); | ||
+ | foods[i].destroy(); | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | this.tryToEat = //NOTE: could optimize by checking both ways only i>curNum | ||
+ | function(){ | ||
+ | var ateSomething = true; | ||
+ | while(ateSomething == true){ | ||
+ | ateSomething = false; | ||
+ | for(var i=0;i<_cells.length;i++){ | ||
+ | var curCell = _cells[i]; | ||
+ | if(curCell != this){ | ||
+ | if(curCell.object!=undefined){ | ||
+ | for(var j=0;j<curCell.children;j++){ | ||
+ | if(this.isTouching(curCell.children[j]) && this.distance(curCell.children[j])<this.radius){ | ||
+ | if(curCell.children[j].radius<this.radius*EATINGRATIO){ | ||
+ | ateSomething = true; | ||
+ | this.resize(this.radius+curCell.children[j]/2); | ||
+ | curCell.children[j].destroy(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | if(this.isTouching(curCell) && this.distance(curCell)<this.radius){ | ||
+ | if(curCell.radius<this.radius*EATINGRATIO){ | ||
+ | ateSomething = true; | ||
+ | this.resize(this.radius+curCell.radius/2); | ||
+ | curCell.destroy(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | this.tryToEatFood(); | ||
+ | this.tryToCollectSubstrate(); | ||
+ | }; | ||
+ | this.checkSpikes = | ||
+ | function(){ | ||
+ | var spikes = Spike.GetSpikes(); | ||
+ | for(var i=0;i<spikes.length;i++){ | ||
+ | if(spikes[i].object!=undefined && this.radius>spikes[i].radius*1.5 && this.isTouching(spikes[i])){ | ||
+ | this.split(); | ||
+ | spikes[i].destroy(); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | this.updateVector = | ||
+ | function(xpos,ypos){ | ||
+ | var c = this.center; | ||
+ | var xcomp = xpos-c[0]; | ||
+ | var ycomp = ypos-c[1]; | ||
+ | var mag = Math.sqrt(xcomp*xcomp+ycomp*ycomp); | ||
+ | if(mag==0){ | ||
+ | this.movementVector = [0,0]; | ||
+ | }else{ | ||
+ | this.movementVector = [xcomp/mag,ycomp/mag]; | ||
+ | } | ||
+ | }; | ||
+ | this.move = | ||
+ | function(){ | ||
+ | var right = this.movementVector[0]*this.speed; | ||
+ | var down = this.movementVector[1]*this.speed; | ||
+ | if(this.center[0]-this.radius+right<0){ | ||
+ | this.center[0]=this.radius; | ||
+ | }else if(this.center[0]+this.radius+right>BOUNDARIES[0]){ | ||
+ | this.center[0]=BOUNDARIES[0]-this.radius; | ||
+ | }else{ | ||
+ | this.center[0]+=right; | ||
+ | } | ||
+ | if(this.center[1]-this.radius+down<0){ | ||
+ | this.center[1]=this.radius; | ||
+ | }else if(this.center[1]+this.radius+down>BOUNDARIES[1]){ | ||
+ | this.center[1]=BOUNDARIES[1]-this.radius; | ||
+ | }else{ | ||
+ | this.center[1]+=down; | ||
+ | } | ||
+ | this.moveImageTo(this.center[0],this.center[1]); | ||
+ | this.tryToEat(); | ||
+ | }; | ||
+ | this.enemyMovementAI = | ||
+ | function(){ | ||
+ | var prey = -1; | ||
+ | var gottaRun = [0,0]; | ||
+ | var sight = this.luminescence; // radius of sight | ||
+ | var proximity = AIPROXIMITY; | ||
+ | if(AIPROXIMITY>this.luminescence){ | ||
+ | proximity = this.luminescence; | ||
+ | } | ||
+ | for (var i=0;i<_cells.length;i++){ //look for other cells as prey | ||
+ | var curCell = _cells[i]; | ||
+ | if(sight>proximity){ //if something is in proximity do immediately (else look for better) | ||
+ | for(var j=0;j<curCell.children.length;j++){ | ||
+ | if(curCell.children[j] != this){ | ||
+ | if(curCell.children[j].object!=undefined && | ||
+ | curCell.children[j].radius<this.radius*EATINGRATIO && this.distance(curCell.children[j])<sight){ | ||
+ | prey = curCell.children[j]; | ||
+ | sight = this.distance(prey); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | if(curCell != this){ | ||
+ | if(curCell.object!=undefined && curCell.radius<this.radius*EATINGRATIO && this.distance(curCell)<sight){ | ||
+ | prey = curCell; | ||
+ | sight = this.distance(prey); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | if(curCell.object!=undefined && curCell.size*EATINGRATIO>this.size && this.distance(curCell)<this.radius*5){ //this cell can eat me and is close | ||
+ | var difference = [curCell.center[0]-this.center[0],curCell.center[1]-this.center[1]]; | ||
+ | gottaRun[0] += difference[0]; | ||
+ | gottRun[0] += difference[1]; | ||
+ | } | ||
+ | } | ||
+ | if(gottaRun[0]!=0 || gottaRun[1]!=0){ | ||
+ | this.updateVector(this.center[0]-gottaRun[0],this.center[1]-gottaRun[1]); | ||
+ | }else{ | ||
+ | if(prey != -1){ //if prey found, chase it. | ||
+ | this.updateVector(prey.center[0],prey.center[1]); | ||
+ | }else{ | ||
+ | var food = -1; | ||
+ | var foods = Food.GetFood(); | ||
+ | sight = this.luminescence; //reset line of sight | ||
+ | proximity = AIPROXIMITY; | ||
+ | if(AIPROXIMITY>this.luminescence){ | ||
+ | proximity = this.luminescence; | ||
+ | } | ||
+ | for (i=0;i<foods.length;i++){ //look for food | ||
+ | if(sight>proximity){ //if something is in proximity do immediately (else look for better) | ||
+ | var curFood = foods[i]; | ||
+ | if(curFood!=undefined && this.distance(curFood)<sight){ | ||
+ | food = curFood; | ||
+ | sight = this.distance(curFood); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | if(food != -1){ //if food found, go to it. | ||
+ | this.updateVector(food.center[0],food.center[1]); | ||
+ | }else{ | ||
+ | var substrate = -1; | ||
+ | var substrates = Substrate.GetSubstrates(); | ||
+ | sight = this.luminescence; //reset line of sight | ||
+ | proximity = AIPROXIMITY; | ||
+ | if(AIPROXIMITY>this.luminescence){ | ||
+ | proximity = this.luminescence; | ||
+ | } | ||
+ | for (i=0;i<substrates.length;i++){ //look for food | ||
+ | if(sight>proximity){ //if something is in proximity do immediately (else look for better) | ||
+ | var curSubstrate = substrates[i]; | ||
+ | if(curSubstrate!=undefined && this.distance(curSubstrate)<sight){ | ||
+ | substrate = curSubstrate; | ||
+ | sight = this.distance(curSubstrate); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | if(substrate != -1){ //if food found, go to it. | ||
+ | this.updateVector(substrate.center[0],substrate.center[1]); | ||
+ | }else{ //literally nothing to do. Move randomly in panic. | ||
+ | this.updateVector(this.center[0]+Math.round(this.speed*(Math.random()-0.5)*2), | ||
+ | this.center[1]+Math.round(this.speed*(Math.random()-0.5)*2)); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | this.move(); | ||
+ | }; | ||
+ | } | ||
+ | |||
+ | Cell.GarbageCollect = function(){ | ||
+ | var i=0; | ||
+ | while(i<_cells.length){ | ||
+ | if(_cells[i].object == undefined){ //cell is dead | ||
+ | var last = _cells[_cells.length-1]; | ||
+ | _cells[_cells.length-1] = _cells[i]; | ||
+ | _cells[i] = last; | ||
+ | _cells.length -= 1; | ||
+ | }else{ | ||
+ | var c=0; | ||
+ | while(c<_cells[i].children.length){ | ||
+ | if(_cells[i].children[c].object == undefined){ | ||
+ | var last = _cells[i].children[_cells.length-1]; | ||
+ | _cells[i].children[_cells.length-1] = _cells[i].children[i]; | ||
+ | _cells[i].children[i] = last; | ||
+ | _cells[i].children.length -= 1; | ||
+ | }else{ | ||
+ | c++; | ||
+ | } | ||
+ | } | ||
+ | i++; | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | </script> | ||
+ | |||
+ | <script type="text/JavaScript"> //objects | ||
+ | var _foods = new Array(); | ||
+ | var _foodCount = 0; | ||
+ | |||
+ | var _substrates = new Array(); | ||
+ | var _substrateCount = 0; | ||
+ | |||
+ | var _spikes = new Array(); | ||
+ | var _spikeCount = 0; | ||
+ | |||
+ | function Food(center,color){ | ||
+ | this.size = FOODSIZE; | ||
+ | this.center = center; | ||
+ | this.color = color; | ||
+ | this.radius = FOODSIZE/2; | ||
+ | |||
+ | this.spawn = | ||
+ | function(){ | ||
+ | var square = document.createElement("div"); | ||
+ | square.setAttribute('id',"food"); | ||
+ | square.style.position="absolute"; | ||
+ | square.style.width=this.size+"px"; | ||
+ | square.style.height=this.size+"px"; | ||
+ | square.style.backgroundColor=this.color; | ||
+ | square.style.left=(this.center[0]-this.radius)+"px"; | ||
+ | square.style.top=(this.center[1]-this.radius)+"px"; | ||
+ | square.style.zIndex = this.radius.toString(); | ||
+ | document.getElementById("gameWrapper").appendChild(square); | ||
+ | this.object = square; | ||
+ | }; | ||
+ | this.destroy = | ||
+ | function(){ | ||
+ | this.object.parentNode.removeChild(this.object); | ||
+ | delete this.object; // makes this.object = undefined | ||
+ | _foodCount--; | ||
+ | }; | ||
+ | this.updatePosition = | ||
+ | function(){ | ||
+ | var player = getMyCell(); | ||
+ | var left = (this.center[0]-this.radius)-(player.center[0]-width/2); | ||
+ | var top = (this.center[1]-this.radius)-(player.center[1]-height/2); | ||
+ | this.object.style.left=left+"px"; | ||
+ | this.object.style.top=top+"px"; | ||
+ | }; | ||
+ | } | ||
+ | Food.GarbageCollect = function(){ | ||
+ | var i=0; | ||
+ | while(i<_foods.length){ | ||
+ | if(_foods[i].object==undefined){ // food has been eaten | ||
+ | var last = _foods[_foods.length-1]; | ||
+ | _foods[_foods.length-1] = _foods[i]; | ||
+ | _foods[i] = last; | ||
+ | _foods.length -= 1; | ||
+ | }else{ | ||
+ | i++; | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | Food.SpawnFood = function(amount){ | ||
+ | for(var i=0;i<amount;i++){ | ||
+ | var color = "rgb("+(Math.round(Math.random()*256))+","+(Math.round(Math.random()*256))+","+(Math.round(Math.random()*256))+")"; | ||
+ | var xpos = Math.round(Math.random()*(BOUNDARIES[0]-FOODSIZE)+FOODSIZE/2); | ||
+ | var ypos = Math.round(Math.random()*(BOUNDARIES[1]-FOODSIZE)+FOODSIZE/2); | ||
+ | var food = new Food([xpos,ypos],color); | ||
+ | food.spawn(); | ||
+ | _foods.push(food); | ||
+ | _foodCount++; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | Food.GetFood = function(){ | ||
+ | return _foods; | ||
+ | }; | ||
+ | |||
+ | |||
+ | function Substrate(center){ //([intx,inty]) | ||
+ | this.size = SUBSTRATESIZE; | ||
+ | this.center = center; | ||
+ | this.radius = SUBSTRATESIZE/4; //just the way the source image is | ||
+ | |||
+ | this.spawn = | ||
+ | function(){ | ||
+ | var newImage = document.createElement("img"); | ||
+ | newImage.setAttribute('src',SUBSTRATEIMAGELOCATION); | ||
+ | newImage.setAttribute('id',"substrate"); | ||
+ | newImage.style.position="absolute"; | ||
+ | newImage.style.left=(this.center[0]-this.size/2)+"px"; | ||
+ | newImage.style.top=(this.center[1]-this.size/2)+"px"; | ||
+ | newImage.style.width=this.size+"px"; | ||
+ | newImage.style.height=this.size+"px"; | ||
+ | newImage.style.zIndex = this.radius.toString(); | ||
+ | document.getElementById("gameWrapper").appendChild(newImage); | ||
+ | this.object = newImage; | ||
+ | }; | ||
+ | this.destroy = | ||
+ | function(){ | ||
+ | this.object.parentNode.removeChild(this.object); | ||
+ | delete this.object; // makes this.object = undefined | ||
+ | _substrateCount--; | ||
+ | }; | ||
+ | this.updatePosition = | ||
+ | function(){ | ||
+ | var player = getMyCell(); | ||
+ | var left = (this.center[0]-this.radius)-(player.center[0]-width/2); | ||
+ | var top = (this.center[1]-this.radius)-(player.center[1]-height/2); | ||
+ | this.object.style.left=left+"px"; | ||
+ | this.object.style.top=top+"px"; | ||
+ | }; | ||
+ | } | ||
+ | Substrate.GarbageCollect = function(){ | ||
+ | var i=0; | ||
+ | while(i<_substrates.length){ | ||
+ | if(_substrates[i].object==undefined){ // food has been eaten | ||
+ | var last = _substrates[_substrates.length-1]; | ||
+ | _substrates[_substrates.length-1] = _substrates[i]; | ||
+ | _substrates[i] = last; | ||
+ | _substrates.length -= 1; | ||
+ | }else{ | ||
+ | i++; | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | Substrate.SpawnSubstrates = function(amount){ | ||
+ | for(var i=0;i<amount;i++){ | ||
+ | var xpos = Math.round(Math.random()*(BOUNDARIES[0]-SUBSTRATESIZE)+SUBSTRATESIZE/2); | ||
+ | var ypos = Math.round(Math.random()*(BOUNDARIES[1]-SUBSTRATESIZE)+SUBSTRATESIZE/2); | ||
+ | var substrate = new Substrate([xpos,ypos]); | ||
+ | substrate.spawn(); | ||
+ | _substrates.push(substrate); | ||
+ | _substrateCount++; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | Substrate.GetSubstrates = function(){ | ||
+ | return _substrates; | ||
+ | }; | ||
+ | |||
+ | |||
+ | function Spike(center){ //([intx,inty]) | ||
+ | this.size = SPIKESIZE; | ||
+ | this.center = center; | ||
+ | this.radius = SPIKESIZE/2; | ||
+ | |||
+ | this.spawn = | ||
+ | function(){ | ||
+ | var newImage = document.createElement("img"); | ||
+ | newImage.setAttribute('src',SPIKEIMAGELOCATION); | ||
+ | newImage.setAttribute('id',"spike"); | ||
+ | newImage.style.position="absolute"; | ||
+ | newImage.style.left=(this.center[0]-this.size/2)+"px"; | ||
+ | newImage.style.top=(this.center[1]-this.size/2)+"px"; | ||
+ | newImage.style.width=this.size+"px"; | ||
+ | newImage.style.height=this.size+"px"; | ||
+ | newImage.style.zIndex = "1000000"; | ||
+ | document.getElementById("gameWrapper").appendChild(newImage); | ||
+ | this.object = newImage; | ||
+ | }; | ||
+ | this.destroy = | ||
+ | function(){ | ||
+ | this.object.parentNode.removeChild(this.object); | ||
+ | delete this.object; // makes this.object = undefined | ||
+ | _spikeCount--; | ||
+ | }; | ||
+ | this.updatePosition = | ||
+ | function(){ | ||
+ | var player = getMyCell(); | ||
+ | var left = (this.center[0]-this.radius)-(player.center[0]-width/2); | ||
+ | var top = (this.center[1]-this.radius)-(player.center[1]-height/2); | ||
+ | this.object.style.left=left+"px"; | ||
+ | this.object.style.top=top+"px"; | ||
+ | }; | ||
+ | } | ||
+ | Spike.GarbageCollect = function(){ | ||
+ | var i=0; | ||
+ | while(i<_spikes.length){ | ||
+ | if(_spikes[i].object==undefined){ // food has been eaten | ||
+ | var last = _spikes[_spikes.length-1]; | ||
+ | _spikes[_spikes.length-1] = _spikes[i]; | ||
+ | _spikes[i] = last; | ||
+ | _spikes.length -= 1; | ||
+ | }else{ | ||
+ | i++; | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | Spike.SpawnSpikes = function(amount){ | ||
+ | for(var i=0;i<amount;i++){ | ||
+ | var xpos = Math.round(Math.random()*(BOUNDARIES[0]-SPIKESIZE)+SPIKESIZE/2); | ||
+ | var ypos = Math.round(Math.random()*(BOUNDARIES[1]-SPIKESIZE)+SPIKESIZE/2); | ||
+ | var spike = new Spike([xpos,ypos]); | ||
+ | spike.spawn(); | ||
+ | _spikes.push(spike); | ||
+ | _spikeCount++; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | Spike.GetSpikes = function(){ | ||
+ | return _spikes; | ||
+ | }; | ||
+ | |||
+ | </script> | ||
+ | |||
+ | <script type="text/JavaScript"> //Darkness | ||
+ | var _darkness; | ||
+ | var _darkPadding = 500; | ||
+ | |||
+ | function makeBlackSquare(width,height,top,left){ | ||
+ | if(width<0){width=0;} | ||
+ | if(height<0){height=0;} | ||
+ | var square = document.createElement("div"); | ||
+ | square.setAttribute('id',"darkness"); | ||
+ | square.style.position="absolute"; | ||
+ | square.style.width=width+"px"; | ||
+ | square.style.height=height+"px"; | ||
+ | square.style.backgroundColor="black"; | ||
+ | square.style.left=left+"px"; | ||
+ | square.style.top=top+"px"; | ||
+ | square.style.zIndex = "10000000000000000"; | ||
+ | document.getElementById("gameWrapper").appendChild(square); | ||
+ | return square; | ||
+ | } | ||
+ | |||
+ | function updateBlackSquare(square,width,height,top,left){ | ||
+ | if(width<0){width=0;} | ||
+ | if(height<0){height=0;} | ||
+ | square.style.width=width+"px"; | ||
+ | square.style.height=height+"px"; | ||
+ | square.style.left=left+"px"; | ||
+ | square.style.top=top+"px"; | ||
+ | } | ||
+ | |||
+ | function createDarkness(cell){ | ||
+ | var L = cell.luminescence; | ||
+ | |||
+ | var top = makeBlackSquare(width,height/2-cell.radius-L,0,0); | ||
+ | var bottom = makeBlackSquare(width,height/2-cell.radius-L,height/2+cell.radius+L,0); | ||
+ | var left = makeBlackSquare(width/2-cell.radius-L,height,0,0); | ||
+ | var right = makeBlackSquare(width/2-cell.radius-L,height,0,width/2+cell.radius+L); | ||
+ | |||
+ | _darkness = [top,bottom,left,right]; | ||
+ | } | ||
+ | |||
+ | function updateDarkness(cell){ | ||
+ | var L = cell.luminescence; | ||
+ | var top = _darkness[0], bottom = _darkness[1], left = _darkness[2], right = _darkness[3]; | ||
+ | updateBlackSquare(top,width,height/2-cell.radius-L,0,0); | ||
+ | updateBlackSquare(bottom,width,height/2-cell.radius-L,height/2+cell.radius+L,0); | ||
+ | updateBlackSquare(left,width/2-cell.radius-L,height,0,0); | ||
+ | updateBlackSquare(right,width/2-cell.radius-L,height,0,width/2+cell.radius+L); | ||
+ | } | ||
+ | </script> | ||
+ | |||
+ | <script type="text/JavaScript"> //Main | ||
+ | var _mouseX=-1, _mouseY=-1; | ||
+ | var _myCell; | ||
+ | var _div; | ||
+ | var width,height; | ||
+ | var top=-1, left=-1; | ||
+ | var _computers= new Array(); | ||
+ | var _compNum=0; | ||
+ | var _isPaused = false; | ||
+ | |||
+ | function pause(){ | ||
+ | _isPaused = !(_isPaused); | ||
+ | } | ||
+ | |||
+ | function gameOver(){ | ||
+ | alert("Game Over!!"); | ||
+ | restart(); | ||
+ | } | ||
+ | |||
+ | /* start of AI code. should be on server */ | ||
+ | function updateComputerPlayers(){ | ||
+ | for(var i=0;i<_computers.length;i++){ | ||
+ | var computer = _computers[i]; | ||
+ | if(computer!=undefined && computer.object!=undefined){ | ||
+ | computer.enemyMovementAI(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function spawnAIComputer(){ | ||
+ | var comp = new Cell(true,"computer"+_compNum.toString()); | ||
+ | comp.spawnCell(); | ||
+ | _computers.push(comp); | ||
+ | _compNum++; | ||
+ | } | ||
+ | |||
+ | function spawnAI(){ | ||
+ | if(AIPLAYERSEXIST){ | ||
+ | for(var i=0;i<AISTARTSPAWN;i++){ | ||
+ | spawnAIComputer(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function garbageCollectAI(){ | ||
+ | var i=0; | ||
+ | while(i<_computers.length){ | ||
+ | if(_computers[i].object == undefined){ //cell is dead | ||
+ | var last = _computers[_computers.length-1]; | ||
+ | _computers[_computers.length-1] = _computers[i]; | ||
+ | _computers[i] = last; | ||
+ | _computers.length -= 1; | ||
+ | }else{ | ||
+ | i++; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /* End of AI code. should be on server */ | ||
+ | |||
+ | |||
+ | function updateMouse(e){ ///doesn't work | ||
+ | _mouseX = (e.clientX+window.pageXOffset-document.getElementById("gameWrapper").offsetLeft); | ||
+ | _mouseY = (e.clientY+window.pageYOffset-document.getElementById("gameWrapper").offsetTop); | ||
+ | } | ||
+ | |||
+ | function getMouseLocation(){ | ||
+ | return [_mouseX,_mouseY]; | ||
+ | } | ||
+ | |||
+ | function eventsList(event){ | ||
+ | if(event.keyCode == 69){ //spawn enemy ('e') | ||
+ | spawnAIComputer(); | ||
+ | } | ||
+ | if(event.keyCode == 70){ //spawn food ('f') | ||
+ | Food.SpawnFood(1); | ||
+ | } | ||
+ | if(event.keyCode == 80){ //pause game ('p') | ||
+ | pause(); | ||
+ | } | ||
+ | if(event.keyCode == 82){ | ||
+ | restart(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function bindEvents(){ | ||
+ | document.onmousemove = updateMouse; | ||
+ | document.addEventListener('keydown', eventsList); | ||
+ | } | ||
+ | |||
+ | function updateRelative(){ | ||
+ | var bx=_myCell.center[0]-width/2,by=_myCell.center[1]-height/2; | ||
+ | _div.style.top=(-by)+"px"; | ||
+ | _div.style.left=(-bx)+"px"; | ||
+ | } | ||
+ | |||
+ | function updateDisplay(){ | ||
+ | var foods = Food.GetFood(); | ||
+ | var substrates = Substrate.GetSubstrates(); | ||
+ | var spikes = Spike.GetSpikes(); | ||
+ | for(var i=0;i<foods.length;i++){foods[i].updatePosition();} | ||
+ | for(var i=0;i<substrates.length;i++){substrates[i].updatePosition();} | ||
+ | for(var i=0;i<spikes.length;i++){spikes[i].updatePosition();} | ||
+ | updateRelative(); | ||
+ | } | ||
+ | |||
+ | function gameLoop(){ | ||
+ | if(!_isPaused){ | ||
+ | if(_myCell.object==undefined){ | ||
+ | gameOver(); | ||
+ | }else{ | ||
+ | var mouse = getMouseLocation(); //NOTE: Only works if mouse is moving | ||
+ | if(mouse[0]!=-1){ | ||
+ | _myCell.updateVector(mouse[0]+(_myCell.center[0]-width/2),mouse[1]+(_myCell.center[1]-height/2)); | ||
+ | _myCell.move(); | ||
+ | } | ||
+ | } | ||
+ | if(AIPLAYERSEXIST){ | ||
+ | updateComputerPlayers(); | ||
+ | } | ||
+ | //Garbage Collection | ||
+ | Food.GarbageCollect(); | ||
+ | Cell.GarbageCollect(); | ||
+ | garbageCollectAI(); | ||
+ | Substrate.GarbageCollect(); | ||
+ | //end of garbage collection | ||
+ | Food.SpawnFood(FOODSPAWNRATE); | ||
+ | Substrate.SpawnSubstrates(SUBSTRATESPAWNRATE); | ||
+ | Spike.SpawnSpikes(SPIKESPAWNRATE); | ||
+ | updateDisplay(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function getMyCell(){ | ||
+ | return _myCell; | ||
+ | } | ||
+ | |||
+ | function getPlayerLocation(){ | ||
+ | return _myCell.center; | ||
+ | } | ||
+ | |||
+ | function restart(){ | ||
+ | var name = window.prompt("what is your cell's name?",""); | ||
+ | _myCell = new Cell(false, name); //NOT a computer | ||
+ | _myCell.spawnCell(); | ||
+ | updateDarkness(_myCell); | ||
+ | } | ||
+ | |||
+ | function main(){ | ||
+ | //make border and boundaries; | ||
+ | var gameWrapper = document.getElementById("gameWrapper"); | ||
+ | width=gameWrapper.offsetWidth; | ||
+ | height=gameWrapper.offsetHeight; | ||
+ | _div = document.createElement("div"); | ||
+ | gameWrapper.appendChild(_div); | ||
+ | _div.setAttribute('id',"boundaries"); | ||
+ | _div.style.position="relative"; | ||
+ | _div.style.width=(BOUNDARIES[0])+"px"; | ||
+ | _div.style.height=(BOUNDARIES[1])+"px"; | ||
+ | _div.style.outline = "#FF0000 dotted thick"; | ||
+ | bindEvents(); | ||
+ | |||
+ | _myCell = new Cell(false, "mainPlayer"); //NOT a computer | ||
+ | _myCell.spawnCell(); | ||
+ | createDarkness(_myCell); | ||
+ | updateDarkness(_myCell); | ||
+ | |||
+ | /*server code*/ | ||
+ | spawnAI(); | ||
+ | Food.SpawnFood(FOODSTARTSPAWN); | ||
+ | Substrate.SpawnSubstrates(SUBSTRATESTARTSPAWN); | ||
+ | Spike.SpawnSpikes(SPIKESTARTSPAWN); | ||
+ | /*end server */ | ||
+ | setInterval(gameLoop, MSPF); | ||
+ | } | ||
+ | </script> | ||
+ | </head> | ||
+ | |||
+ | <body> | ||
+ | <div id="gameWrapper" onclick="main();" style="width:400px; height:400px; position:absolute; background-color:MidnightBlue;overflow:hidden;border-style:outset;border-width:10px;border-color:green"/> | ||
+ | </body> | ||
</html> | </html> |
Revision as of 14:09, 29 June 2015