Web Games Development · Arrays, images & game logic · ~150 minutes
Card) with a draw() method.new Image() and draw them with drawImage.setTimeout.Date and detect completion.Create a folder named Week5 and copy the photo materials into it (needed for
memoryPictures.html). Create each file below, writing the code shown. Save and refresh after each
change. Tick each checkpoint.
Week5\triangle.html
<!DOCTYPE html>
<html lang="en">
<head><title>Triangle</title></head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById("canvas").getContext("2d");
var rad = 50, centerX = 200, centerY = 200, n = 3;
var angle = (2 * Math.PI) / n;
// TODO: draw the polygon with a path
</script>
</body>
</html>
ctx.beginPath();
ctx.moveTo(centerX + rad * Math.cos(-0.5 * angle), centerY + rad * Math.sin(-0.5 * angle));
for (var i = 1; i < n; i++) {
ctx.lineTo(centerX + rad * Math.cos((i - 0.5) * angle), centerY + rad * Math.sin((i - 0.5) * angle));
}
ctx.closePath();
ctx.fill();
Week5\memoryPolygons.html
<!DOCTYPE html>
<html lang="en">
<head><title>Memory game using polygons</title></head>
<body>
<canvas id="canvas" width="900" height="400"></canvas>
<br />
Click on two cards to see if you have a match.
<form name="f">
Number of matches: <input type="text" name="count" value="0" size="1" />
Time taken: <input type="text" name="elapsed" value=" " size="4" /> seconds.
</form>
<script>
var ctx, canvas1, deck = [], firstpick = true, firstcard, secondcard, matched;
var cardrad = 30, cardwidth = 4 * cardrad, cardheight = 4 * cardrad;
var firstsx = 30, firstsy = 50, margin = 30;
// TODO: add the Card constructor and makedeck()
// TODO: add shuffle(), choose() and flipback()
function init() {
ctx = document.getElementById("canvas").getContext("2d");
canvas1 = document.getElementById("canvas");
// TODO: add the click listener, make and shuffle the deck
}
</script>
</body>
</html>
Card constructor and build the deck.
function Card(sx, sy, swidth, sheight, info) {
this.sx = sx; this.sy = sy; this.swidth = swidth; this.sheight = sheight;
this.info = info; this.draw = drawback;
}
for (var nt = 0; nt < 3 * dl; nt++) {
i = Math.floor(Math.random() * dl);
k = Math.floor(Math.random() * dl);
holder = deck[i].info; deck[i].info = deck[k].info; deck[k].info = holder;
}
canvas1.addEventListener("click", choose, false);
if (deck[i].info == deck[firstcard].info) { matched = true; }
firstpick = true;
setTimeout(flipback, 1000);
var backcolor = "rgb(128,0,128)";
var frontbgcolor = "rgb(251,215,73)";
var polycolor = "rgb(254,11,0)";
var tablecolor = "rgb(255,255,255)";
function drawback() {
ctx.fillStyle = backcolor;
ctx.fillRect(this.sx, this.sy, this.swidth, this.sheight);
}
function Polycard(sx, sy, rad, n) {
this.sx = sx; this.sy = sy; this.rad = rad; this.n = n;
this.angle = (2 * Math.PI) / n; this.draw = drawpoly;
}
function drawpoly() {
ctx.fillStyle = frontbgcolor;
ctx.fillRect(this.sx - 2 * this.rad, this.sy - 2 * this.rad, 4 * this.rad, 4 * this.rad);
ctx.beginPath();
ctx.fillStyle = polycolor;
var rad = this.rad;
ctx.moveTo(this.sx + rad * Math.cos(-0.5 * this.angle), this.sy + rad * Math.sin(-0.5 * this.angle));
for (var i = 1; i < this.n; i++) {
ctx.lineTo(this.sx + rad * Math.cos((i - 0.5) * this.angle), this.sy + rad * Math.sin((i - 0.5) * this.angle));
}
ctx.fill();
}
function makedeck() {
var cx = firstsx, cy = firstsy;
for (var i = 3; i < 9; i++) {
deck.push(new Card(cx, cy, cardwidth, cardheight, i));
deck.push(new Card(cx, cy + cardheight + margin, cardwidth, cardheight, i));
cx = cx + cardwidth + margin;
}
}
function choose(ev) {
var mx = ev.pageX, my = ev.pageY, card;
for (var i = 0; i < deck.length; i++) {
card = deck[i];
if (card.sx >= 0 && mx > card.sx && mx < card.sx + card.swidth && my > card.sy && my < card.sy + card.sheight) { break; }
}
if (i < deck.length) {
if (firstpick) {
firstcard = i; firstpick = false;
new Polycard(card.sx + cardwidth * 0.5, card.sy + cardheight * 0.5, cardrad, card.info).draw();
} else {
secondcard = i;
new Polycard(card.sx + cardwidth * 0.5, card.sy + cardheight * 0.5, cardrad, card.info).draw();
matched = (card.info == deck[firstcard].info);
if (matched) { document.f.count.value = String(1 + Number(document.f.count.value)); }
firstpick = true;
setTimeout(flipback, 1000);
}
}
}
function flipback() {
if (!matched) { deck[firstcard].draw(); deck[secondcard].draw(); }
else {
ctx.fillStyle = tablecolor;
ctx.fillRect(deck[secondcard].sx, deck[secondcard].sy, deck[secondcard].swidth, deck[secondcard].sheight);
ctx.fillRect(deck[firstcard].sx, deck[firstcard].sy, deck[firstcard].swidth, deck[firstcard].sheight);
deck[secondcard].sx = -1; deck[firstcard].sx = -1;
}
}
init() to start the game.
ctx = document.getElementById("canvas").getContext("2d");
canvas1 = document.getElementById("canvas");
canvas1.addEventListener("click", choose, false);
makedeck();
document.f.count.value = "0";
starttime = Date.now();
shuffle();
Week5\memoryPictures.html
<!DOCTYPE html>
<html lang="en">
<head><title>Memory game using pictures</title></head>
<body>
<canvas id="canvas" width="900" height="400"></canvas>
<script>
var ctx, canvas1, deck = [], firstpick = true, firstcard, secondcard, matched;
var cardwidth = 100, cardheight = 100, firstsx = 30, firstsy = 50, margin = 30;
var starttime, count = 0;
var pairs = [
// TODO: add pairs of image file names
];
// TODO: add the Card constructor and makedeck() that loads the images
// TODO: add shuffle(), choose() and flipback()
function init() {
ctx = document.getElementById("canvas").getContext("2d");
canvas1 = document.getElementById("canvas");
// TODO: add the click listener, make and shuffle the deck
}
</script>
</body>
</html>
var pairs = [
["anneGorge.jpg", "anneNow.jpg"],
["esther.jpg", "pigtailEsther.jpg"]
];
var pica = new Image();
pica.src = pairs[i][0];
ctx.drawImage(card.img, card.sx, card.sy, card.swidth, card.sheight);
Date.
starttime = new Date();
var seconds = Math.floor(0.5 + (now - starttime) / 1000);
Card constructor, deck and drawing/game functions.
var backcolor = "rgb(128,0,128)";
var tablecolor = "rgb(255,255,255)";
function Card(sx, sy, swidth, sheight, img, info) {
this.sx = sx; this.sy = sy; this.swidth = swidth; this.sheight = sheight;
this.img = img; this.info = info; this.draw = drawback;
}
function drawback() { ctx.fillStyle = backcolor; ctx.fillRect(this.sx, this.sy, this.swidth, this.sheight); }
function makedeck() {
var cx = firstsx, cy = firstsy;
for (var i = 0; i < pairs.length; i++) {
var pica = new Image(); pica.src = pairs[i][0];
var picb = new Image(); picb.src = pairs[i][1];
deck.push(new Card(cx, cy, cardwidth, cardheight, pica, i));
deck.push(new Card(cx, cy + cardheight + margin, cardwidth, cardheight, picb, i));
cx = cx + cardwidth + margin;
deck[deck.length - 2].draw();
deck[deck.length - 1].draw();
}
}
function shuffle() {
for (var nt = 0; nt < 3 * deck.length; nt++) {
var i = Math.floor(Math.random() * deck.length), k = Math.floor(Math.random() * deck.length);
var hi = deck[i].info, him = deck[i].img;
deck[i].info = deck[k].info; deck[i].img = deck[k].img;
deck[k].info = hi; deck[k].img = him;
}
}
function choose(ev) {
var mx = ev.pageX, my = ev.pageY, card;
for (var i = 0; i < deck.length; i++) {
card = deck[i];
if (card.sx >= 0 && mx > card.sx && mx < card.sx + card.swidth && my > card.sy && my < card.sy + card.sheight) { break; }
}
if (i < deck.length) {
if (firstpick) {
firstcard = i; firstpick = false;
ctx.drawImage(card.img, card.sx, card.sy, card.swidth, card.sheight);
} else {
secondcard = i;
ctx.drawImage(card.img, card.sx, card.sy, card.swidth, card.sheight);
matched = (card.info == deck[firstcard].info) && (firstcard != secondcard);
if (matched) { count++; }
firstpick = true;
setTimeout(flipback, 1000);
}
}
}
function flipback() {
if (!matched) { deck[firstcard].draw(); deck[secondcard].draw(); }
else {
ctx.fillStyle = tablecolor;
ctx.fillRect(deck[secondcard].sx, deck[secondcard].sy, deck[secondcard].swidth, deck[secondcard].sheight);
ctx.fillRect(deck[firstcard].sx, deck[firstcard].sy, deck[firstcard].swidth, deck[firstcard].sheight);
deck[secondcard].sx = -1; deck[firstcard].sx = -1;
if (count >= deck.length / 2) {
var seconds = Math.floor(0.5 + (Date.now() - starttime) / 1000);
ctx.fillStyle = tablecolor; ctx.fillRect(0, 0, 900, 400);
ctx.fillStyle = backcolor;
ctx.fillText("You finished in " + seconds + " secs.", 10, 100);
}
}
}
init() to start the game.
ctx = document.getElementById("canvas").getContext("2d");
canvas1 = document.getElementById("canvas");
canvas1.addEventListener("click", choose, false);
makedeck();
shuffle();
ctx.font = "bold 20pt sans-serif";
starttime = Date.now();
| Criterion | Points | Score |
|---|---|---|
| Polygons drawn with paths and trigonometry | 2 | |
| Card objects and deck built correctly | 3 | |
| Shuffle works | 2 | |
| Click hit-testing and matching logic | 3 | |
| Flip-back delay with setTimeout | 2 | |
| Images loaded and timed completion | 2 | |
| Runs with no console errors | 1 | |
| Total | 15 |
firstcard before flipback runs.Progress and quiz scores are also tracked on the Week 5 lab page in the class website.