My height is defined but is shown as undefined - javascript

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.

Related

Error message when using drawimage() on a pushed canvas object, not helped by preloading()

When trying to draw an image on an obstacle in an html canvas game I get this error message: Uncaught InvalidStateError: Failed to execute 'drawimage' on 'CanvasRenderingContext2D': The HTMLImageElement provided is in the 'broken' state.
The obstacle is invisible but the game still stops if the player collides with where it should be. The other stationary obstacles' images in the game are visible. What do I do?
I tried uploading the images in my html as a preload() function but it still doesn't work. Other articles about similar situations do not cover this same context and do not help me who is quite new to programming.
Here is the code:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" type="text/css" href="stylesheet.css"> <link/>
<script>
function preloader()
{
// counter
var i = 0;
// create object
imageObj = new Image();
// set image list
images = new Array();
images[0]="player.jpg"
images[1]="player2.jpg"
images[2]="obstacle.jpg"
images[3]="obstacle2.jpg"
images[3]="obstacle3.jpg"
// start preloading
for(i=0; i<=3; i++)
{
imageObj.src=images[i];
}
}
</script>
</head>
<body onload="startGame(), preloader()">
<h2> My Lost Game </h2>
<p>Press the 'up', 'down', 'left' and 'right' keys on your keyboard to move. Avoid the obstacles and reach the goal.</p><br>
<p></p>
<script>
var myObstacle = [];
function startGame() {
myGameArea.start();
myGameGoal = new component(75, 95, "player2.jpg", 710, 215, "image");
myGamePiece = new component(75, 95, "player.jpg", 10, 215, "image");
myObstacle2 = new component (110, 150, "obstacle2.jpg", 350, 0, "image");
myObstacle3 = new component (110, 150, "obstacle3.jpg", 530, 350, "image");
}
var myGameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 800;
this.canvas.height = 500;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[4]);
this.frameNo = 0;
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function (e) {
myGameArea.keys = (myGameArea.keys || []);
myGameArea.keys[e.keyCode] = true;
})
window.addEventListener('keyup', function (e) {
myGameArea.keys[e.keyCode] = false;
})
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);},
stop : function() {
clearInterval(this.interval);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
if (type == "image") {
this.image = new Image();
this.image.src = color;
}
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
if (type == "image") {
ctx.drawImage(this.image,
this.x,
this.y,
this.width, this.height);
} else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
this.crashWith = function(otherobj) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = otherobj.x;
var otherright = otherobj.x + (otherobj.width);
var othertop = otherobj.y;
var otherbottom = otherobj.y + (otherobj.height);
var crash = true;
if ((mybottom < othertop) ||
(mytop > otherbottom) ||
(myright < otherleft) ||
(myleft > otherright)) {
crash = false;
}
return crash;
}
}
function updateGameArea() {
var x, y;
for (i = 0; i < myObstacle.length; i += 1) {
if (myGamePiece.crashWith(myObstacle[i])) {
myGameArea.stop();
return;
}
}
myGameArea.clear();
myGameArea.frameNo += 1;
if (myGameArea.frameNo == 1 || everyinterval(150)) {
x = 200;
y = 300;
myObstacle.push(new component(110, 150, "obstacle1.jpg", x, y, "image"));
}
for (i = 0; i < myObstacle.length; i += 1) {
myObstacle[i].y += -1;
myObstacle[i].update();
}
myGameArea.clear();
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
if (myGameArea.keys && myGameArea.keys[37]) {myGamePiece.speedX = -3; }
if (myGameArea.keys && myGameArea.keys[39]) {myGamePiece.speedX = 3; }
if (myGameArea.keys && myGameArea.keys[38]) {myGamePiece.speedY = -3; }
if (myGameArea.keys && myGameArea.keys[40]) {myGamePiece.speedY = 3; }
myObstacle2.update();
myObstacle3.update();
myGameGoal.update();
myGamePiece.newPos();
myGamePiece.update();
}
function everyinterval(n) {
if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
return false;
}
</script>
</body>
</html>
You need to create a separate image object for each image
The code below loads images from an array of image URLs and returns an array of images in the same order as the URL names
var loading = 0; // number of images still loading
function preloader(imageURLs){
// function creates and loads an image
function createImage(url){
loading += 1; // count up when loading images
const image = new Image;
image.src = url;
image.onload = () => loading -= 1; // count down when loaded
return image;
}
const images = imageURLs.map(createImage);
return images;
}
const imageList = preloader(["player.jpg", "player2.jpg", "obstacle3.jpg"]);
// at this point loading greater than zero
When loading is 0 you know all images have loaded
Thus in your render loop
function mainLoop(){
if(loading === 0){ // all images have loaded
ctx.drawImage(imageList[0],0,0); // draw first image
ctx.drawImage(imageList[1],0,0); // draw second image
ctx.drawImage(imageList[2],0,0); // draw third image
}
requestAnimationFrame(mainLoop);
}
requestAnimationFrame(mainLoop);
Or you can have it call a function when all loaded
var loading = 0; // number of images still loading
function preloader(imageURLs, callback){
// function creates and loads an image
function createImage(url, callback){
loading += 1; // count up when loading images
const image = new Image;
image.src = url;
image.onload = () => {
loading -= 1; // count down when loaded
if(loading === 0){ // all done
callback(); // call callback
}
}
return image;
}
const images = imageURLs.map(createImage);
return images;
}
function start(){ // function to start main loop when images have loaded
requestAnimationFrame(mainLoop);
}
// second argument is the callback function that is called when all images have loaded
const imageList = preloader(["player.jpg", "player2.jpg", "obstacle3.jpg"], start);
function mainLoop(){
ctx.drawImage(imageList[0],0,0); // draw first image
ctx.drawImage(imageList[1],0,0); // draw second image
ctx.drawImage(imageList[2],0,0); // draw third image
requestAnimationFrame(mainLoop);
}

how to run html canvas AI game run as fullscreen

this is the code I tried below I wanted to run this animation project full screen of the window. when run the project it not run as an full screen please any one help me to run this application as full window thanks
window.onload = init();
function init() {
c = document.getElementById("canvas10");
ctx = c.getContext("2d");
ctx.fillStyle = "white";
//ctx.rect(0,0,1366,768);
// ctx.fill();
// Coordinates and speed of player
var x1 = 200 ;
var y1 = 420 ;
var SPEED = 4 ;
//tree creaion
var x3 = 600;
var y3 = 350;
//mouse1 creations
var x4 = 570;
vr y4 = 500;
var SPEED1 = 1;
//mouse2 creations
var x5 = 640;
var y5 = 560;
var SPEED2 = 1;
//mouse3 creations
var x6 = 700;
var y6 = 580;
var SPEED3 = 1;
//mouse4 creations
var x7 = 600;
var y7 = 540;
//roof creations
var x8 = 130;
var y8 = 500;
//fence creations
var x9 = 30;
var y9 = 500;
//leavies creations
var x10 = 380;
var y10 = 550;
//bee creation
var x11 = 680;
var y11 = 350;
// programming begins
// commands
stop = false;
var textImage = new Image(); // make image object
textImage.src = "text1.jpg"; // set the image path
var textImage2 = new Image(); // make image object
textImage2.src = "text2.jpg"; // set the image path
agentCanFeel = false;
agentCOLOR = "lightblue";
// Handle keyboard controls
var keyPress = {} ; // initialize the list that stores key presses
addEventListener ("keydown", function (e) {
keyPress[e.keyCode] = true; } , false);
addEventListener ("keyup", function (e) {
delete keyPress[e.keyCode]; } , false);
function Player(x1, y1) {
var playerImage = new Image(); // make image object
playerImage.src = "tom.png"; // set the image path
ctx.drawImage(playerImage, x1, y1, 80,70);
}
function Agent() {
ctx.beginPath();
ctx.arc (x2,y2, 50, 0 , 2 * Math.PI, false);
ctx.fillStyle = agentCOLOR;
ctx.fill();
var wingImage = new Image();
wingImage.src = "wings.jpg";
ctx.drawImage(wingImage, x2-40, y2-120 , 90 , 70);
}
//tree creation function
function tree()
{
ctx.beginPath();
ctx.fill();
var tree = new Image();
tree.src = "tree.png";
ctx.drawImage(tree, x3- 60, y3- 120 , 250 , 230);
}
//mouse creation function
function mouse()
{
ctx.beginPath();
ctx.fill();
var mouse = new Image();
mouse.src = "mouse.gif";
ctx.drawImage(mouse, x4- 60, y4- 120 , 40 , 30);
}
function mouse2()
{
ctx.beginPath();
ctx.fill();
var mouse1 = new Image();
mouse1.src = "mouse.gif";
ctx.drawImage(mouse1, x5- 60, y5- 120 , 40 , 30);
}
function mouse3()
{
ctx.beginPath();
ctx.fill();
var mouse2 = new Image();
mouse2.src = "mouse.gif";
ctx.drawImage(mouse2, x6- 60, y6- 120 , 40 , 30);
}
function mouse4()
{
ctx.beginPath();
ctx.fill();
var mouse4 = new Image();
mouse4.src = "mouse.gif";
ctx.drawImage(mouse4, x7- 60, y7- 120 , 40 , 30);
}
//cat roof creation function
function roof()
{
ctx.beginPath();
ctx.fill();
var roof = new Image();
roof.src = "roof.png";
ctx.drawImage(roof, x8- 60, y8- 120 , 150 , 130);
}
// fence behind cat
function fence()
{
ctx.beginPath();
ctx.fill();
var roof = new Image();
roof.src = "fence.png";
ctx.drawImage(roof, x9- 60, y9- 120 , 150 , 130);
}
// leavies creation
function leaves()
{
ctx.beginPath();
ctx.fill();
var roof = new Image();
roof.src = "leaves.png";
ctx.drawImage(roof, x10- 60, y10- 120 , 80 , 70);
}
// bee creation
function bee()
{
ctx.beginPath();
ctx.fill();
var bee = new Image();
bee.src = "bee.gif";
ctx.drawImage(bee, x11- 60, y11- 120 , 80 , 70);
}
function clear() {
ctx.rect(0,0,1000,600);
ctx.fill();
}
//mouse programming
function updatemouse()
{
x5 = x5 + SPEED1;
if (x5>650)
SPEED1 = SPEED1 * -1;
if (x5<600)
SPEED1 = SPEED1 * -1;
}
//end updateStuff
function updatemouse1()
{
x6 = x6 + SPEED2;
if (x6>800)
SPEED2 = SPEED2 * -1;
if (x6<600)
SPEED2 = SPEED2 * -1;
}
//end updateStuff
function updatemouse2()
{
x7 = x7 + SPEED3;
if (x7>800)
SPEED3 = SPEED3 * -1;
if (x7<600)
SPEED3 = SPEED3 * -1;
}
//end updateStuff
if (stopok == true)
{
ctx.drawImage(textImage, 100, 250); //STOP COMMAND
ctx.drawImage(textImage2, x5, y5-50); // OK RESPONSE
}//end if
function updateStuff() {
if (37 in keyPress && x1>0) // left arrorw
x1 = x1 - SPEED;
if (39 in keyPress && x1<1000) // right arrow
x1 = x1 + SPEED;
if (38 in keyPress && y1 > 20) // arrow up
y1 = y1 - SPEED;
if (50 in keyPress && y1 < 500) // arrow down
y1 = y1 + SPEED;
if (agentCanFeel == true ) {
agentCOLOR = "Red";
x4 = x4 + 2;
}
else
{
agentCOLOR = "Lightblue";
x4=x4 - 1;
}
} //end updateStuff
function drawStuff() {
Player(x1,y1);
// Agent();
// mouse();
mouse2();
mouse3();
mouse4();
roof();
tree();
fence();
leaves();
bee();
} //end drawStuff
function gameLoop() {
clear();
updateStuff();
drawStuff();
updatemouse();
updatemouse1();
updatemouse2();
setTimeout(gameLoop, 20); //call game loop every 20 mili sec
} //end gameloop
gameLoop();
} //end init function

how do i get my balls to move down the canvas after a short period of time?

I am trying to get my balls, in the array, to move directly down the canvas after a short period of time, one after the other to equal exactly 100 balls dropped. I included all of my code to try and show more of what i want the program to do.
Really the balls spawn and a user controls the paddle scoring points for each ball hit. Their are radio buttons that can be checked to make the balls fall faster or slower.
Im just stuck on getting the balls to move down the canvas one at a time.
var posY = 0;
var spawnRateOfDescent = 2;
var spawnRate = 500;
var lastSpawn = -1;
var balls = [100];
var startTime = Date.now();
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
function checkRadio() {
if (document.getElementById("moderate").checked == true) {
spawnRate = 250;
} else if (document.getElementById("hard").checked == true) {
spawnRate = 100;
} else if (document.getElementById("easy").checked == true) {
spawnRate = 500;
}
}
function startGame() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
baton = new batonPiece(50, 10, "28E060", 210, 250)
}
function ball() {
this.x = Math.random() * (canvas.width - 30) + 15;
this.y = 0;
this.radius = 10;
this.color = randomColor();
this.draw = function () {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
ctx.fillStyle = randomColor();
ctx.fill();
ctx.closePath();
}
}
var balls = [];
for (var i = 0; i < 100; i++) {
balls[i] = new ball();
balls[i].draw();
}
function batonPiece(width, height, color, x, y) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
function randomColor() {
var letter = "0123456789ABCDEF".split("");
var color = "#";
for (var i = 0; i < 6; i = i + 1) {
color += letter[Math.round(Math.random() * 15)];
}
return color;
}
function moveLeft() {
batonPiece.x -= 1;
}
function moveRight() {
baton.x += 1;
}
function stopMove() {
baton.x = 0;
}

How to fillStyle all circles in different color in canvas: red, yellow, blue and green?

I am looking for a way to fillStyle of all circles in 4 colors: #00ce66, #e3bf37, #cc5543, #a1b7c2.
I want circles to show in the way: 25% of circles are red, 25% circles are yellow… etc. on canvas while the page is loaded.
When I added Math.random() and put inside the colors, circles are black. Please help :-)
(function() {
var width, height, largeHeader, canvas, ctx, circles, target, animateHeader = true;
// Main
initHeader();
addListeners();
function initHeader() {
width = window.innerWidth;
height = window.innerHeight;
target = {x: 0, y: height};
largeHeader = document.getElementById('large-header');
largeHeader.style.height = height+'px';
canvas = document.getElementById('canvas');
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
// create particles
circles = [];
for(var x = 0; x < width*0.2; x++) {
var c = new Circle();
circles.push(c);
}
animate();
}
// Event handling
function addListeners() {
window.addEventListener('scroll', scrollCheck);
window.addEventListener('resize', resize);
}
function scrollCheck() {
if(document.body.scrollTop > height) animateHeader = false;
else animateHeader = true;
}
function resize() {
width = window.innerWidth;
height = window.innerHeight;
largeHeader.style.height = height+'px';
canvas.width = width;
canvas.height = height;
}
function animate() {
if(animateHeader) {
ctx.clearRect(0,0,width,height);
for(var i in circles) {
circles[i].draw();
}
}
requestAnimationFrame(animate);
}
// Canvas manipulation
function Circle() {
var _this = this;
// constructor
(function() {
_this.pos = {};
init();
console.log(_this);
})();
function init() {
_this.pos.x = Math.random()*width;
_this.pos.y =-50;
_this.alpha = 0.1+Math.random()*0.9;
_this.scale = 0.1+Math.random()*1;
_this.velocity = Math.random();
}
this.draw = function() {
if(_this.alpha <= 0) {
init();
}
_this.pos.y -= -_this.velocity;
_this.alpha -= 0.0005;
ctx.beginPath();
ctx.arc(_this.pos.x, _this.pos.y, _this.scale*10, 0, 2 * Math.PI, false);
ctx.fillStyle = 'rgba(16,239,173,'+ _this.alpha+')';
ctx.fill();
};
}
})();
You can create an array with the 4 colors and choose a random one at the creation of each circle.
Here is code for the Circle function:
function Circle() {
var _this = this;
// constructor
(function() {
_this.pos = {};
init();
console.log(_this);
})();
function init() {
_this.pos.x = Math.random()*width;
_this.pos.y =-50;
_this.alpha = 0.1+Math.random()*0.9;
_this.scale = 0.1+Math.random()*1;
_this.velocity = Math.random();
var colors = [[0,206,102], [227, 191, 55], [204,85,67], [161,183, 194]];
var random_index = Math.floor(0 + (Math.random() * ((3 + 1) - 0)));
_this.color = colors[random_index];
}
this.draw = function() {
if(_this.alpha <= 0) {
init();
}
_this.pos.y -= -_this.velocity;
_this.alpha -= 0.0005;
ctx.beginPath();
ctx.arc(_this.pos.x, _this.pos.y, _this.scale*10, 0, 2 * Math.PI, false);
var c = _this.color;
ctx.fillStyle = 'rgba('+c[0]+','+c[1]+','+c[2]+','+ _this.alpha+')';
ctx.fill();
};
}

Simple memory game doesn't update its state. Bad game loop?

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;
}

Categories