Created
August 28, 2014 14:52
-
-
Save DavidOldAccount/b364863c87ac6b7762a5 to your computer and use it in GitHub Desktop.
GeoBlasterGame HTML5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>GeoBlaster</title> | |
<script type="text/javascript"> | |
window.addEventListener('load', eventWindowLoaded, false); | |
function eventWindowLoaded() { | |
canvasApp(); | |
} | |
function canvasApp(){ | |
var theCanvas = document.getElementById('canvas'); | |
if (!theCanvas || !theCanvas.getContext) { | |
return; | |
} | |
var context = theCanvas.getContext('2d'); | |
if (!context) { | |
return; | |
} | |
//application states | |
const GAME_STATE_TITLE=0; | |
const GAME_STATE_NEW_GAME=1; | |
const GAME_STATE_NEW_LEVEL=2; | |
const GAME_STATE_PLAYER_START=3; | |
const GAME_STATE_PLAY_LEVEL=4; | |
const GAME_STATE_PLAYER_DIE=5; | |
const GAME_STATE_GAME_OVER=6; | |
var currentGameState=0; | |
var currentGameStateFunction=null; | |
//title screen | |
var titleStarted=false; | |
//gameover screen | |
var gameOverStarted=false; | |
//objects for game play | |
//game environment | |
var score=0; | |
var level=0; | |
var extraShipAtEach=10000; | |
var extraShipsEarned=0; | |
var playerShips=5; | |
//playfield | |
var xMin=0; | |
var xMax=500; | |
var yMin=0; | |
var yMax=800; | |
//score values | |
var bigRockScore=50; | |
var medRockScore=75; | |
var smlRockScore=100; | |
var saucerScore=300; | |
//rock scale constants | |
const ROCK_SCALE_LARGE=3; | |
const ROCK_SCALE_MEDIUM=4; | |
const ROCK_SCALE_SMALL=5; | |
//create game objects and arrays | |
var player={}; | |
var rocks=[]; | |
var saucers=[]; | |
var playerMissiles=[]; | |
var particles=[] | |
var saucerMissiles=[]; | |
//level specific | |
var levelRockMaxSpeedAdjust=1; | |
var levelSaucerMax = 20; | |
var levelSaucerOccurenceRate=25; //this will be multiplied by the level and a max can be se | |
var levelSaucerSpeed=5; | |
var levelSaucerFireDelay=300; | |
var levelSaucerFireRate=100; | |
var levelSaucerMissileSpeed=10; | |
//keyPresses | |
var keyPressList=[]; | |
function runGame(){ | |
currentGameStateFunction(); | |
} | |
function switchGameState(newState) { | |
currentGameState=newState; | |
switch (currentGameState) { | |
case GAME_STATE_TITLE: | |
currentGameStateFunction=gameStateTitle; | |
break; | |
case GAME_STATE_NEW_GAME: | |
currentGameStateFunction=gameStateNewGame; | |
break; | |
case GAME_STATE_NEW_LEVEL: | |
currentGameStateFunction=gameStateNewLevel; | |
break; | |
case GAME_STATE_PLAYER_START: | |
currentGameStateFunction=gameStatePlayerStart; | |
break; | |
case GAME_STATE_PLAY_LEVEL: | |
currentGameStateFunction=gameStatePlayLevel; | |
break; | |
case GAME_STATE_PLAYER_DIE: | |
currentGameStateFunction=gameStatePlayerDie; | |
break; | |
case GAME_STATE_GAME_OVER: | |
currentGameStateFunction=gameStateGameOver; | |
break; | |
} | |
} | |
function gameStateTitle() { | |
if (titleStarted !=true){ | |
fillBackground(); | |
setTextStyle(); | |
context.fillText ("Shoot the rocks and saucers by superLaser!!", 150, 75); | |
context.fillText ("Press Space To Start!!", 120, 140); | |
titleStarted=true; | |
}else{ | |
//wait for space key click | |
if (keyPressList[32]==true){ | |
//ConsoleLog.log("space pressed"); | |
switchGameState(GAME_STATE_NEW_GAME); | |
titleStarted=false; | |
} | |
} | |
} | |
function gameStateNewGame(){ | |
//ConsoleLog.log("gameStateNewGame") | |
//setup new game | |
level=0; | |
score=0; | |
playerShips=3; | |
player.maxVelocity=5; | |
player.width=40; | |
player.height=40; | |
player.halfWidth=20; | |
player.halfHeight=20; | |
player.rotationalVelocity=5; //how many degrees to turn the ship | |
player.thrustAcceleration=.05; | |
player.missileFrameDelay=5; | |
player.thrust=false; | |
fillBackground(); | |
renderScoreBoard(); | |
switchGameState(GAME_STATE_NEW_LEVEL) | |
} | |
function gameStateNewLevel(){ | |
rocks=[]; | |
saucers=[]; | |
playerMissiles=[]; | |
particles=[]; | |
saucerMissiles=[]; | |
level++; | |
levelRockMaxSpeedAdjust=level*.25; | |
if (levelRockMaxSpeedAdjust > 3){ | |
levelRockMaxSpeed=3; | |
} | |
levelSaucerMax=1+Math.floor(level/10); | |
if (levelSaucerMax > 5){ | |
levelSaucerMax=5; | |
} | |
levelSaucerOccurenceRate=10+3*level; | |
if (levelSaucerOccurenceRate > 35){ | |
levelSaucerOccurenceRate=35; | |
} | |
levelSaucerSpeed=1+.5*level; | |
if (levelSaucerSpeed>5){ | |
levelSaucerSpeed=5; | |
} | |
levelSaucerFireDelay=120-10*level; | |
if (levelSaucerFireDelay<20) { | |
levelSaucerFireDelay=20; | |
} | |
levelSaucerFireRate=20 + 3*level; | |
if (levelSaucerFireRate<50) { | |
levelSaucerFireRate=50; | |
} | |
levelSaucerMissileSpeed=1+.2*level; | |
if (levelSaucerMissileSpeed > 4){ | |
levelSaucerMissileSpeed=4; | |
} | |
//create level rocks | |
for (var newRockctr=0;newRockctr<level+3;newRockctr++){ | |
var newRock={}; | |
newRock.scale=1; | |
//scale | |
//1=large | |
//2=medium | |
//3=small | |
//these will be used as the devisor for the new size | |
//50/1=50 | |
//50/2=25 | |
//50/3=16 | |
newRock.width=100; | |
newRock.height=100; | |
newRock.halfWidth=50; | |
newRock.halfHeight=50; | |
//start all new rocks in upper left for ship safety | |
newRock.x=Math.floor(Math.random()*100); | |
//ConsoleLog.log("newRock.x=" + newRock.x); | |
newRock.y=Math.floor(Math.random()*100);//50 | |
//ConsoleLog.log("newRock.y=" + newRock.y); | |
newRock.dx=(Math.random()*2)+levelRockMaxSpeedAdjust; | |
if (Math.random()<.5){ | |
newRock.dx*=-1; | |
} | |
newRock.dy=(Math.random()*2)+levelRockMaxSpeedAdjust; | |
if (Math.random()<.5){ | |
newRock.dy*=-1; | |
} | |
//rotation speed and direction | |
newRock.rotationInc=(Math.random()*5)+1; | |
if (Math.random()<.5){ | |
newRock.rotationInc*=-1; | |
} | |
newRock.scoreValue=bigRockScore; | |
newRock.rotation=0; | |
rocks.push(newRock); | |
//ConsoleLog.log("rock created rotationInc=" + newRock.rotationInc); | |
} | |
resetPlayer(); | |
switchGameState(GAME_STATE_PLAYER_START); | |
} | |
function gameStatePlayerStart(){ | |
fillBackground(); | |
renderScoreBoard(); | |
if (player.alpha < 1){ | |
player.alpha+=.02; | |
context.globalAlpha = player.alpha; | |
}else{ | |
switchGameState(GAME_STATE_PLAY_LEVEL); | |
} | |
renderPlayerShip(player.x, player.y,270,1); | |
context.globalAlpha=1; | |
updateRocks(); | |
renderRocks(); | |
} | |
function gameStatePlayLevel(){ | |
checkKeys(); | |
update(); | |
render(); | |
checkCollisions(); | |
checkForExtraShip(); | |
checkForEndOfLevel(); | |
frameRateCounter.countFrames(); | |
} | |
function resetPlayer() { | |
player.rotation=270; | |
player.x=.5*xMax; | |
player.y=.5*yMax; | |
player.facingX=0; | |
player.facingY=0; | |
player.movingX=0; | |
player.movingY=0; | |
player.alpha=0; | |
player.missileFrameCount=0; | |
} | |
function checkForExtraShip() { | |
if (Math.floor(score/extraShipAtEach) > extraShipsEarned) { | |
playerShips++ | |
extraShipsEarned++; | |
} | |
} | |
function checkForEndOfLevel(){ | |
if (rocks.length==0) { | |
switchGameState(GAME_STATE_NEW_LEVEL); | |
} | |
} | |
function gameStatePlayerDie(){ | |
if (particles.length >0 || playerMissiles.length>0) { | |
fillBackground(); | |
renderScoreBoard(); | |
updateRocks(); | |
updateSaucers(); | |
updateParticles(); | |
updateSaucerMissiles(); | |
updatePlayerMissiles(); | |
renderRocks(); | |
renderSaucers(); | |
renderParticles(); | |
renderSaucerMissiles(); | |
renderPlayerMissiles(); | |
frameRateCounter.countFrames(); | |
}else{ | |
playerShips--; | |
if (playerShips<1) { | |
switchGameState(GAME_STATE_GAME_OVER); | |
}else{ | |
resetPlayer(); | |
switchGameState(GAME_STATE_PLAYER_START); | |
} | |
} | |
} | |
function gameStateGameOver() { | |
//ConsoleLog.log("Game Over State"); | |
if (gameOverStarted !=true){ | |
fillBackground(); | |
renderScoreBoard(); | |
setTextStyle(); | |
context.fillText ("Game Over, Man!It's Over!!", 150, 70); | |
context.fillText ("Press space to try again.", 120, 140); | |
gameOverStarted=true; | |
}else{ | |
//wait for space key click | |
if (keyPressList[32]==true){ | |
//ConsoleLog.log("space pressed"); | |
switchGameState(GAME_STATE_TITLE); | |
gameOverStarted=false; | |
} | |
} | |
} | |
function fillBackground() { | |
// draw background and text | |
context.fillStyle = 'brown'; | |
context.fillRect(xMin, yMin, xMax, yMax); | |
} | |
function setTextStyle() { | |
context.fillStyle = 'yellow'; | |
context.font = '15px _sans'; | |
context.textBaseline = 'top'; | |
} | |
function renderScoreBoard() { | |
context.fillStyle = "lime"; | |
context.fillText('分数 ' + score, 10, 20); | |
renderPlayerShip(200,16,270,.75) | |
context.fillText('X ' + playerShips, 220, 20); | |
context.fillText('帧数: ' + frameRateCounter.lastFrameCount, 300,20) | |
} | |
function checkKeys() { | |
//check keys | |
if (keyPressList[38]==true){ | |
//thrust | |
var angleInRadians = player.rotation * Math.PI / 180; | |
player.facingX=Math.cos(angleInRadians); | |
player.facingY=Math.sin(angleInRadians); | |
var movingXNew=player.movingX+player.thrustAcceleration*player.facingX; | |
var movingYNew=player.movingY+player.thrustAcceleration*player.facingY; | |
var currentVelocity= Math.sqrt ((movingXNew*movingXNew) + (movingXNew*movingXNew)); | |
if (currentVelocity < player.maxVelocity) { | |
player.movingX=movingXNew; | |
player.movingY=movingYNew; | |
} | |
player.thrust=true; | |
}else{ | |
player.thrust=false; | |
} | |
if (keyPressList[37]==true) { | |
//rotate counter-clockwise | |
player.rotation-=player.rotationalVelocity; | |
} | |
if (keyPressList[39]==true) { | |
//rotate clockwise | |
player.rotation+=player.rotationalVelocity;; | |
} | |
if (keyPressList[32]==true) { | |
//ConsoleLog.log("player.missileFrameCount=" + player.missileFrameCount); | |
//ConsoleLog.log("player.missileFrameDelay=" + player.missileFrameDelay); | |
if (player.missileFrameCount>player.missileFrameDelay){ | |
firePlayerMissile(); | |
player.missileFrameCount=0; | |
} | |
} | |
} | |
function update() { | |
updatePlayer(); | |
updatePlayerMissiles(); | |
updateRocks(); | |
updateSaucers(); | |
updateSaucerMissiles(); | |
updateParticles(); | |
} | |
function render() { | |
fillBackground(); | |
renderScoreBoard(); | |
renderPlayerShip(player.x,player.y,player.rotation,1); | |
renderPlayerMissiles(); | |
renderRocks(); | |
renderSaucers(); | |
renderSaucerMissiles(); | |
renderParticles(); | |
} | |
function updatePlayer() { | |
player.missileFrameCount++; | |
player.x+=player.movingX; | |
player.y+=player.movingY; | |
if (player.x > xMax) { | |
player.x=-player.width; | |
}else if (player.x<-player.width){ | |
player.x=xMax; | |
} | |
if (player.y > yMax) { | |
player.y=-player.height; | |
}else if (player.y<-player.height){ | |
player.y=yMax; | |
} | |
} | |
function updatePlayerMissiles() { | |
var tempPlayerMissile={}; | |
var playerMissileLength=playerMissiles.length-1; | |
//ConsoleLog.log("update playerMissileLength=" + playerMissileLength); | |
for (var playerMissileCtr=playerMissileLength;playerMissileCtr>=0;playerMissileCtr--){ | |
//ConsoleLog.log("update player missile" + playerMissileCtr) | |
tempPlayerMissile=playerMissiles[playerMissileCtr]; | |
tempPlayerMissile.x+=tempPlayerMissile.dx; | |
tempPlayerMissile.y+=tempPlayerMissile.dy; | |
if (tempPlayerMissile.x > xMax) { | |
tempPlayerMissile.x=-tempPlayerMissile.width; | |
}else if (tempPlayerMissile.x<-tempPlayerMissile.width){ | |
tempPlayerMissile.x=xMax; | |
} | |
if (tempPlayerMissile.y > yMax) { | |
tempPlayerMissile.y=-tempPlayerMissile.height; | |
}else if (tempPlayerMissile.y<-tempPlayerMissile.height){ | |
tempPlayerMissile.y=yMax; | |
} | |
tempPlayerMissile.lifeCtr++; | |
if (tempPlayerMissile.lifeCtr > tempPlayerMissile.life){ | |
//ConsoleLog.log("removing player missile"); | |
playerMissiles.splice(playerMissileCtr,1) | |
tempPlayerMissile=null; | |
} | |
} | |
} | |
function updateRocks(){ | |
var tempRock={}; | |
var rocksLength=rocks.length-1; | |
//ConsoleLog.log("update rocks length=" + rocksLength); | |
for (var rockCtr=rocksLength;rockCtr>=0;rockCtr--){ | |
tempRock=rocks[rockCtr] | |
tempRock.x += tempRock.dx; | |
tempRock.y += tempRock.dy; | |
tempRock.rotation+=tempRock.rotationInc; | |
//ConsoleLog.log("rock rotationInc="+ tempRock.rotationInc) | |
//ConsoleLog.log("rock rotation="+ tempRock.rotation) | |
if (tempRock.x > xMax) { | |
tempRock.x=xMin-tempRock.width; | |
}else if (tempRock.x<xMin-tempRock.width){ | |
tempRock.x=xMax; | |
} | |
if (tempRock.y > yMax) { | |
tempRock.y=yMin-tempRock.width; | |
}else if (tempRock.y<yMin-tempRock.width){ | |
tempRock.y=yMax; | |
} | |
//ConsoleLog.log("update rock "+ rockCtr) | |
} | |
} | |
function updateSaucers() { | |
//first check to see is we want to add a saucer | |
if (saucers.length< levelSaucerMax){ | |
if (Math.floor(Math.random()*100)<=levelSaucerOccurenceRate){ | |
//ConsoleLog.log("create saucer") | |
var newSaucer={}; | |
newSaucer.width=30; | |
newSaucer.height=20; | |
newSaucer.halfHeight=15; | |
newSaucer.halfWidth=10; | |
newSaucer.scoreValue=saucerScore; | |
newSaucer.fireRate=levelSaucerFireRate; | |
newSaucer.fireDelay=levelSaucerFireDelay; | |
newSaucer.fireDelayCount=0; | |
newSaucer.missileSpeed=levelSaucerMissileSpeed; | |
newSaucer.dy=(Math.random()*2); | |
if (Math.floor(Math.random)*2==1){ | |
newSaucer.dy*=-1; | |
} | |
//choose betweeen left or right edge to start | |
if (Math.floor(Math.random()*2)==1){ | |
//start on right and go left | |
newSaucer.x=450; | |
newSaucer.dx=-1*levelSaucerSpeed; | |
}else{ | |
//left to right | |
newSaucer.x=-50; | |
newSaucer.dx=levelSaucerSpeed; | |
} | |
newSaucer.missileSpeed=levelSaucerMissileSpeed; | |
newSaucer.fireDelay=levelSaucerFireDelay; | |
newSaucer.fireRate=levelSaucerFireRate; | |
newSaucer.y=Math.floor(Math.random()*400); | |
saucers.push(newSaucer); | |
} | |
} | |
var tempSaucer={}; | |
var saucerLength=saucers.length-1; | |
//ConsoleLog.log("update rocks length=" + rocksLength); | |
for (var saucerCtr=saucerLength;saucerCtr>=0;saucerCtr--){ | |
tempSaucer=saucers[saucerCtr]; | |
//should saucer fire | |
tempSaucer.fireDelayCount++; | |
if (Math.floor(Math.random()*100) <=tempSaucer.fireRate && tempSaucer.fireDelayCount>tempSaucer.fireDelay ){ | |
fireSaucerMissile(tempSaucer) | |
tempSaucer.fireDelayCount=0; | |
} | |
var remove=false; | |
tempSaucer.x+=tempSaucer.dx; | |
tempSaucer.y+=tempSaucer.dy; | |
//remove saucers on left and right edges | |
if (tempSaucer.dx > 0 && tempSaucer.x >xMax){ | |
remove=true; | |
}else if (tempSaucer.dx <0 &&tempSaucer.x<xMin-tempSaucer.width){ | |
remove=true; | |
} | |
//bounce saucers off over vertical edges | |
if (tempSaucer.y > yMax || tempSaucer.y<yMin-tempSaucer.width) { | |
tempSaucer.dy*=-1 | |
} | |
if (remove==true) { | |
//remove the saucer | |
//ConsoleLog.log("saucer removed") | |
saucers.splice(saucerCtr,1); | |
tempSaucer=null; | |
} | |
} | |
} | |
function updateSaucerMissiles() { | |
var tempSaucerMissile={}; | |
var saucerMissileLength=saucerMissiles.length-1; | |
for (var saucerMissileCtr=saucerMissileLength;saucerMissileCtr>=0;saucerMissileCtr--){ | |
//ConsoleLog.log("update player missile" + playerMissileCtr) | |
tempSaucerMissile=saucerMissiles[saucerMissileCtr]; | |
tempSaucerMissile.x += tempSaucerMissile.dx; | |
tempSaucerMissile.y += tempSaucerMissile.dy; | |
if (tempSaucerMissile.x > xMax) { | |
tempSaucerMissile.x=-tempSaucerMissile.width; | |
}else if (tempSaucerMissile.x<-tempSaucerMissile.width){ | |
tempSaucerMissile.x=xMax; | |
} | |
if (tempSaucerMissile.y > yMax) { | |
tempSaucerMissile.y=-tempSaucerMissile.height; | |
}else if (tempSaucerMissile.y<-tempSaucerMissile.height){ | |
tempSaucerMissile.y=yMax; | |
} | |
tempSaucerMissile.lifeCtr++; | |
if (tempSaucerMissile.lifeCtr > tempSaucerMissile.life){ | |
//remove | |
saucerMissiles.splice(saucerMissileCtr,1) | |
tempSaucerMissile=null; | |
} | |
} | |
} | |
function updateParticles() { | |
var tempParticle={}; | |
var particleLength=particles.length-1; | |
//ConsoleLog.log("particle=" + particleLength) | |
for (var particleCtr=particleLength;particleCtr>=0;particleCtr--){ | |
var remove =false; | |
tempParticle=particles[particleCtr]; | |
tempParticle.x+=tempParticle.dx; | |
tempParticle.y+=tempParticle.dy; | |
tempParticle.lifeCtr++; | |
//ConsoleLog.log("particle.lifeCtr=" + tempParticle.lifeCtr); | |
//try{ | |
if (tempParticle.lifeCtr > tempParticle.life){ | |
remove=true; | |
} else if ((tempParticle.x > xMax) || (tempParticle.x<xMin) || (tempParticle.y > yMax) || (tempParticle.y<yMin)){ | |
remove=true; | |
} | |
//} | |
//catch(err) { | |
// ConsoleLog.log ("error in particle"); | |
// ConsoleLog.log("particle:" + particleCtr); | |
//} | |
if (remove) { | |
particles.splice(particleCtr,1) | |
tempParticle=null; | |
} | |
} | |
} | |
function renderPlayerShip(x,y,rotation, scale) { | |
//transformation | |
var angleInRadians = rotation * Math.PI / 180; | |
context.save(); //save current state in stack | |
context.setTransform(1,0,0,1,0,0); // reset to identity | |
//translate the canvas origin to the center of the player | |
context.translate(x+player.halfWidth,y+player.halfHeight); | |
context.rotate(angleInRadians); | |
context.scale(scale,scale) | |
//drawShip | |
context.strokeStyle = 'yellow'; | |
context.beginPath(); | |
//hard coding in locations | |
//facing right | |
context.moveTo(-10,-10); | |
context.lineTo(10,0); | |
context.moveTo(10,1); | |
context.lineTo(-10,10); | |
context.lineTo(1,1); | |
context.moveTo(1,-1); | |
context.lineTo(-10,-10); | |
if (player.thrust==true && scale==1) { | |
//check for scale==1 for ship indicator does not display with thrust | |
context.moveTo(-4,-2); | |
context.lineTo(-4,1); | |
context.moveTo(-5,-1); | |
context.lineTo(-10,-1); | |
context.moveTo(-5,0); | |
context.lineTo(-10,0); | |
} | |
context.stroke(); | |
context.closePath(); | |
//restore context | |
context.restore(); //pop old state on to screen | |
} | |
function renderPlayerMissiles() { | |
var tempPlayerMissile={}; | |
var playerMissileLength=playerMissiles.length-1; | |
//ConsoleLog.log("render playerMissileLength=" + playerMissileLength); | |
for (var playerMissileCtr=playerMissileLength;playerMissileCtr>=0;playerMissileCtr--){ | |
//ConsoleLog.log("draw playert missile " + playerMissileCtr) | |
tempPlayerMissile=playerMissiles[playerMissileCtr]; | |
context.save(); //save current state in stack | |
context.setTransform(1,0,0,1,0,0); // reset to identity | |
//translate the canvas origin to the center of the player | |
context.translate(tempPlayerMissile.x+1,tempPlayerMissile.y+1); | |
context.strokeStyle = 'yellow'; | |
context.beginPath(); | |
//draw everything offset by 1/2. Zero Relative 1/2 is 15 | |
context.moveTo(-1,-1); | |
context.lineTo(1,-1); | |
context.lineTo(1,1); | |
context.lineTo(-1,1); | |
context.lineTo(-1,-1); | |
context.stroke(); | |
context.closePath(); | |
context.restore(); //pop old state on to screen | |
} | |
} | |
function renderRocks() { | |
var tempRock={}; | |
var rocksLength=rocks.length-1; | |
for (var rockCtr=rocksLength;rockCtr>=0;rockCtr--){ | |
tempRock=rocks[rockCtr]; | |
var angleInRadians = tempRock.rotation * Math.PI / 180; | |
//ConsoleLog.log("render rock rotation"+(tempRock.rotation)); | |
context.save(); //save current state in stack | |
context.setTransform(1,0,0,1,0,0); // reset to identity | |
//translate the canvas origin to the center of the player | |
context.translate(tempRock.x+tempRock.halfWidth,tempRock.y+tempRock.halfHeight); | |
//ConsoleLog.log("render rock x"+(tempRock.x+tempRock.halfWidth)); | |
//ConsoleLog.log("render rock y"+(tempRock.y+tempRock.halfHeight)); | |
context.rotate(angleInRadians); | |
context.strokeStyle = 'white'; | |
context.beginPath(); | |
//draw everything offset by 1/2. Zero Relative 1/2 is if .5*width -1. Same for height | |
context.moveTo(-(tempRock.halfWidth-1),-(tempRock.halfHeight-1)); | |
context.lineTo((tempRock.halfWidth-1),-(tempRock.halfHeight-1)); | |
context.lineTo((tempRock.halfWidth-1),(tempRock.halfHeight-1)); | |
context.lineTo(-(tempRock.halfWidth-1),(tempRock.halfHeight-1)); | |
context.lineTo(-(tempRock.halfWidth-1),-(tempRock.halfHeight-1)); | |
context.stroke(); | |
context.closePath(); | |
context.restore(); //pop old state on to screen | |
} | |
} | |
function renderSaucers() { | |
var tempSaucer={}; | |
var saucerLength=saucers.length-1; | |
for (var saucerCtr=saucerLength;saucerCtr>=0;saucerCtr--){ | |
//ConsoleLog.log("saucer: " + saucerCtr); | |
tempSaucer=saucers[saucerCtr]; | |
context.save(); //save current state in stack | |
context.setTransform(1,0,0,1,0,0); // reset to identity | |
//translate the canvas origin to the center of the player | |
//context.translate(this.x+halfWidth,this.y+halfHeight); | |
context.translate(tempSaucer.x,tempSaucer.y); | |
context.strokeStyle = 'lime'; | |
context.beginPath(); | |
//did not move to middle because it is drawn in exact space | |
context.moveTo(4,0); | |
context.lineTo(9,0); | |
context.lineTo(12,3); | |
context.lineTo(13,3); | |
context.moveTo(13,4); | |
context.lineTo(10,7); | |
context.lineTo(3,7); | |
context.lineTo(1,5); | |
context.lineTo(12,5); | |
context.moveTo(0,4); | |
context.lineTo(0,3); | |
context.lineTo(13,3); | |
context.moveTo(5,1); | |
context.lineTo(5,2); | |
context.moveTo(8,1); | |
context.lineTo(8,2); | |
context.moveTo(2,2); | |
context.lineTo(4,0); | |
context.stroke(); | |
context.closePath(); | |
context.restore(); //pop old state on to screen | |
} | |
} | |
function renderSaucerMissiles() { | |
var tempSaucerMissile={}; | |
var saucerMissileLength=saucerMissiles.length-1; | |
//ConsoleLog.log("saucerMissiles= " + saucerMissiles.length) | |
for (var saucerMissileCtr=saucerMissileLength;saucerMissileCtr>=0;saucerMissileCtr--){ | |
//ConsoleLog.log("draw playert missile " + playerMissileCtr) | |
tempSaucerMissile=saucerMissiles[saucerMissileCtr]; | |
context.save(); //save current state in stack | |
context.setTransform(1,0,0,1,0,0); // reset to identity | |
//translate the canvas origin to the center of the player | |
context.translate(tempSaucerMissile.x+1,tempSaucerMissile.y+1); | |
context.strokeStyle = '#ffffff'; | |
context.beginPath(); | |
//draw everything offset by 1/2. Zero Relative 1/2 is 15 | |
context.moveTo(-1,-1); | |
context.lineTo(1,-1); | |
context.lineTo(1,1); | |
context.lineTo(-1,1); | |
context.lineTo(-1,-1); | |
context.stroke(); | |
context.closePath(); | |
context.restore(); //pop old state on to screen | |
} | |
} | |
function renderParticles() { | |
var tempParticle={}; | |
var particleLength=particles.length-1; | |
for (var particleCtr=particleLength;particleCtr>=0;particleCtr--){ | |
tempParticle=particles[particleCtr]; | |
context.save(); //save current state in stack | |
context.setTransform(1,0,0,1,0,0); // reset to identity | |
//translate the canvas origin to the center of the player | |
context.translate(tempParticle.x,tempParticle.y); | |
context.strokeStyle = '#ffffff'; | |
context.beginPath(); | |
//draw everything offset by 1/2. Zero Relative 1/2 is 15 | |
context.moveTo(0,0); | |
context.lineTo(1,1); | |
context.stroke(); | |
context.closePath(); | |
context.restore(); //pop old state on to screen | |
} | |
} | |
function checkCollisions() { | |
//loop through rocks then missiles. There will always be rocks and a ship, but there will not always be missiles | |
var tempRock={}; | |
var rocksLength=rocks.length-1; | |
var tempPlayerMissile={}; | |
var playerMissileLength=playerMissiles.length-1; | |
var saucerLength=saucers.length-1; | |
var tempSaucer={}; | |
var saucerMissileLength=saucerMissiles.length-1; | |
rocks: for (var rockCtr=rocksLength;rockCtr>=0;rockCtr--){ | |
tempRock=rocks[rockCtr]; | |
missiles:for (var playerMissileCtr=playerMissileLength;playerMissileCtr>=0;playerMissileCtr--){ | |
tempPlayerMissile=playerMissiles[playerMissileCtr]; | |
if (boundingBoxCollide(tempRock,tempPlayerMissile)){ | |
//ConsoleLog.log("hit rock"); | |
createExplode(tempRock.x+tempRock.halfWidth,tempRock.y+tempRock.halfHeight,10); | |
if (tempRock.scale<3) { | |
splitRock(tempRock.scale+1, tempRock.x, tempRock.y); | |
} | |
addToScore(tempRock.scoreValue); | |
playerMissiles.splice(playerMissileCtr,1); | |
tempPlayerMissile=null; | |
rocks.splice(rockCtr,1); | |
tempRock=null; | |
break rocks; | |
break missiles; | |
} | |
} | |
saucers:for (var saucerCtr=saucerLength;saucerCtr>=0;saucerCtr--){ | |
tempSaucer=saucers[saucerCtr]; | |
if (boundingBoxCollide(tempRock,tempSaucer)){ | |
//ConsoleLog.log("hit rock"); | |
createExplode(tempSaucer.x+tempSaucer.halfWidth,tempSaucer.y+tempSaucer.halfHeight,10); | |
createExplode(tempRock.x+tempRock.halfWidth,tempRock.y+tempRock.halfHeight,10); | |
if (tempRock.scale<3) { | |
splitRock(tempRock.scale+1, tempRock.x, tempRock.y); | |
} | |
saucers.splice(saucerCtr,1); | |
tempSaucer=null; | |
rocks.splice(rockCtr,1); | |
tempRock=null; | |
break rocks; | |
break saucers; | |
} | |
} | |
//saucer missiles against rocks | |
//this is done here so we don't have to loop through rocks again as it would probably | |
//be the biggest arrary | |
saucerMissiles:for (var saucerMissileCtr=saucerMissileLength;saucerMissileCtr>=0;saucerMissileCtr--){ | |
tempSaucerMissile=saucerMissiles[saucerMissileCtr]; | |
if (boundingBoxCollide(tempRock,tempSaucerMissile)){ | |
//ConsoleLog.log("hit rock"); | |
createExplode(tempRock.x+tempRock.halfWidth,tempRock.y+tempRock.halfHeight,10); | |
if (tempRock.scale<3) { | |
splitRock(tempRock.scale+1, tempRock.x, tempRock.y); | |
} | |
saucerMissiles.splice(saucerCtr,1); | |
tempSaucerMissile=null; | |
rocks.splice(rockCtr,1); | |
tempRock=null; | |
break rocks; | |
break saucerMissiles; | |
} | |
} | |
//check player aginst rocks | |
if (boundingBoxCollide(tempRock,player)){ | |
//ConsoleLog.log("hit player"); | |
createExplode(tempRock.x+tempRock.halfWidth,tempRock.halfHeight,10); | |
addToScore(tempRock.scoreValue); | |
if (tempRock.scale<3) { | |
splitRock(tempRock.scale+1, tempRock.x, tempRock.y); | |
} | |
rocks.splice(rockCtr,1); | |
tempRock=null; | |
playerDie(); | |
} | |
} | |
//now check player against saucers and then saucers against player missiles and finally player against saucer missiles | |
playerMissileLength=playerMissiles.length-1; | |
saucerLength=saucers.length-1; | |
saucers:for (var saucerCtr=saucerLength;saucerCtr>=0;saucerCtr--){ | |
tempSaucer=saucers[saucerCtr]; | |
missiles:for (var playerMissileCtr=playerMissileLength;playerMissileCtr>=0;playerMissileCtr--){ | |
tempPlayerMissile=playerMissiles[playerMissileCtr]; | |
if (boundingBoxCollide(tempSaucer,tempPlayerMissile)){ | |
//ConsoleLog.log("hit rock"); | |
createExplode(tempSaucer.x+tempSaucer.halfWidth,tempSaucer.y+tempSaucer.halfHeight,10); | |
addToScore(tempSaucer.scoreValue); | |
playerMissiles.splice(playerMissileCtr,1); | |
tempPlayerMissile=null; | |
saucers.splice(saucerCtr,1); | |
tempSaucer=null; | |
break saucers; | |
break missiles; | |
} | |
} | |
//player against saucers | |
if (boundingBoxCollide(tempSaucer,player)){ | |
//ConsoleLog.log("hit player"); | |
createExplode(tempSaucer.x+16,tempSaucer.y+16,10); | |
addToScore(tempSaucer.scoreValue); | |
saucers.splice(rockCtr,1); | |
tempSaucer=null; | |
playerDie(); | |
} | |
} | |
//saucerMissiles against player | |
saucerMissileLength=saucerMissiles.length-1; | |
saucerMissiles:for (var saucerMissileCtr=saucerMissileLength;saucerMissileCtr>=0;saucerMissileCtr--){ | |
tempSaucerMissile=saucerMissiles[saucerMissileCtr]; | |
if (boundingBoxCollide(player,tempSaucerMissile)){ | |
//ConsoleLog.log("saucer missile hit player"); | |
playerDie(); | |
saucerMissiles.splice(saucerCtr,1); | |
tempSaucerMissile=null; | |
break saucerMissiles; | |
} | |
} | |
} | |
function firePlayerMissile(){ | |
//ConsoleLog.log("fire playerMissile"); | |
var newPlayerMissile={}; | |
newPlayerMissile.dx=5*Math.cos(Math.PI*(player.rotation)/180); | |
newPlayerMissile.dy=5*Math.sin(Math.PI*(player.rotation)/180); | |
newPlayerMissile.x=player.x+player.halfWidth; | |
newPlayerMissile.y=player.y+player.halfHeight; | |
newPlayerMissile.life=60; | |
newPlayerMissile.lifeCtr=0; | |
newPlayerMissile.width=2; | |
newPlayerMissile.height=2; | |
playerMissiles.push(newPlayerMissile); | |
} | |
function fireSaucerMissile(saucer) { | |
var newSaucerMissile={}; | |
newSaucerMissile.x=saucer.x+.5*saucer.width; | |
newSaucerMissile.y=saucer.y+.5*saucer.height; | |
newSaucerMissile.width=2; | |
newSaucerMissile.height=2; | |
newSaucerMissile.speed=saucer.missileSpeed; | |
//ConsoleLog.log("saucer fire"); | |
//fire at player from small saucer | |
var diffx = player.x-saucer.x; | |
var diffy = player.y-saucer.y; | |
var radians = Math.atan2(diffy, diffx); | |
var degrees = 360 * radians / (2 * Math.PI); | |
newSaucerMissile.dx=saucer.missileSpeed*Math.cos(Math.PI*(degrees)/180); | |
newSaucerMissile.dy=saucer.missileSpeed*Math.sin(Math.PI*(degrees)/180); | |
newSaucerMissile.life=160; | |
newSaucerMissile.lifeCtr=0; | |
saucerMissiles.push(newSaucerMissile); | |
} | |
function playerDie() { | |
//ConsoleLog.log("player die"); | |
createExplode(player.x+player.halfWidth, player.y+player.halfWidth,50); | |
switchGameState(GAME_STATE_PLAYER_DIE); | |
} | |
function createExplode(x,y,num) { | |
//create 10 particles | |
for (var partCtr=0;partCtr<num;partCtr++){ | |
var newParticle=new Object(); | |
newParticle.dx=Math.random()*3; | |
if (Math.random()<.5){ | |
newParticle.dx*=-1; | |
} | |
newParticle.dy=Math.random()*3; | |
if (Math.random()<.5){ | |
newParticle.dy*=-1; | |
} | |
newParticle.life=Math.floor(Math.random()*30+30); | |
newParticle.lifeCtr=0; | |
newParticle.x=x; | |
newParticle.y=y; | |
//ConsoleLog.log("newParticle.life=" + newParticle.life); | |
particles.push(newParticle); | |
} | |
} | |
function boundingBoxCollide(object1, object2) { | |
var left1 = object1.x; | |
var left2 = object2.x; | |
var right1 = object1.x + object1.width; | |
var right2 = object2.x + object2.width; | |
var top1 = object1.y; | |
var top2 = object2.y; | |
var bottom1 = object1.y + object1.height; | |
var bottom2 = object2.y + object2.height; | |
if (bottom1 < top2) return(false); | |
if (top1 > bottom2) return(false); | |
if (right1 < left2) return(false); | |
if (left1 > right2) return(false); | |
return(true); | |
}; | |
function splitRock(scale,x,y){ | |
for (var newRockctr=0;newRockctr<2;newRockctr++){ | |
var newRock={}; | |
//ConsoleLog.log("split rock"); | |
if (scale==2){ | |
newRock.scoreValue=medRockScore; | |
newRock.width=60; | |
newRock.height=60; | |
newRock.halfWidth=30; | |
newRock.halfHeight=30; | |
}else { | |
newRock.scoreValue=smlRockScore; | |
newRock.width=40; | |
newRock.height=40; | |
newRock.halfWidth=20; | |
newRock.halfHeight=20; | |
} | |
newRock.scale=scale; | |
newRock.x=x; | |
newRock.y=y; | |
newRock.dx=Math.random()*3; | |
if (Math.random()<.5){ | |
newRock.dx*=-1; | |
} | |
newRock.dy=Math.random()*3; | |
if (Math.random()<.5){ | |
newRock.dy*=-1; | |
} | |
newRock.rotationInc=(Math.random()*5)+1; | |
if (Math.random()<.5){ | |
newRock.rotationInc*=-1; | |
} | |
newRock.rotation=0; | |
//ConsoleLog.log("new rock scale"+(newRock.scale)); | |
rocks.push(newRock); | |
} | |
} | |
function addToScore(value){ | |
score+=value; | |
} | |
document.onkeydown=function(e){ | |
e=e?e:window.event; | |
//ConsoleLog.log(e.keyCode + "down"); | |
keyPressList[e.keyCode]=true; | |
} | |
document.onkeyup=function(e){ | |
//document.body.onkeyup=function(e){ | |
e=e?e:window.event; | |
//ConsoleLog.log(e.keyCode + "up"); | |
keyPressList[e.keyCode]=false; | |
}; | |
//*** application start | |
switchGameState(GAME_STATE_TITLE); | |
frameRateCounter=new FrameRateCounter(); | |
//**** application loop | |
const FRAME_RATE=40; | |
var intervalTime=1000/FRAME_RATE; | |
setInterval(runGame, intervalTime ); | |
} | |
//***** object prototypes ***** | |
//*** consoleLog util object | |
//creat constructor | |
function ConsoleLog(){ | |
} | |
//create function that will be added to the class | |
console_log=function(message) { | |
if(typeof(console) !== 'undefined' && console != null) { | |
console.log(message); | |
} | |
} | |
//add class/static function to class by assignment | |
ConsoleLog.log=console_log; | |
//*** end console log object | |
//*** FrameRateCounter object prototype | |
function FrameRateCounter() { | |
this.lastFrameCount=0; | |
var dateTemp =new Date(); | |
this.frameLast=dateTemp.getTime(); | |
delete dateTemp; | |
this.frameCtr=0; | |
} | |
FrameRateCounter.prototype.countFrames=function() { | |
var dateTemp =new Date(); | |
this.frameCtr++; | |
if (dateTemp.getTime() >=this.frameLast+1000) { | |
//ConsoleLog.log("frame event"); | |
this.lastFrameCount=this.frameCtr; | |
this.frameLast=dateTemp.getTime(); | |
this.frameCtr=0; | |
} | |
delete dateTemp; | |
} | |
</script> | |
</head> | |
<body> | |
<div style="position: absolute; top: 50px; left: 50px;"> | |
<canvas id="canvas" width="800" height="600"> | |
</canvas> | |
<a href = "http://www.coloner.icoc.cc/">My Website</a> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment