Using NodeJS and Socket.io, I'm making a quick canvas app that moves a shape across the screen. This data will appear on all clients. Each square is timestamped to determine draw order.
Below is client.html. It says that I "cannot set property lastUpdate" of undefined. How is it considered undefined? I tried defining it so many times at the top. What's wrong?
<!DOCTYPE html>
<html lang="en">
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
"use strict";
var canvas;
var ctx;
var socket;
//var lastUpdate = new Date().getTime();
/*var square = {
lastUpdate: new Date().getTime(),
x: 0,
y: 0,
height: 100,
width: 100
};*/
//
//var person = {name: 'user' + (Math.floor((Math.random() * 1000)) + 1)};
//var user = 'user' + (Math.floor((Math.random() * 1000)) + 1);
//var user = Object.keys(something about name);
//var user = Object.keys(user);
//function person(name) {
//this.name = name;
//}
//var user = Object.keys(person);
//lets try using a prototype
/*function user(lastUpdate, x, y, width, height) {
this.lastUpdate = lastUpdate;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}*/
var name = {lastUpdate: new Date().getTime(), x: 0, y: 0, width: 100, height: 100};
var user = Object.keys(name);
var draws = {};
function updatePosition() {
var message = {
xUpdate: 10,
yUpdate: 5
}
socket.emit('movementUpdate', message);
}
/*function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(square.x, square.y, square.width, square.height);
}*/
//
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
var keys = Object.keys(draws);
for(var i = 0; i < keys.length; i++)
{
var drawCall = draws[keys[i]];
//order to draw
//gets drawcalls instead of var square
ctx.fillRect(drawCall.x, drawCall.y, drawCall.width, drawCall.height);
}
}
//
function setup() {
var time = new Date().getTime();
//console.log(time);
var x = Math.floor(Math.random()*(300-10) + 10); //random x position
var x = Math.floor(Math.random()*(300-10) + 10); //random y position
draws[user] = {lastUpdate: time, x: x, y: y, width: 100, height: 100};
}
/*function update(data) {
square = data;
redraw();
}*/
//
function handleMessage(data) {
if(!draws[data.name])
{
draws[data.name] = data.coords;
}
else if(data.coords.lastUpdate > draws[data.name].lastUpdate)
{
draws[data.name] = data.coords;
}
draw(); //redraw after updates
}
function init() {
canvas = document.querySelector("#canvas");
ctx = canvas.getContext("2d");
socket = io.connect();
socket.on('connect', function () {
//setInterval(updatePosition, 1000);
setInterval(function()
{
var time = new Date().getTime();
//console.log(time);
console.log(draws);
**draws[user].lastUpdate = time; //lastUpdate is UNDEFINED**
draws[user].x += 5;
socket.emit('draw', {name: user, coords: draws[user]});
draw();
}, 3000);
});
socket.on('updatedDraw', handleMessage);
//socket.on('updatedMovement', updatePosition); //UNDEFINED, used to be 'update'. Could it be 'handleMessage'?
}
window.onload = init;
</script>
</head>
<body>
<canvas id="canvas" height="500" width="500">Please use an HTML 5 browser</canvas>
</body>
</html>
Related
I was wondering how I could write in my html/js code a simple leaderboard with the score at the end of the game. I have a level, score and a clickcount score that I want to register.
I don't have any knowledge with databases and server and such, so I really want to keep it 'simple' because I also want to understand what I am typing.
window.addEventListener("load", function() {
//constants
var GAME_WIDTH = 640;
var GAME_HEIGHT = 360;
//keep the game going
var gameLive = true;
//current level
var level = 1;
//Count per click
var clickCount = 0;
//Score
var score = 0;
//enemies
var enemies = [{
x: 100, //x coordinate
y: 100, //y coordinate
speedY: 2, //speed in Y
w: 40, //width
h: 40 //heght
},
{
x: 200,
y: 0,
speedY: 2,
w: 40,
h: 40
},
{
x: 330,
y: 100,
speedY: 3,
w: 40,
h: 40
},
{
x: 450,
y: 100,
speedY: -3,
w: 40,
h: 40
}
];
//the player object
var player = {
x: 10,
y: 160,
speedX: 2.5,
isMoving: false, //keep track whether the player is moving or not
w: 40,
h: 40
};
//the goal object
var goal = {
x: 580,
y: 160,
w: 50,
h: 36
}
// var zonder waarde
var img = {};
var movePlayer = function() {
clickCount += 1;
player.isMoving = true;
document.getElementById('clickCount').innerHTML = clickCount;
}
var stopPlayer = function() {
player.isMoving = false;
}
//grab the canvas and context
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext("2d");
//event listeners to move player
canvas.addEventListener('mousedown', movePlayer);
canvas.addEventListener('mouseup', stopPlayer);
canvas.addEventListener('touchstart', movePlayer);
canvas.addEventListener('touchend', stopPlayer);
//img load
var load = function() {
img.player = new Image();
img.player.src = 'images/ping.png';
img.background = new Image();
img.background.src = 'images/sea.png';
img.enemy = new Image();
img.enemy.src = 'images/enemy.png';
img.goal = new Image();
img.goal.src = 'images/fish.png';
};
//update the logic
var update = function() {
//check if you've won the game
if (checkCollision(player, goal)) {
// level +1
level++;
// level in console
console.log(level);
// get player back in position
player.x = 10;
player.y = 160;
//increase the speed of the enemies by 1
//increase the speed of the enemies by 1
enemies.forEach(function(enemies) {
if (enemies.speedY > 0) {
enemies.speedY++;
} else {
enemies.speedY--;
}
});
}
//update player
if (player.isMoving) {
player.x = player.x + player.speedX;
score += 1;
}
enemies.forEach(function(element, index) {
//check for collision with player
if (checkCollision(player, element)) {
//stop the game
gameLive = false;
// alert for the level/ points/game over/ and click count
alert('Game Over!' + "\n" + "\n" + "Level: " + level + "\n" + "Score: " + score + '\n' + "Click count:" + " " + clickCount);
//reload page
window.location = "";
};
//move enemy
element.y += element.speedY;
//check borders
if (element.y <= 10) {
element.y = 10;
//element.speedY = element.speedY * -1;
element.speedY *= -1;
} else if (element.y >= GAME_HEIGHT - 50) {
element.y = GAME_HEIGHT - 50;
element.speedY *= -1;
}
});
};
//show the game on the screen
var draw = function() {
//clear the canvas
ctx.clearRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
//draw background
ctx.drawImage(img.background, 0, 0);
//draw player
ctx.drawImage(img.player, player.x, player.y);
//draw enemies
enemies.forEach(function(element, index) {
ctx.drawImage(img.enemy, element.x, element.y);
});
//draw goal
ctx.drawImage(img.goal, goal.x, goal.y);
//for seeing the level in canvas
//color points
ctx.fillStyle = "#339900";
//font points
ctx.font = "60px Michroma";
//level shower
ctx.fillText(level, 10, 55);
//point shower
ctx.font = "15px Michroma";
ctx.fillText(score, 585, 30);
};
//gets executed multiple times per second
var step = function() {
update();
draw();
if (gameLive) {
window.requestAnimationFrame(step);
}
};
//check the collision between two rectangles
var checkCollision = function(rect1, rect2) {
var closeOnWidth = Math.abs(rect1.x - rect2.x) <= Math.max(rect1.w, rect2.w);
var closeOnHeight = Math.abs(rect1.y - rect2.y) <= Math.max(rect1.h, rect2.h);
return closeOnWidth && closeOnHeight;
}
//initial kick
load();
step();
});
<div id="centerCanvas">
<canvas id="mycanvas" width="640" height="360"></canvas>
</div>
<div id="clickCount"><span>0</span></div>
A fast database setup that integrates with your script can be Google's Firebase database.
Add Firebase to your Javascript Project
Installation & Setup of Database in Javascript
How to Structure Your Databse
After running through the Firebase web portal to set up your account and project, as an example, you can use the following in your JS file to write a record to the database:
var config = {
apiKey: "yourApiKey",
authDomain: "yourProjectId.firebaseapp.com",
databaseURL: "https://yourDatabaseName.firebaseio.com"
};
firebase.initializeApp(config);
// Get a reference to the database service
var database = firebase.database();
function writeUserData(userName, clickCount, score) {
firebase.database().ref('highscores/' + name).set({
userName: userName,
clickCount: clickCount,
score: score
});
}
So I'm making a game with canvas and my object for one of the characters aren't showing up. My console didn't show any errors so I just decided to check my asteroidList object. I checked it and saw that the first character in the object's height was undefined, but I already defined it. Can someone tell me what the problem is? Here is my code:
var c = document.getElementById("game");
var ctx = c.getContext("2d");
//variables
pX = 1;
pY = 40;
pW = 54.6;
pH = 52.6;
hw = 100;
hh = 10;
asteroidSpeed = 0.05;
//load image sprites
var player = new Image();
var aster = new Image();
var enemy = new Image();
var max = new Image();
var animatedPlayer = new Image();
player.src = "player.png";
aster.src = "aster.png";
enemy.src = "enemy.png";
max.src = "max.png";
animatedPlayer.src = "animatedPlayer.png";
//keys
document.addEventListener("keydown",function (e) {
if (e.keyCode === 83) {
moveDown();
}
else if(e.keyCode === 87) {
moveUp();
}
})
function moveDown() {
pY += 2;
}
function moveUp() {
pY -= 2;
}
//asteroid constructor
asteroidList = {};
function asteroid(id,x,y,img,width,height) {
var asteroid = {
x:x,
y:y,
width:width,
height:height,
id:id
};
asteroidList['A1'] = asteroid;
}
function updateAsteroid(asteroid) {
asteroid.x -= asteroidSpeed;
ctx.drawImage(aster, asteroid.x, asteroid.y, asteroid.width, asteroid.height);
}
function draw() {
ctx.clearRect(0,0,c.width,c.height);
//characters
asteroid('A1', 250, 40, 29.6, 29.3);
ctx.drawImage(player,pX,pY,pW,pH);
setInterval(update, 40);
function update() {
//map collision
if(pY < 0) {
pY = 0;
}
if(pY > 100) {
pY = 100;
}
//enemy loop
for(var key in asteroidList) {
updateAsteroid(asteroidList[key]);
}
}
//hp
ctx.fillStyle = 'green';
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.fillRect(199,139,hw,hh);
ctx.strokeRect(199,139,100,10);
//animation call
requestAnimationFrame(draw);
}
</script>
You have an extra param called img in your asteroid function definition:
function asteroid(id, x, y, img, width, height) {
var asteroid = {
x:x,
y:y,
width:width,
height:height,
id:id
};
asteroidList['A1'] = asteroid;
}
So when you call it like:
asteroid('A1', 250, 40, 29.6, 29.3);
// asteroid(id, x, y, img, width);
you are missing to set up the height value and thus getting undefined.
I am making a reproduction function to my game test. Inside my newly created function contains the new wolf function and subtracts the x value of the object then draws it to the canvas. The only problem is the page remains static and nothing moves. I used MDN for my research on creating new functions. Any help or feedback would be much appreciated! Heres my code
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var body = document.getElementById("body");
var wolfPop = 2;
var bornWolves = 0;
var wolves = {
};
var funs = {
};
var name;
var fname;
function setupWolf(x, y, w, h){
context.fillStyle = "blue";
context.fillRect(wolves[name].x, wolves[name].y, wolves[name].w, wolves[name].h);
context.fill();
console.log("alive wolves: " + bornWolves);
}
body.style.overflow = "hidden";
body.style.margin = "0px";
canvas.style.backgroundColor = "black";
setInterval(function(){
if(wolfPop != bornWolves){
spawnWolf();
bornWolves++;
}
}, 1);
function spawnWolf(){
name = "w" + bornWolves;
rand = Math.floor(Math.random() * 100) + 1;
wolves[name] = Object.create({}, {x: {value: Math.floor(Math.random() * 450) + 1}, y: {value: Math.floor(Math.random() * 450) + 1}, h: {value: 10}, w: {value: 10}});
setupWolf();
var f1 = createWolfMove();
f1();
}
function createWolfMove(){
console.log("called");
return new Function('var k = wolves[name]; setInterval(function(){ k.x -= 1; context.fillStyle = "cornflowerblue"; context.fillRect(k.x, k.y, k.w, k.h); context.fill();}, 100);');
}
<body id="body">
<canvas id="canvas" height="500px" width="500px"></canvas>
</body>
Youre probably looking for inheritance :
You could create new wolves that inherit from a wolf class:
//setup canvas
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var body = document.getElementById("body");
body.style.overflow = "hidden";
body.style.margin = "0px";
canvas.style.backgroundColor = "black";
var wolfPop = 2;
var bornWolves = 0;
var wolves = [];
function rand(a,b=1){return Math.floor(Math.random() * a) + b;}
//constructor
function Wolf(name,x,y,w,h){
//setup
this.name=name||" w"+bornWolves;
this.x=x||rand(450);
this.y=y||rand(450);
this.w=w||10;
this.h=h||10;
//update globals
wolves.push(this);
bornWolves++;
}
Wolf.prototype={
update:function(){
context.fillStyle = "blue";
context.fillRect(this.x, this.y, this.w, this.h);
},
moving:false,
move:function(){
this.x+=rand(100,-50);//move between 50 and -50
this.y+=rand(100,-50);/
}
};
setInterval(function(){
//clear
context.clearRect(0, 0, canvas.width, canvas.height);
//update all wolves
wolves.forEach(function(wolf){
if(wolf.moving) wolf.move();
wolf.update();
}
if(wolfPop != bornWolves){
new Wolf();
}
}, 1);
//add a new wolf
var first=new Wolf(false,false,20,20);// a bit fater
first.moving=true;
I'm trying to set up a background in canvas and have some small circles just flow throughout the background, eventually I'll change the shapes and add more details in, but I'm just having trouble with the set up.
I know my code is janky, but are there any suggestions to the structure of the code?
var dx = 1;
var dy = 2;
var circle=new Circle(400,30,10);
var timer;
function Circle(x,y,r){
this.x=x;
this.y=y;
this.r=r;
}
function init() {
// Get the canvas element.
canvas = document.getElementById("canvas");
if (canvas.getContext) {
ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
}
timer=setInterval(draw, 10);
return timer;
}
function gradient (){
var my_gradient=ctx.createLinearGradient(0,0,1000,0);
my_gradient.addColorStop(0,"black");
my_gradient.addColorStop(1,"white");
ctx.fillStyle=my_gradient;
ctx.fillRect(0,0,1000,1000);
ctx.rect(0, 0, 1000, 1000);
stars();
}
function stars(){
for (i = 0; i <= 50; i++) {
// Get random positions for stars
var x = Math.floor(Math.random() * 1000)
var y = Math.floor(Math.random() * 1000)
ctx.fillStyle = "yellow";
//if (x < 30 || y < 30) ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
}
function move(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = gradient.my_gradient;
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "#003300";
drawBall(circle);
if (circle.x +dx > canvas.width || circle.x +dx < 0)
dx=-dx;
if(circle.y+dy>bar.y && circle.x>bar.x && circle.x<bar.x+barImg.width)
dy=-dy;
if (circle.y +dy > canvas.height || circle.y +dy < 0)
dy=-dy;
circle.x += dx;
circle.y += dy;
}
I tried to code a working exemple. Here stars are popping up continuously.
HTML
<!DOCTYPE html>
<html>
<head>
<title>Exemple</title>
</head>
<body>
<canvas id="viewport"></canvas>
<script src='test.js'></script>
</body>
</html>
JS
var doc = document;
var canvas = doc.getElementById('viewport');
var ctx = canvas.getContext('2d');
var settings = {
area : {
height : 100,
width : 100
}
};
canvas.width = settings.area.width;
canvas.height = settings.area.height;
function draw() {
for (var i = 10; i--;) {
var x = Math.floor(Math.random() * 1000)
var y = Math.floor(Math.random() * 1000)
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI * 2, true);
ctx.fillStyle = "yellow";
ctx.closePath();
ctx.fill();
}
}
function gameLoop (render, element) {
var running, lastFrame = +new Date;
function loop( now ) {
// stop the loop if render returned false
if ( running !== false ) {
requestAnimationFrame( loop, element );
running = render( now - lastFrame );
lastFrame = now;
}
}
loop( lastFrame );
}
gameLoop (function (deltaT) {
draw();
}, canvas );
Here is the fiddle : https://jsfiddle.net/q4q0uLht/
----- EDIT -----
/*
Basic config
*/
var doc = document,
canvas = doc.getElementById('viewport'),
ctx = canvas.getContext('2d');
var settings = {
canvas: {
height: 200,
width: 300
}
}
canvas.height = settings.canvas.height;
canvas.width = settings.canvas.width;
canvas.style.border = '1px #000 solid';
/*
easy gets a random number, inside a range of [0, x);
*/
function getRandomNumber(x) {
return parseInt(Math.random() * x, 10);
}
/*
Checks if the obj passed in argument is still in the canvas limits
*/
function incorrectPosition(obj) {
return obj.x < 0 || obj.y < 0 || obj.x > settings.canvas.width || obj.y > settings.canvas.height;
}
/*
stars array and Star object.
*/
var stars = [];
function Star(r) {
this.x = getRandomNumber(canvas.width);
this.y = getRandomNumber(canvas.height);
this.r = r || 10;
this.move = function(dx, dy) {
this.x += dx;
this.y += dy;
};
}
/*
This function adds new stars,
calculates new coordinates of each star,
and removes them from the stars array
when they are out of the canvas limits.
*/
function update() {
var len = stars.length;
if (len < 10) {
stars.push(new Star());
}
for (var i = len; i--;) {
var star = stars[i];
star.move(1, 2);
if (incorrectPosition(star)) {
stars.splice(i, 1);
}
}
}
/*
This function clears the canvas each turn and
draws each star which is stored inside the stores array.
*/
function draw() {
ctx.clearRect(0, 0, settings.canvas.width, settings.canvas.height);
var len = stars.length;
for (var i = len; i--;) {
var star = stars[i];
ctx.beginPath();
ctx.arc(star.x, star.y, 3, 0, Math.PI * 2, true);
ctx.fillStyle = "yellow";
ctx.closePath();
ctx.fill();
}
}
// Here is the loop inside which are called functions
setInterval(loop, 33);
function loop() {
update(); // update first
draw(); // then draw
}
<!DOCTYPE html>
<html>
<head>
<title>Exemple</title>
</head>
<body>
<canvas id="viewport"></canvas>
<script src='test.js'></script>
</body>
</html>
I'm trying to make a simple (or so I thought) memory game. Unfortunately it does not update state of cards when user clicks on them. I'm running out of ideas, probably because it's my first javascript game. I suppose there is a problem with game loop. Could anyone at least point me in the right direction and help me understand what needs to be changed/rewritten?
//HTML5 Memory Game implementation
//main variables
var cards = [1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8];
var exposed = [makeArray("false",16)];
var first_card = 0;
var second_card = 0;
var moves = 0;
var WIDTH = 800;
var HEIGHT = 100;
var state = 0;
var mouseX = 0;
var mouseY = 0;
//creating canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = WIDTH;
canvas.height = HEIGHT;
document.getElementById("game").appendChild(canvas);
//filling empty array with number,character,object
function makeArray(value, length) {
var newArray = [];
var i = 0;
while (i<length) {
newArray[i] = value;
i++;
}
return newArray;
}
//shuffling algorithm
function shuffle(array) {
var copy = [];
var n = array.length;
var i;
while (n) {
i = Math.floor(Math.random() * n--);
copy.push(array.splice(i, 1)[0]);
}
return copy;
}
//where user clicks
function getClickPosition(event) {
var X = event.pageX - canvas.offsetLeft;
var Y = event.pageY - canvas.offsetTop;
return mouse = [X, Y];
}
//read click position
function readPos(event) {
mousePos = getClickPosition(event);
mouseX = mousePos[0];
mouseY = mousePos[1];
}
//initializing
function init() {
state = 0;
moves = 0;
exposed = [makeArray("false",16)];
cards = shuffle(cards);
}
//drawing cards
function draw() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (var i in cards) {
if (exposed[i] === true) {
ctx.fillStyle = "rgb(250, 250, 250)";
ctx.font = "50px Courier New";
ctx.fillText(cards[i], (i*50+12), 65);
} else {
ctx.strokeStyle = "rgb(250, 0, 0)";
ctx.fillStyle = "rgb(0, 0, 250)";
ctx.fillRect(i*50, 0, 50, 100);
ctx.strokeRect(i*50, 0, 50, 100);
}
}
};
//update cards
function update() {
if (exposed[parseInt(mouseX / 50)] === false) {
if (state == 0) {
state = 1;
first_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
} else if (state == 1) {
state = 2;
second_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
} else {
if (cards[first_card] != cards[second_card]) {
exposed[first_card] = false;
exposed[second_card] = false;
}
state = 1;
first_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
}
}
}
addEventListener('click', readPos, false);
setInterval(function() {
update();
draw();
}, 16);
I would check your addEventListener method: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener
I also recommend you look into using jQuery.
After copy and pasting your code I found a couple of things:
You didn't add an event listener to anything, you should add it to something so I added it to document.
You initialize the exposed array with values "false" and later check if they are false. These are not the same, the string "false" isn't the Boolean false.
You initializes the exposed array as a multi dimensional array [[false,false,false ...]] this should be a single dimension array because later you check exposed[1] (1 depending on the mouse x position.
No need to call draw and update every 16 milliseconds, you can call it after someone clicked.
Wrapped the whole thing up in a function so there are no global variables created.
Here is the code after changing these obvious errors. There might be room for optimization but for now I've gotten the problems out.
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<div id="game"></div>
<script type="text/javascript">
(function(){
//HTML5 Memory Game implementation
//main variables
var cards = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8];
var exposed = makeArray(false, 16);
var first_card = 0;
var second_card = 0;
var moves = 0;
var WIDTH = 800;
var HEIGHT = 100;
var state = 0;
var mouseX = 0;
var mouseY = 0;
//creating canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = WIDTH;
canvas.height = HEIGHT;
document.getElementById("game").appendChild(canvas);
//filling empty array with number,character,object
function makeArray(value, length) {
var newArray = [];
var i = 0;
while (i < length) {
newArray.push(value);
i++;
}
return newArray;
}
//shuffling algorithm
function shuffle(array) {
var copy = [];
var n = array.length;
var i;
while (n) {
i = Math.floor(Math.random() * n--);
copy.push(array.splice(i, 1)[0]);
}
return copy;
}
//where user clicks
function getClickPosition(event) {
var X = event.pageX - canvas.offsetLeft;
var Y = event.pageY - canvas.offsetTop;
return mouse = [X, Y];
}
//read click position
function readPos(event) {
mousePos = getClickPosition(event);
mouseX = mousePos[0];
mouseY = mousePos[1];
update();
draw();
}
//initializing
function init() {
state = 0;
moves = 0;
exposed = makeArray(false, 16);
cards = shuffle(cards);
}
//drawing cards
function draw() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (var i in cards) {
if (exposed[i] === true) {
ctx.fillStyle = "rgb(150, 150, 150)";
ctx.font = "50px Courier New";
ctx.fillText(cards[i], (i * 50 + 12), 65);
} else {
ctx.strokeStyle = "rgb(250, 0, 0)";
ctx.fillStyle = "rgb(0, 0, 250)";
ctx.fillRect(i * 50, 0, 50, 100);
ctx.strokeRect(i * 50, 0, 50, 100);
}
}
};
//update cards
function update() {
if (exposed[parseInt(mouseX / 50)] === false) {
if (state == 0) {
state = 1;
first_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
} else if (state == 1) {
state = 2;
second_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
} else {
if (cards[first_card] != cards[second_card]) {
exposed[first_card] = false;
exposed[second_card] = false;
}
state = 1;
first_card = parseInt(mouseX / 50);
exposed[parseInt(mouseX / 50)] = true;
}
}
}
document.body.addEventListener('click', readPos, false);
init();
draw();
})();
</script>
</body>
</html>
Your overall logic was good.
The point that was 'bad' was the way you handle the event :
the event handler should store some valuable information that
the update will later process and clear.
Here you mix your update with event handling, which cannot work
especially since the event will not fire on every update.
So i did a little fiddle to show you, the main change is
the click event handler, which update the var last_clicked_card :
http://jsfiddle.net/wpymH/
//read click position
function readPos(event) {
last_clicked_card = -1;
mousePos = getClickPosition(event);
mouseX = mousePos[0];
mouseY = mousePos[1];
// on canvas ?
if ((mouseY>100)||(mouseX<0)||(mouseX>WIDTH)) return;
// now yes : which card clicked ?
last_clicked_card = Math.floor(mouseX/50);
}
and then update is the processing of this information :
//update cards
function update() {
// return if no new card clicked
if (last_clicked_card == -1) return;
// read and clear last card clicked
var newCard = last_clicked_card;
last_clicked_card=-1;
// flip, store it as first card and return
// if there was no card flipped
if (state==0) { exposed[newCard] = true;
first_card = newCard;
state = 1 ;
return; }
// just unflip card if card was flipped
if ((state = 1) && exposed[newCard]) {
exposed[newCard]=false ;
state=0;
return;
}
// we have a second card now
second_card = newCard;
exposed[second_card] = true;
draw();
// ... i don't know what you want to do ...
if (cards[first_card] == cards[second_card]) {
alert('win'); }
else {
alert('loose'); }
exposed[first_card]=false;
exposed[second_card]=false;
state=0;
}