*title screen

*show final score on game over
*help text
This commit is contained in:
Rob Pearce 2016-08-20 15:12:32 +10:00
parent 85b1b0ca0d
commit 2aad5e2a93
2 changed files with 438 additions and 68 deletions

443
cat.html
View File

@ -9,18 +9,15 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=devicewidth, minimal-ui" />
<!-- for apps on home screen -->
<!-- for ios 7 style, multi-resolution icon of 152x152 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-barstyle" content="black-translucent">
<link rel="apple-touch-icon" href="icon-152.png">
<link rel="apple-touch-icon" href="images/icon-152.png">
<!-- for Chrome on Android, multi-resolution icon of 196x196 -->
<meta name="mobile-web-app-capable" content="yes">
<link rel="shortcut icon" sizes="196x196" href="icon-196.png">
<link rel="shortcut icon" sizes="196x196" href="images/icon-196.png">
<style>
canvas {
@ -53,12 +50,21 @@ var GRAVITY = 0.5;
var GRIDSIZE = 80;
var THINGSIZE = 64;
var TEXTSIZE = 36; // in points
var TEXTSIZE = 16; // in points
var TEXTSPEED = 0.5;
var TEXTFADESPEED = 0.05;
var TEXTTIME = 35;
var PARADESPEED=16;
var HELPLINEWIDTH=4;
var HELPARROWSIZE=15;
var HELPTITLESIZE = 18;
var HELPTEXTSIZE = 12;
var TITLETEXTSIZE = 36;
var TITLECREDITTEXTSIZE = 16;
var TITLESTARTTEXTSIZE = 26;
var PARADESPEED=14;
var EXPLODETICKS=20;
var EXPLODEGAIN= (THINGSIZE*2) / EXPLODETICKS;
@ -67,16 +73,26 @@ var EXPLODEFADESPEED = 1.0 / EXPLODETICKS;
var LINEWIDTH=2;
var CROSSWIDTH=2;
var GRIDW = 5;
var GRIDH = 5;
var PATHARROWSIZE = 10;
var PARADELENGTH = 3;
var BOARDX = (SCREENW - (GRIDW * GRIDSIZE)) / 2;
var BOARDY = 64;
var FOODPOINTS = 10;
var LLAMAPOINTS = 100;
var CATPOINTS = 25;
var SLEEPYCATPOINTS = 5;
var overdesc = "";
var llamatext = "llama";
var image = new Array();
function loadimage(name, filename) {
@ -101,15 +117,22 @@ function getgridthing(gridx, gridy) {
}
function getthingxy(x, y) {
var i;
var i,gridx,gridy;
var thing;
// use thing coords
/*
for (i = 0; i < things.length; i += 1) {
if ((x >= things[i].x) && (x <= things[i].x + THINGSIZE-1) &&
(y >= things[i].y) && (y <= things[i].y + THINGSIZE-1)) {
return things[i];
}
}
*/
// use grid coords
gridx = Math.floor(x / GRIDSIZE);
gridy = Math.floor(y / GRIDSIZE);
return null;
return getgridthing(gridx, gridy);
}
function clearpath() {
@ -331,11 +354,15 @@ function startGame() {
loadimage('catscared', 'images/catscared.png');
loadimage('llama', 'images/alpaca.png');
loadimage('cheese', 'images/cheese.png');
loadimage('title', 'images/title.png');
game.init();
window.addEventListener('load', game.init, false);
window.addEventListener('resize', game.resize, false);
mainloop();
}
// valid types:
@ -467,8 +494,24 @@ function isadjacenttotype(what, wanttype) {
return false;
}
function drawarrowhead(ctx, x1, y1, x2, y2, col) {
function drawline(ctx,x1,y1,x2,y2,col,width) {
ctx.strokeStyle = col;
ctx.lineWidth = width;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function drawarrow(ctx,x1,y1,x2,y2,col,width, arrowsize) {
drawline(ctx, x1, y1, x2, y2, col, width);
drawarrowhead(ctx, x1, y1, x2, y2, col, arrowsize);
}
function drawarrowhead(ctx, x1, y1, x2, y2, col, size) {
var startrads,endrads;
var size2;
size2 = size * 1.5;
startrads = Math.atan((y2 - y1) / (x2 - x1));
if (x2 >= x1) {
@ -492,8 +535,8 @@ function drawarrowhead(ctx, x1, y1, x2, y2, col) {
ctx.translate(x2,y2);
ctx.rotate(endrads);
ctx.moveTo(0,0);
ctx.lineTo(10,15);
ctx.lineTo(-10,15);
ctx.lineTo(size,size2);
ctx.lineTo(-size,size2);
ctx.closePath();
ctx.restore();
ctx.fill();
@ -542,9 +585,19 @@ var game = {
this.resize();
this.interval = setInterval(updateGameArea, 20);
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
//this.interval = setInterval(mainloop, 20);
// this.canvas.addEventListener('click', this.handleclick, false);
this.canvas.addEventListener('mousedown', this.handlemousedown, false);
this.canvas.addEventListener('mouseup', this.handlemouseup, false);
this.canvas.addEventListener('mouseout', this.handlemouseup, false);
@ -556,9 +609,9 @@ var game = {
this.canvas.addEventListener('touchleave', this.handlemouseup, false);
this.canvas.addEventListener('touchmove', this.handlemousemove, false);
this.canvas.addEventListener('keypress', this.handlekeypress, false);
window.addEventListener('keypress', this.handlekeypress, false);
this.start();
this.setstate("title");
},
resize : function() {
@ -597,7 +650,6 @@ var game = {
this.initgamevars();
while (!anyvalidmoves()) {
var m;
clearthings();
@ -667,15 +719,292 @@ var game = {
this.context.fillText(texttodraw, SCREENW-16, 16);
}
} else if (game.state == "gameover") {
this.context.font = "20pt Futura";
this.context.textAlign = "center";
this.context.textBaseline = "top";
this.context.fillStyle = "red";
this.context.fillText("GAME OVER", SCREENW / 2, 16);
shadowtext(this.context, "GAME OVER", 20, "red", SCREENW / 2, 5);
shadowtext(this.context, "Final Score: " + score, 16, "white", SCREENW / 2, 35);
}
},
drawtitle : function() {
var ratio,w,h;
var img = image['title'];
var gradient;
// background
gradient = this.context.createLinearGradient(0, 0, 0, SCREENH);
gradient.addColorStop(0, "black");
gradient.addColorStop(1, "blue");
this.context.fillStyle = gradient;
this.context.fillRect(0, 0, SCREENW, SCREENH);
// image
ratio = SCREENW / img.width;
w = img.width * ratio;
h = img.height * ratio;
this.context.drawImage(img, 0, SCREENH - h, w, h);
// text
this.context.textAlign = "center";
this.context.textBaseline = "top";
shadowtext(this.context, "Cat Parade", TITLETEXTSIZE,"red", SCREENW / 2, 5);
shadowtext(this.context, "rpearce, 2016", TITLECREDITTEXTSIZE, "#00aaee", SCREENW / 2, 64);
this.context.textBaseline = "bottom";
shadowtext(this.context, "Tap to start", TITLESTARTTEXTSIZE, "#00dd00", SCREENW / 2, SCREENH - 64);
},
drawhelp : function() {
var divamt = 2;
var imgsize = THINGSIZE / divamt;
var gridsize = GRIDSIZE / divamt;
var gradient,ctx,x,y,x2,y2,curx,cury;
var row1y,row2y;
var i;
var linex = [];
var liney = [];
var textyspace = HELPTEXTSIZE * 1.5;
var textxspace = 10;
var midpoint1 = SCREENW/8 * 5;
var midpoint2 = SCREENW/8 * 4;
ctx = this.context;
// background
gradient = this.context.createLinearGradient(0, 0, 0, SCREENH);
gradient.addColorStop(0, "black");
gradient.addColorStop(1, "blue");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, SCREENW, SCREENH);
// top text
cury = textyspace*2;
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
shadowtext(ctx, "Instructions", HELPTITLESIZE,"#00aaee", SCREENW / 2, cury);
cury += textyspace;
cury += textyspace;
ctx.textAlign = "left";
ctx.textBaseline = "bottom";
shadowtext(ctx, "Drag a cat to eat cheese.", HELPTEXTSIZE,"#00cc00", textxspace, cury);
cury += textyspace;
shadowtext(ctx, " - Cats can eat any amount of cheese, but only in a straight line.", HELPTEXTSIZE,"#00cc00", textxspace, cury);
cury += textyspace;
shadowtext(ctx, " - Cats get tired after eating and cannot eat again.", HELPTEXTSIZE,"#00cc00", textxspace, cury);
cury += textyspace;
// help on eating
// row 1
x = imgsize;
y = cury;
row1y = y;
ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x2 = x + gridsize;
y2 = y;
ctx.drawImage(image['cheese'], x2, y2, imgsize, imgsize);
ctx.strokeStyle = "green";
ctx.lineWidth = LINEWIDTH;
ctx.beginPath();
ctx.moveTo(x + imgsize/2, y + imgsize/2);
ctx.lineTo(x2 + imgsize/2, y2 + imgsize/2);
ctx.stroke();
drawarrow(ctx, x + (imgsize/2), y + (imgsize/2),
x2 + (imgsize/2), y2 + (imgsize/2), "green", LINEWIDTH, PATHARROWSIZE);
cury = y2 + gridsize;
// row 2
x = imgsize;
y = cury;
row2y = y;
ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x2 = x + gridsize;
y2 = y;
ctx.drawImage(image['cheese'], x2, y2, imgsize, imgsize);
x2 = x2 + gridsize;
y2 = y;
ctx.drawImage(image['cheese'], x2, y2, imgsize, imgsize);
x2 = x2 + gridsize;
y2 = y;
ctx.drawImage(image['cheese'], x2, y2, imgsize, imgsize);
drawarrow(ctx, x + (imgsize/2), y + (imgsize/2),
x2 + (imgsize/2), y2 + (imgsize/2), "green", LINEWIDTH, PATHARROWSIZE);
cury = y2 + gridsize;
// arrow to middle
x = x2 + gridsize;
y = row1y + (imgsize);
x2 = x + gridsize*1.5;
y2 = y;
drawarrow(ctx, x, y, x2, y2, "red", HELPLINEWIDTH, HELPARROWSIZE);
// middle
ctx.textAlign = "center";
ctx.textBaseline = "top";
x = midpoint1;
y = row1y+10;
shadowtext(ctx, "+" + FOODPOINTS + " points", HELPTEXTSIZE,"#cccc00", x, y);
y = row2y-10;
shadowtext(ctx, "per cheese", HELPTEXTSIZE,"#cccc00", x, y);
// arrow to right
x = midpoint1 + gridsize + 10;
y = row1y + (imgsize);
x2 = SCREENW - imgsize*2;
y2 = y;
drawarrow(ctx, x, y, x2, y2, "red", HELPLINEWIDTH, HELPARROWSIZE);
// right
x = SCREENW - imgsize*2;
y = row1y;
ctx.drawImage(image['catfull'], x, y, imgsize, imgsize);
y = row2y;
ctx.drawImage(image['catfull'], x, y, imgsize, imgsize);
cury += textyspace;
cury += textyspace;
cury += textyspace;
// LLAMA HELP
ctx.textAlign = "left";
ctx.textBaseline = "bottom";
shadowtext(ctx, "Cats are scared of " + llamatext + "s and can't move when near them.", HELPTEXTSIZE,"#00cc00", textxspace, cury);
cury += textyspace;
x = (SCREENW / 2) - gridsize/2 - gridsize;
y = cury;
ctx.drawImage(image['catscared'], x, y, imgsize, imgsize);
x += gridsize;
y = cury;
ctx.drawImage(image['llama'], x, y, imgsize, imgsize);
x += gridsize;
y = cury;
ctx.drawImage(image['catscared'], x, y, imgsize, imgsize);
cury += textyspace;
cury += textyspace;
cury += textyspace;
cury += textyspace;
// PARADE HELP
ctx.textAlign = "left";
ctx.textBaseline = "bottom";
shadowtext(ctx, "Drag a path through multiple cats to start a parade.", HELPTEXTSIZE,"#00cc00", textxspace, cury);
cury += textyspace;
shadowtext(ctx, " - Parades can turn corners.", HELPTEXTSIZE,"#00cc00", textxspace, cury);
cury += textyspace;
shadowtext(ctx, " - Parades can include one " + llamatext + " only.", HELPTEXTSIZE,"#00cc00", textxspace, cury);
cury += textyspace;
// top line of parade
x = imgsize;
y = cury;
row1y = y;
ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
linex[0] = x + imgsize/2;
liney[0] = y + imgsize/2;
x += gridsize;
ctx.drawImage(image['catscared'], x, y, imgsize, imgsize);
linex[3] = x + imgsize/2;
liney[3] = y + imgsize/2;
x += gridsize;
ctx.drawImage(image['llama'], x, y, imgsize, imgsize);
linex[4] = x + imgsize/2;
liney[4] = y + imgsize/2;
x += gridsize;
x = imgsize;
y += gridsize;
row2y = y;
ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
linex[1] = x + imgsize/2;
liney[1] = y + imgsize/2;
x += gridsize;
ctx.drawImage(image['catfull'], x, y, imgsize, imgsize);
linex[2] = x + imgsize/2;
liney[2] = y + imgsize/2;
x += gridsize;
ctx.drawImage(image['catscared'], x, y, imgsize, imgsize);
linex[5] = x + imgsize/2;
liney[5] = y + imgsize/2;
cury = y + textyspace;
for (i = 0; i < 4; i++) {
drawline(ctx, linex[i], liney[i], linex[i+1], liney[i+1], "green", LINEWIDTH);
}
drawarrow(ctx, linex[4], liney[4], linex[5], liney[5], "green", LINEWIDTH, PATHARROWSIZE);
// arrow to middle
x = x + gridsize;
y = row1y + (imgsize);
x2 = midpoint2 - 10;
y2 = y;
drawarrow(ctx, x, y, x2, y2, "red", HELPLINEWIDTH, HELPARROWSIZE);
// explain points for parades
ctx.textAlign = "left";
ctx.textBaseline = "top";
x = midpoint2;
y = row1y;
shadowtext(ctx, "+" + CATPOINTS + " points per cat", HELPTEXTSIZE,"#cccc00", x, y);
y += textyspace;
shadowtext(ctx, "+" + SLEEPYCATPOINTS + " points per sleepy cat", HELPTEXTSIZE,"#cccc00", x, y);
y += textyspace;
shadowtext(ctx, "+" + LLAMAPOINTS + " points per " + llamatext, HELPTEXTSIZE,"#cccc00", x, y);
cury = y + textyspace;
cury += textyspace;
cury += textyspace;
cury += textyspace;
cury += textyspace;
// GAME OVER HELP
ctx.textAlign = "left";
ctx.textBaseline = "bottom";
shadowtext(ctx, "The game ends when there are no valid moves left.", HELPTEXTSIZE,"#00cc00", textxspace, cury);
cury += textyspace;
ctx.textAlign = "center";
this.context.textBaseline = "bottom";
shadowtext(this.context, "Tap to start", TITLESTARTTEXTSIZE, "#00dd00", SCREENW / 2, SCREENH - textyspace*2);
},
drawgrid : function() {
this.context.strokeStyle = "black";
this.context.beginPath();
@ -721,7 +1050,7 @@ var game = {
x2 = curpath[curpath.length-1].x + (THINGSIZE/2);
y2 = curpath[curpath.length-1].y + (THINGSIZE/2);
drawarrowhead(ctx, BOARDX + x1, BOARDY + y1, BOARDX + x2, BOARDY + y2, col);
drawarrowhead(ctx, BOARDX + x1, BOARDY + y1, BOARDX + x2, BOARDY + y2, col, PATHARROWSIZE);
}
},
@ -786,10 +1115,26 @@ var game = {
}
}
} else if (game.state == "gameover") {
game.setstate("title");
} else if (game.state == "title") {
game.setstate("help");
} else if (game.state == "help") {
game.start();
}
},
setstate : function(newstate) {
if (newstate == "help") {
// decide which word to use
if (onein(2)) {
llamatext = "llama";
} else {
llamatext = "alpaca";
}
}
this.state = newstate;
},
handlemousemove : function(event) {
var coords,adjustx,adjusty;
@ -933,6 +1278,12 @@ var game = {
},
}
function onein(num) {
var roll;
roll = Math.floor(Math.random() * num);
if (roll == 0) return true;
return false;
}
function getrandomcolour() {
var letters = '0123456789ABCDEF';
@ -959,6 +1310,19 @@ function isonscreen(x,y) {
return true;
}
function shadowtext(ctx, text, size, col, x, y) {
ctx.font = size + "pt Futura";
// shadows
ctx.fillStyle = "black";
ctx.fillText(text, x-1, y-1);
ctx.fillText(text, x+1, y);
ctx.fillText(text, x+1, y+1);
ctx.fillText(text, x-1, y+1);
// real text
ctx.fillStyle = col;
ctx.fillText(text, x, y);
}
function getrandomtype() {
var pct,type;
pct = Math.random() * 100;
@ -1114,14 +1478,14 @@ function thing(gridx, gridy, type, text) {
this.givepoints = function() {
var points = 0;
if (this.type == "food") {
points = 10;
points = FOODPOINTS;
} else if (this.type == "llama") {
points = 100;
points = LLAMAPOINTS;
} else if (this.type == "cat") {
if (this.eaten == true) {
points = 5;
points = SLEEPYCATPOINTS;
} else {
points = 25;
points = CATPOINTS;
}
}
score += points;
@ -1178,15 +1542,7 @@ function thing(gridx, gridy, type, text) {
if (this.type == "text") {
ctx.textAlign = "center";
ctx.textBaseline = "center";
// shadows
ctx.fillStyle = "black";
ctx.fillText(this.name, BOARDX + this.x-1, BOARDY + this.y-1);
ctx.fillText(this.name, BOARDX + this.x+1, BOARDY + this.y);
ctx.fillText(this.name, BOARDX + this.x+1, BOARDY + this.y+1);
ctx.fillText(this.name, BOARDX + this.x-1, BOARDY + this.y+1);
// real text
ctx.fillStyle = this.color;
ctx.fillText(this.name, BOARDX + this.x, BOARDY + this.y);
shadowtext(ctx, this.name, TEXTSIZE, this.color, BOARDX + this.x,BOARDY + this.y);
} else {
if (this.type == "cat") {
var myimage;
@ -1524,13 +1880,21 @@ function thing(gridx, gridy, type, text) {
}
}
function updateGameArea() {
function mainloop() {
var x, height, gap, minHeight, maxHeight, minGap, maxGap;
var i;
game.clear();
game.drawgrid(); // draw grid
requestAnimFrame(mainloop);
game.frameNo += 1;
game.clear();
if (game.state == "title") {
game.drawtitle();
} else if (game.state == "help") {
game.drawhelp();
} else {
game.drawgrid(); // draw grid
// move objects
for (i = 0; i < things.length; i += 1) {
things[i].move();
@ -1559,10 +1923,7 @@ function updateGameArea() {
game.state = "gameover";
}
}
//myScore.text="SCORE: " + game.frameNo;
//myScore.draw();
}
}
function anyvalidmoves() {

11
todo
View File

@ -29,7 +29,16 @@ phone fixes as per http://www.html5rocks.com/en/mobile/touch/
https://www.smashingmagazine.com/2012/10/design-your-own-mobile-game/
title screen
*title screen
*show final score on game over
*help text
bath time then next level after getting sufficient llamas?
then each level, you need to get more llamas
what does bath time give you?
use requestanimframe