Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 1010 lines (756 sloc) 22.3 KB
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Geo Blaster Basic Game</title>
<script type="text/javascript">
window.addEventListener('load', eventWindowLoaded, false);
function eventWindowLoaded() {
canvasApp();
}
</script>
<script src="modernizr-1.6.min.js"></script>
<script language="Javascript" ">
function canvasSupport () {
return Modernizr.canvas;
}
function canvasApp(){
if (!canvasSupport()) {
return;
}else{
theCanvas = document.getElementById('canvas');
context = theCanvas.getContext('2d');
}
//application states
const GAME_STATE_INIT=0;
const GAME_STATE_WAIT_FOR_LOAD=10;
const GAME_STATE_TITLE=20;
const GAME_STATE_NEW_GAME=30;
const GAME_STATE_WAIT_FOR_PLAYER_MOVE=40;
const GAME_STATE_ANIMATE_PLAYER=50;
const GAME_STATE_EVALUATE_PLAYER_MOVE=60;
const GAME_STATE_ENEMY_MOVE=70;
const GAME_STATE_ANIMATE_ENEMY=80;
const GAME_STATE_EVALUATE_ENEMY_MOVE=90;
const GAME_STATE_EVALUATE_OUTCOME=100;
const GAME_STATE_ANIMATE_EXPLODE=110;
const GAME_STATE_CHECK_FOR_GAME_OVER=120;
const GAME_STATE_PLAYER_WIN=130;
const GAME_STATE_PLAYER_LOSE=140;
const GAME_STATE_GAME_OVER=150;
var currentGameState=0;
var currentGameStateFunction=null;
//loading
var loadCount=0;
var itemsToLoad = 1;
//keyPresses
var keyPressList=[];
var tileSheet;
var mapRows=15;
var mapCols=15;
//playfield
var playField=[];
var items=[];
var xMin=0;
var xMax=480;
var yMin=0;
var yMax=480;
//tiles
var playerTiles=[1,2,3,4,5,6,7,8];
var enemyTiles=[9,10,11,12,13,14,15,16];
var roadTile=0;
var wallTile=30;
var goalTile=23;
var explodeTiles=[17,18,19,18,17];
var wallMax=20;
var playerMax=1;
var enemyMax=20;
var goalMax=1;
var enemyMoveCompleteCount=0;
//objects
var player={};
var enemy=[];
var explosions=[];
//screens
var screenStarted=false;
var score=0;
var enemyScore=10;
var goalScore=50;
var highScore=0;
var chanceRandomEnemyMovement=25;
function runGame(){
currentGameStateFunction();
}
function switchGameState(newState) {
currentGameState=newState;
switch (currentGameState) {
case GAME_STATE_INIT:
currentGameStateFunction=gameStateInit;
break;
case GAME_STATE_WAIT_FOR_LOAD:
currentGameStateFunction=gameStateWaitForLoad;
break;
case GAME_STATE_TITLE:
currentGameStateFunction=gameStateTitle;
break;
case GAME_STATE_NEW_GAME:
currentGameStateFunction=gameStateNewGame;
break;
case GAME_STATE_WAIT_FOR_PLAYER_MOVE:
currentGameStateFunction=gameStateWaitForPlayerMove;
break;
case GAME_STATE_ANIMATE_PLAYER:
currentGameStateFunction=gameStateAnimatePlayer;
break;
case GAME_STATE_EVALUATE_PLAYER_MOVE:
currentGameStateFunction=gameStateEvaluatePlayerMove;
break;
case GAME_STATE_ENEMY_MOVE:
currentGameStateFunction=gameStateEnemyMove;
break;
case GAME_STATE_ANIMATE_ENEMY:
currentGameStateFunction=gameStateAnimateEnemy;
break;
case GAME_STATE_EVALUATE_ENEMY_MOVE:
currentGameStateFunction=gameStateEvaluateEnemyMove;
break;
case GAME_STATE_EVALUATE_OUTCOME:
currentGameStateFunction=gameStateEvaluateOutcome;
break;
case GAME_STATE_ANIMATE_EXPLODE:
currentGameStateFunction=gameStateAnimateExplode;
break;
case GAME_STATE_CHECK_FOR_GAME_OVER:
currentGameStateFunction=gameStateCheckForGameOver;
break;
case GAME_STATE_PLAYER_WIN:
currentGameStateFunction=gameStatePlayerWin;
break;
case GAME_STATE_PLAYER_LOSE:
currentGameStateFunction=gameStatePlayerLose;
break;
}
}
function gameStateWaitForLoad(){
//do nothing while loading events occur
////console.log("doing nothing...")
}
function gameStateInit() {
tileSheet = new Image();
tileSheet.src = "tanks_sheet.png";
tileSheet.onload = itemLoaded;
switchGameState(GAME_STATE_WAIT_FOR_LOAD);
}
function itemLoaded(event) {
loadCount++;
//////console.log("loading:" + loadCount)
if (loadCount >= itemsToLoad) {
switchGameState(GAME_STATE_TITLE)
}
}
function gameStateTitle() {
if (screenStarted !=true){
fillBackground();
setTextStyleTitle();
context.fillText ("Micro Tank Maze", 160, 70);
context.fillText ("Press Space To Play", 150, 140);
screenStarted=true;
}else{
//wait for space key click
if (keyPressList[32]==true){
////console.log("space pressed");
switchGameState(GAME_STATE_NEW_GAME);
screenStarted=false;
}
}
}
function gameStatePlayerWin(){
if (!screenStarted){
score+=goalScore;
fillBackground();
setTextStyleTitle();
context.fillText ("YOU WON THE GAME!", 135, 70);
context.fillText ("Final Score: " + score, 150, 100);
context.fillText ("Number of enemy: " + enemyMax, 150,130);
if (score > highScore){
highScore=score;
context.fillText ("NEW HIGH SCORE!", 150,160);
}
context.fillText ("High Score: " + score, 150, 190);
screenStarted=true;
enemyMax++;
if (enemyMax >50){
enemyMax=50;
}
context.fillText ("Number of enemy for next game: " + enemyMax, 100,220);
context.fillText ("Press Space To Play", 150, 300);
}else{
//wait for space key click
if (keyPressList[32]==true){
////console.log("space pressed");
switchGameState(GAME_STATE_NEW_GAME);
screenStarted=false;
}
}
}
function gameStatePlayerLose(){
if (!screenStarted){
fillBackground();
setTextStyleTitle();
context.fillText ("SORRY, YOU LOST THE GAME!", 100, 70);
context.fillText ("Final Score: " + score, 150, 100);
context.fillText ("Number of enemy: " + enemyMax, 150,130);
if (score > highScore){
highScore=score;
context.fillText ("NEW HIGH SCORE!", 150,160);
}
context.fillText ("High Score: " + score, 150, 190);
screenStarted=true;
context.fillText ("Number of enemy for next game: " + enemyMax, 100,220);
context.fillText ("Press Space To Play", 150, 300);
}else{
//wait for space key click
if (keyPressList[32]==true){
////console.log("space pressed");
switchGameState(GAME_STATE_NEW_GAME);
screenStarted=false;
}
}
}
function gameStateNewGame(){
score=0;
enemy=[];
explosions=[];
playField=[];
items=[];
resetPlayer();
createPlayField();
renderPlayField();
switchGameState(GAME_STATE_WAIT_FOR_PLAYER_MOVE);
}
function createPlayField(){
var wallCount=0;
var playerCount=0;
var enemyCount=0;
var goalCount=0;
var roadCount=0;
//fill with road
for (var rowCtr=0;rowCtr<15;rowCtr++){
var tempRow=[];
for (colCtr=0;colCtr<15;colCtr++) {
tempRow.push(roadTile)
}
playField.push(tempRow);
}
////console.log("playField=" + playField);
//create items array
for (rowCtr=0;rowCtr<15;rowCtr++){
var tempRow=[];
for (colCtr=0;colCtr<15;colCtr++) {
tempRow.push(0)
}
items.push(tempRow);
}
var randRow;
var randCol;
//placewalls
for (var wallCtr=0;wallCtr<wallMax;wallCtr++){
var wallLocationFound=false;
while(!wallLocationFound){
randRow=Math.floor(Math.random()*15);
randCol=Math.floor(Math.random()*15);
if (playField[randRow][randCol]==roadTile){
playField[randRow][randCol]=wallTile;
wallLocationFound=true;
}
}
}
//place enemy
for (var enemyCtr=0;enemyCtr<enemyMax;enemyCtr++){
var enemyLocationFound=false;
while(!enemyLocationFound){
randRow=Math.floor(Math.random()*15);
randCol=Math.floor(Math.random()*15);
if (playField[randRow][randCol]==roadTile){
enemyLocationFound=true;
var tempEnemy={};
tempEnemy.row=randRow;
tempEnemy.col=randCol;
tempEnemy.nextRow=0;
tempEnemy.nextCol=0;
tempEnemy.currentTile=0;
tempEnemy.rotation=0;
tempEnemy.x=tempEnemy.col*32;
tempEnemy.y=tempEnemy.row*32;
tempEnemy.speed=2;
tempEnemy.destinationX=0;
tempEnemy.destinationY=0;
tempEnemy.dx=0;
tempEnemy.dy=0;
tempEnemy.hit=false;
tempEnemy.dead=false;
tempEnemy.moveComplete=false;
enemy.push(tempEnemy);
items[randRow][randCol]=1;
}
}
}
//place player
var playerLocationFound=false;
while(!playerLocationFound){
randRow=Math.floor(Math.random()*15);
randCol=Math.floor(Math.random()*15);
if (playField[randRow][randCol]==roadTile && items[randRow][randCol]==0){
playerLocationFound=true;
player.col=randCol;
player.row=randRow;
player.x=player.col*32;
player.y=player.row*32;
items[randRow][randCol]=1;
}
}
//place goal
var goalLocationFound=false;
while(!goalLocationFound){
randRow=Math.floor(Math.random()*15);
randCol=Math.floor(Math.random()*15);
if (playField[randRow][randCol]==roadTile && items[randRow][randCol]==0){
playField[randRow][randCol]=goalTile;
goalLocationFound=true;
}
}
////console.log("playField=" + playField);
}
function resetPlayer(){
player.row=0;
player.col=0;
player.nextRow=0;
player.nextCol=0;
player.currentTile=0;
player.rotation=0;
player.speed=2;
player.destinationX=0;
player.destinationY=0;
player.x=0;
player.y=0;
player.dx=0;
player.dy=0;
player.hit=false;
player.dead=false;
player.win=false;
}
function gameStateWaitForPlayerMove() {
if (keyPressList[38]==true){
//up
if (checkBounds(-1,0, player)){
setPlayerDestination();
}
}else if (keyPressList[37]==true) {
//left
if (checkBounds(0,-1, player)){
setPlayerDestination();
}
}else if (keyPressList[39]==true) {
//right
if (checkBounds(0,1, player)){
setPlayerDestination();
}
}else if (keyPressList[40]==true){
//down
if (checkBounds(1,0, player)){
setPlayerDestination();
}
}
}
function setPlayerDestination(){
player.destinationX=player.nextCol*32;
player.destinationY=player.nextRow*32;
switchGameState(GAME_STATE_ANIMATE_PLAYER);
}
function checkBounds(rowInc, colInc, object){
object.nextRow=object.row+rowInc;
object.nextCol=object.col+colInc;
if (object.nextCol >=0 && object.nextCol<15 && object.nextRow>=0 && object.nextRow<15){
object.dx=colInc;
object.dy=rowInc;
if (colInc==1){
object.rotation=90;
}else if (colInc==-1){
object.rotation=270;
}else if (rowInc==-1){
object.rotation=0;
}else if (rowInc==1){
object.rotation=180;
}
return(true);
}else{
object.nextRow=object.row;
object.nextCol=object.col;
return(false);
}
}
function gameStateAnimatePlayer(){
player.x+=player.dx*player.speed;
player.y+=player.dy*player.speed;
player.currentTile++;
if (player.currentTile==playerTiles.length){
player.currentTile=0;
}
renderPlayField();
if (player.x==player.destinationX && player.y==player.destinationY){
switchGameState(GAME_STATE_EVALUATE_PLAYER_MOVE);
}
}
function gameStateEvaluatePlayerMove(){
player.row=player.nextRow;
player.col=player.nextCol;
if (playField[player.row][player.col]==wallTile){
player.hit=true;
}else if (playField[player.row][player.col]==goalTile){
player.win=true;
}
for (var eCtr=enemy.length-1;eCtr>=0;eCtr--){
if (player.row==enemy[eCtr].row && player.col==enemy[eCtr].col){
enemy[eCtr].hit=true;
player.hit=true;
}
}
switchGameState(GAME_STATE_ENEMY_MOVE);
}
function gameStateEnemyMove(){
for (var eCtr=0;eCtr<enemy.length;eCtr++){
var tempEnemy=enemy[eCtr];
if (!tempEnemy.hit){
var directionsToTest=[];
var hDiff=tempEnemy.col - player.col;
var vDiff=tempEnemy.row - player.row;
if (Math.abs(vDiff) < Math.abs(hDiff)){
if (vDiff > 0){
directionsToTest.push("up");
directionsToTest.push("down");
}else if (vDiff <0){
directionsToTest.push("down");
directionsToTest.push("up");
}
if (hDiff >0){
directionsToTest.push("left");
directionsToTest.push("right");
}else if (hDiff <0){
directionsToTest.push("right");
directionsToTest.push("left");
}
}else if (Math.abs(hDiff) < Math.abs(vDiff)) {
if (hDiff >0){
directionsToTest.push("left");
directionsToTest.push("right");
}else if (hDiff<0){
directionsToTest.push("right");
directionsToTest.push("left");
}else if (vDiff > 0){
directionsToTest.push("up");
directionsToTest.push("down");
}else if (vDiff <0){
directionsToTest.push("down");
directionsToTest.push("up");
}
}else if (Math.abs(hDiff) == Math.abs(vDiff)) {
//make and educated random guess
if (Math.floor(Math.random()*2)==0){
//try vertical first
if (vDiff >0){
directionsToTest.push("up");
directionsToTest.push("down");
}else if (vDiff<0){
directionsToTest.push("down");
directionsToTest.push("up");
}
}else{
//try vertical first
if (hDiff >0){
directionsToTest.push("left");
directionsToTest.push("right");
}else if (hDiff<0){
directionsToTest.push("right");
directionsToTest.push("left");
}
}
}
var chooseRandom=false;
var moveFound=false;
var movePtr=0;
var move;
if (Math.floor(Math.random()*100)> chanceRandomEnemyMovement){
//not random movement
while(!moveFound){
move=directionsToTest[movePtr];
switch(move){
case "up":
if (checkBounds(-1,0,tempEnemy)){
moveFound=true;
}
break;
case "down":
if (checkBounds(1,0,tempEnemy)){
moveFound=true;
}
break;
case "left":
if (checkBounds(0,-1, tempEnemy)){
moveFound=true;
}
break;
case "right":
if (checkBounds(0,1,tempEnemy)){
moveFound=true;
}
break
}
movePtr++
if (movePtr==directionsToTest.length){
//do not move if no move found
//this should be impossible
chooseRandom=true;
}
}
}else{
chooseRandom=true;
}
//pick random direction to test;
if (chooseRandom) {
while(!moveFound){
switch(Math.floor(Math.random()*4)){
case 0:
if (checkBounds(-1,0,tempEnemy)){
moveFound=true;
}else{
}
break;
case 1:
if (checkBounds(1,0,tempEnemy)){
moveFound=true;
}else{
}
break;
case 2:
if (checkBounds(0,-1, tempEnemy)){
moveFound=true;
}else{
}
break;
case 3:
if (checkBounds(0,1,tempEnemy)){
moveFound=true;
}else{
}
break
}
}
}
tempEnemy.destinationX=tempEnemy.nextCol*32;
tempEnemy.destinationY=tempEnemy.nextRow*32;
}else{
tempEnemy.nextCol=tempEnemy.col;
tempEnemy.nextRow=tempEnemy.row;
tempEnemy.destinationX=tempEnemy.nextCol*32;
tempEnemy.destinationY=tempEnemy.nextRow*32;
}
}
switchGameState(GAME_STATE_ANIMATE_ENEMY);
}
function gameStateAnimateEnemy(){
for (var eCtr=enemy.length-1;eCtr>=0;eCtr--){
var tempEnemy=enemy[eCtr];
if (!tempEnemy.moveComplete){
tempEnemy.x+=tempEnemy.dx*tempEnemy.speed;
tempEnemy.y+=tempEnemy.dy*tempEnemy.speed;
tempEnemy.currentTile++;
if (tempEnemy.currentTile==enemyTiles.length){
tempEnemy.currentTile=0;
}
renderPlayField();
if (tempEnemy.x==tempEnemy.destinationX && tempEnemy.y==tempEnemy.destinationY){
tempEnemy.moveComplete=true;
enemyMoveCompleteCount++;
}
}
}
//console.log("enemyMoveCompleteCount", enemyMoveCompleteCount, "enemy.length", enemy.length);
if (enemyMoveCompleteCount >= enemy.length){
enemyMoveCompleteCount=0;
for (var eCtr=0;eCtr<enemy.length;eCtr++){
var tempEnemy=enemy[eCtr];
tempEnemy.moveComplete=false;
}
switchGameState(GAME_STATE_EVALUATE_ENEMY_MOVE);
}
}
function gameStateEvaluateEnemyMove(){
for (var eCtr=enemy.length-1;eCtr>=0;eCtr--){
var tempEnemy=enemy[eCtr];
tempEnemy.row=tempEnemy.nextRow;
tempEnemy.col=tempEnemy.nextCol;
if (playField[tempEnemy.row][tempEnemy.col]==wallTile){
tempEnemy.hit=true;
}
if (player.row==tempEnemy.row && player.col==tempEnemy.col){
tempEnemy.hit=true;
player.hit=true;
}
//check against other enemy
for (var eCtr2=enemy.length-1;eCtr2>=0;eCtr2--){
var tempEnemy2=enemy[eCtr2];
if (tempEnemy.row==tempEnemy2.row && tempEnemy.col==tempEnemy2.col && eCtr != eCtr2){
tempEnemy.hit=true;
tempEnemy2.hit=true;
}
}
}
switchGameState(GAME_STATE_EVALUATE_OUTCOME);
}
function gameStateEvaluateOutcome(){
if (player.hit){
player.dead=true;
createExplode(player);
}
for (var eCtr=enemy.length-1;eCtr>=0;eCtr--){
var tempEnemy=enemy[eCtr];
if (tempEnemy.hit){
score+=enemyScore;
tempEnemy.dead=true;
createExplode(tempEnemy)
enemy.splice(eCtr,1);
tempEnemy=null;
}
}
switchGameState(GAME_STATE_ANIMATE_EXPLODE);
}
function createExplode(object){
var newExplode={};
newExplode.currentTile=0;
newExplode.row=object.row;
newExplode.col=object.col;
newExplode.x=object.x;
newExplode.y=object.y;
newExplode.rotation=0;
explosions.push(newExplode);
}
function gameStateAnimateExplode(){
for (var eCtr=explosions.length-1;eCtr>=0;eCtr--){
var tempExplosion=explosions[eCtr];
renderPlayField();
tempExplosion.currentTile++;
if (tempExplosion.currentTile == explodeTiles.length){
explosions.splice(eCtr,1);
tempExplode=null;
}
}
if (explosions.length==0){
switchGameState(GAME_STATE_CHECK_FOR_GAME_OVER);
}
}
function gameStateCheckForGameOver() {
if (player.dead){
switchGameState(GAME_STATE_PLAYER_LOSE);
}else if (player.win){
switchGameState(GAME_STATE_PLAYER_WIN)
}else{
switchGameState(GAME_STATE_WAIT_FOR_PLAYER_MOVE);
}
}
function drawPlayField(){
for (rowCtr=0;rowCtr<15;rowCtr++){
for (colCtr=0;colCtr<15;colCtr++) {
var sourceX=Math.floor((playField[rowCtr][colCtr]) % 8) * 32;
var sourceY=Math.floor((playField[rowCtr][colCtr]) /8) *32;
if (playField[rowCtr][colCtr] != roadTile){
context.drawImage(tileSheet, 0, 0,32,32,colCtr*32,rowCtr*32,32,32);
}
context.drawImage(tileSheet, sourceX, sourceY,32,32,colCtr*32,rowCtr*32,32,32);
}
}
}
function drawPlayer(){
if (!player.dead){
context.save();
context.setTransform(1,0,0,1,0,0);
context.translate(player.x+16, player.y+16);
var angleInRadians =player.rotation * Math.PI / 180;
context.rotate(angleInRadians);
var sourceX=Math.floor(playerTiles[player.currentTile] % 8) * 32;
var sourceY=Math.floor(playerTiles[player.currentTile] /8) *32;
context.drawImage(tileSheet, sourceX, sourceY,32,32,-16,-16,32,32);
context.restore();
}
}
function drawEnemy(){
for (var eCtr=enemy.length-1;eCtr>=0;eCtr--){
tempEnemy=enemy[eCtr];
if (!tempEnemy.dead){
context.save();
context.setTransform(1,0,0,1,0,0);
context.translate(tempEnemy.x+16, tempEnemy.y+16);
var angleInRadians =tempEnemy.rotation * Math.PI / 180;
context.rotate(angleInRadians);
var sourceX=Math.floor(enemyTiles[tempEnemy.currentTile] % 8) * 32;
var sourceY=Math.floor(enemyTiles[tempEnemy.currentTile] /8) *32;
context.drawImage(tileSheet, sourceX, sourceY,32,32,-16,-16,32,32);
context.restore();
}
}
}
function drawExplosions(){
for (var eCtr=explosions.length-1;eCtr>=0;eCtr--){
tempExplosion=explosions[eCtr];
context.save();
var sourceX=Math.floor(explodeTiles[tempExplosion.currentTile] % 8) * 32;
var sourceY=Math.floor(explodeTiles[tempExplosion.currentTile] /8) *32;
//console.log("sourceX", sourceX);
//console.log("sourceY", sourceY);
//console.log("tempExplosion.x", tempExplosion.x);
//console.log("tempExplosion.y", tempExplosion.y);
context.drawImage(tileSheet, sourceX, sourceY,32,32,tempExplosion.x,tempExplosion.y,32,32);
context.restore();
}
}
function fillBackground() {
// draw background and text
context.fillStyle = '#000000';
context.fillRect(xMin, yMin, xMax, yMax);
}
function setTextStyleTitle() {
context.fillStyle = '#54ebeb';
context.font = '20px _sans';
context.textBaseline = 'top';
}
function renderPlayField() {
fillBackground();
drawPlayField();
drawPlayer();
drawEnemy();
drawExplosions();
}
document.onkeydown=function(e){
e=e?e:window.event;
keyPressList[e.keyCode]=true;
}
document.onkeyup=function(e){
//document.body.onkeyup=function(e){
e=e?e:window.event;
keyPressList[e.keyCode]=false;
};
//*** application start
switchGameState(GAME_STATE_INIT);
//**** application loop
const FRAME_RATE=40;
var intervalTime=1000/FRAME_RATE;
setInterval(runGame, intervalTime );
}
</script>
</head>
<body>
<div style="position: absolute; top: 50px; left: 50px;">
<canvas id="canvas" width="480" height="480">
Your browser does not support the HTML 5 Canvas.
</canvas>
</body>
</html>