Well I was bored over the past week so I spend a little while creating this game using html5 canavas. The basic objective of the game is to make boxes by drawing lines. You can play against the computer. In terms of the AI, the computer is pretty stupid. It'll take boxes you give it but other than that it basically just draws random lines. Let me know what you think/how can I improve it? [hide=code]
<!DOCTYPE html>
<html>
<head><title>Dots</title></head>
<script type="text/javascript">
var turn = 0; //0 for human, 1 for computer
var canvas;
var timeCountInterval, compTurnInterval;
var time = 0;
var clickedX, clickedY;
var dX, dY, mode;
var fakeDrawn = false;
var barsArr = new Array(450);
var gameOn;
var humanLastX, humanLastY, humanLastMode;
var totalBoxes = 0;
function draw_border(){
canvas = document.getElementById("dotboard");
var context = canvas.getContext("2d");
context.fillStyle = "#000000";
context.fillRect(0,0,500,500);
context.fillStyle = "#FFFFFF";
context.fillRect(1,1,498,498);
}
function clear_canvas() {
canvas = document.getElementById("dotboard");
canvas.width = 1;
canvas.width = 500;
}
function update_screen() {
clear_canvas();
draw_border();
}
function inc_time(){
time = time + 1;
timeDiv = document.getElementById("time");
timeDiv.innerHTML = "Time spent: " + time + " seconds";
}
function incrementScore(type){
var table;
totalBoxes = totalBoxes + 1;
switch(type){
case 0:
table = document.getElementById("yourScore");
break;
case 1:
table = document.getElementById("machineScore");
break;
default:
break;
}
currentScore = parseInt(table.innerHTML);
finalScore = currentScore + 1;
table.innerHTML = finalScore;
}
function incrementTurns(type){
var table;
switch(type){
case 0:
table = document.getElementById("yourTurn");
break;
case 1:
table = document.getElementById("machineTurn");
break;
default:
break;
}
currentTurns = parseInt(table.innerHTML);
finalTurns = currentTurns + 1;
table.innerHTML = finalTurns;
}
function dot(x, y){
canvas = document.getElementById("dotboard");
var context = canvas.getContext("2d");
context.fillStyle = "#000000";
context.fillRect(x, y, 5, 5);
}
function draw_dots(){
for (IY=1;IY<=15;IY++){
for (IX=1;IX<=15;IX++){
xval = IX * 30;
yval = IY * 30;
dot(xval, yval);
}
}
}
function fake_lines(event){
if (fakeDrawn){
line(fakeX, fakeY, 4, fakeMode);
fakeX = 2;
fakeY = 2;
fakeMode = "v";
}
clickedX = event.clientX - 8;
clickedY = event.clientY - 8;
if ((clickedX < 31) || (clickedX > 454)){
return false; //outside clickable x
} else if ((clickedY < 31) || (clickedY > 454)){
return false; //outside clickable y
}
if (get_pipeLine(clickedX, clickedY)){
if (line(dX, dY, 1, mode)){
fakeX = dX;
fakeY = dY;
fakeMode = mode;
fakeDrawn = true;
} else {
return false;
}
}
}
function comp_doTurn(){
if (turn != 1) {
return false;
}
if (gameOn == false){
return false;
}
if (totalBoxes >= 196){
game_over();
return false;
}
//this HAS to be improved - unacceptable think times near game end (when most options return false), more than a minute
//randomly generate clickedX and clickedY here. easy way is just w/e random numbers but it should be done properly
//should also call game_over
/*clickedX = (Math.floor(Math.random()*450) + 30);
clickedY = (Math.floor(Math.random()*450) + 30);
if (get_pipeLine(clickedX, clickedY)){
if (line(dX, dY, 3, mode)) {
if (do_check_score(dX, dY, mode)){
} else {
turn = 0; }
}
}*/
var hX, hY, hMode;
hX = humanLastX;
hY = humanLastY;
hMode = humanLastMode;
var canScore = true;
while (canScore == true){
//if can't score
canScore = false;
}
var vLR, vLL, vLRA, vLRB, vLLA, vLLB;
var hLB, hLA, hLBR, hLAR, hLBL, hLAL;
if (hMode == "v") {
vLR = line_exists(hX + 30, hY);
vLL = line_exists(hX - 30, hY);
vLRA = line_exists(hX + 4, hY - 4);
vLRB = line_exists(hX + 4, hY + 26);
vLLA = line_exists(hX - 26, hY - 4);
vLLB = line_exists(hX - 26, hY + 26);
if (vLR || vLL){
if (vLR && (vLRA || vLRB)){
if (vLRA){
if (get_pipeLine(hX + 4, hY + 26)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
} else if (vLRB){
if (get_pipeLine(hX + 4, hY - 4)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
}
} else if (vLL && (vLLA || vLLB)){
if (vLLA){
if (get_pipeLine(hX - 26, hY + 26)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
} else if (vLLB){
if (get_pipeLine(hX - 26, hY - 4)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
}
}
} else if (vLRA || vLRB){
if (vLRA && (vLR || vLRB)){
if (vLR){
if (get_pipeLine(hX - 26, hY + 26)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
} else if (vLRB){
if (get_pipeLine(hX + 30, hY)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
}
}
} else if (vLLA || vLLB){
if (vLLA && (vLLB || vLL)){
if (vLLB){
if (get_pipeLine(hX - 30, hY)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
} else if (vLL){
if (get_pipeLine(hX - 26, hY + 26)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
}
}
}
} else if (hMode == "h"){
hLB = line_exists(hX, hY + 30);
hLA = line_exists(hX, hY - 30);
hLBR = line_exists(hX + 26, hY + 4);
hLAR = line_exists(hX + 26, hY - 26);
hLBL = line_exists(hX - 4, hY + 4);
hLAL = line_exists(hX - 4, hY - 26);
if (hLB || hLA){
if (hLB && (hLBL || hLBR)){
if (hLBL){
if (get_pipeLine(hX + 26, hY + 4)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
} else if (hLBR){
if (get_pipeLine(hX - 4, hY + 4)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
}
} else if (hLA && (hLAL || hLAR)){
if (hLAL){
if (get_pipeLine(hX + 26, hY - 26)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
} else if (hLAR){
if (get_pipeLine(hX - 4, hY - 26)){
if (line(dX, dY, 3, mode)){
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
}
}
} else if (hLBR || hLBL){
} else if (hLAR || hLAL){
}
//alert("hLB: " + hLB + "\n hLA: " + hLA + "\n hLBR: " + hLBR + "\n hLAR: " + hLAR + "\n hLBL: " + hLBL + "\n hLAL: " + hLAL);
}
//after all this we'll have to clear hmode and all that to try other stuff
var went = false;
while (went == false) {
clickedX = (Math.floor(Math.random()*424) + 30);
clickedY = (Math.floor(Math.random()*424) + 30);
if (get_pipeLine(clickedX, clickedY)){
if (line(dX, dY, 3, mode)) {
incrementTurns(turn);
if (do_check_score(dX, dY, mode)){
} else {
went = true;
}
}
}
}
turn = 0;
return true;
}
function do_check_score(x, y, mode){
var captured = false;
if (mode == "v") {
if (line_exists(x + 30, y )){
if (line_exists(x + 4, y - 4)){
if (line_exists(x + 4, y + 26)){
square(x + 4, y, turn);
incrementScore(turn);
captured = true;
}
}
}
if (line_exists(x - 30, y)){
if (line_exists(x - 26, y - 4)){
if (line_exists(x - 26, y + 26)){
square(x - 26, y, turn);
incrementScore(turn);
captured = true;
}
}
}
if (captured == true) {
return true;
} else {
return false;
}
} else if (mode == "h"){
if (line_exists(x, y - 30)){
if (line_exists(x - 4, y - 26)){
if (line_exists(x + 26, y - 26)){
square(x, y - 26, turn);
incrementScore(turn);
captured = true;
}
}
}
if (line_exists(x, y + 30)){
if (line_exists(x - 4, y + 4)){
if (line_exists(x + 26, y + 4)){
square(x, y + 4, turn);
incrementScore(turn);
captured = true;
}
}
}
if (captured == true) {
return true;
} else {
return false;
}
}
}
function line(x, y, mode, vOrH){
canvas = document.getElementById("dotboard");
var context = canvas.getContext("2d");
var newmode;
switch (mode){
case 1://human hover
context.fillStyle = "#5DFC0A";
newmode = 0;
break;
case 2://human click
context.fillStyle = "#0BB5FF";
newmode = 1;
break;
case 3://comp click
context.fillStyle = "#FF6600";
newmode = 2;
break;
case 4://clear
context.fillStyle = "#FFFFFF";
newmode = 0;
break;
default:
return false;
break;
}
if (vOrH == "v"){
xx = 3;
yy = 25;
} else if (vOrH == "h"){
xx = 25;
yy = 3;
}
if (line_exists(x, y) == false){
context.fillRect(x, y, xx, yy);
if (newmode != 0){
addToArray(x, y, newmode);
return true;
} else {
return true;
}
} else {
return false;
}
}
function square(x, y, mode){
canvas = document.getElementById("dotboard");
var context = canvas.getContext("2d");
switch (mode){
case 0://human click
context.fillStyle = "#0BB5FF";
break;
case 1://comp click
context.fillStyle = "#FF6600";
break;
default:
return false;
break;
}
context.fillRect(x, y, 25, 25);
}
function line_exists(x, y){
for (w=0;w<barsArr.length;w++){
if (barsArr[w][0] == x){
if (barsArr[w][1] == y) {
if (barsArr[w][2] == 0){
return false;
} else {
return true;
}
}
}
}
return false;
}
function addToArray(x, y, mode){
for (w=0;w<barsArr.length;w++){
if(!barsArr[w][0]){
barsArr[w][0] = x;
barsArr[w][1] = y;
barsArr[w][2] = mode;
return true;
}
}
}
//game will deadlock if i do last move (waiting on me before comp goes)
function do_humanTurn(event){
if (turn != 0){
return false;
}
if (gameOn == false){
alert("the game is over!");
return false;
}
if (totalBoxes >= 196){
game_over();
return false;
}
clickedX = event.clientX - 8;
clickedY = event.clientY - 8;
if ((clickedX < 31) || (clickedX > 454)){
return false; //outside clickable x
} else if ((clickedY < 31) || (clickedY > 454)){
return false; //outside clickable y
}
if (get_pipeLine(clickedX, clickedY)){
if (line(dX, dY, 2, mode)) {
incrementTurns(turn);
if (do_check_score(dX, dY, mode)) {
} else {
turn = 1;
humanLastX = dX;
humanLastY = dY;
humanLastMode = mode;
return true;
}
} else {
return false;
}
}
}
function get_pipeLine(cX, cY){
for (i=0;i<5;i++){
obj = (cX - i) % 30;
if (obj == 0){
for (a=0;a<5;a++){
obj2 = (cY - a) % 30;
if (obj2 == 0){
return false;
}
}
for (b=0;b<30;b++){
obj3 = (cY - b) % 30;
if (obj3 == 0){
dY = (cY - b) + 5;
mode = "v";
dX = (cX - i) + 1;
return true;
}
}
}
}
for (i=0;i<5;i++){
obj = (cY - i) % 30;
if (obj == 0){
for (a=0;a<5;a++){
obj2 = (cX - a) % 30;
if (obj2 == 0){
return false;
}
}
for (b=0;b<30;b++){
obj3 = (cX - b) % 30;
if (obj3 == 0){
dX = (cX - b) + 5;
mode = "h";
dY = (cY - i) + 1;
return true;
}
}
}
}
return false;
}
function clearIntervals(){
clearInterval(timeCountInterval);
clearInterval(compTurnInterval);
}
function game_over(){
clearIntervals();
gameOn = false;
compScore = parseInt(document.getElementById("machineScore").innerHTML);
yourScore = parseInt(document.getElementById("yourScore").innerHTML);
if (compScore == yourScore){
alert("Tie game: " + compScore + " to " + yourScore + ". Random...");
} else if (yourScore > compScore){
alert("You win: " + yourScore + " to " + compScore + ". Great job!");
} else if (yourScore < compScore){
alert("You lost: " + compScore + " to " + yourScore + ". You got owned!");
}
}
window.onload = function(){
for (q=0;q<barsArr.length;q++){
barsArr[q] = new Array(3);
}
draw_border();
draw_dots();
timeCountInterval = setInterval("inc_time()", 1000);
compTurnInterval = setInterval("comp_doTurn()", 1000);
gameOn = true;
}
</script>
<canvas id="dotboard" width="500" height="500" onclick="do_humanTurn(event);return false" onmousemove="fake_lines(event);return false">
<body>
<p>It isn't working :-(.</p>
</canvas><br /><br />
<div id="score">
<table id="theTable" cellpadding="10" border="1px">
<tr>
<td></td>
<td><b><span style="color:#0BB5FF"> You </b></span></td>
<td><b><span style="color:#FF6600">Le machine</b></span></td>
</tr>
<tr id="scores">
<td><b>Score:</b></td>
<td id="yourScore">0</td>
<td id="machineScore">0</td>
</tr>
<tr id="turns">
<td><b>Turns:</b></td>
<td id="yourTurn">0</td>
<td id="machineTurn">0</td>
</tr>
</table>
</div><br />
<div id="time">
Time spent: 0 seconds
</div>
</body>
</html>
[/hide] Just save the above code into a .html file and open it on an html5 compliant browser (any new browser should work).