*move goal progress increments to thing.kill() function

*Make 'allowedthings' default to previous level's one.
*fix lev6 help
*bugfix: whitecats aren't ever appearing randomly?
*new object: bricks
*Don't allow extending path off the top of the grid.
*fix incorrect pluralisation "foods" in goal text
This commit is contained in:
Rob Pearce 2016-08-31 13:55:35 +10:00
parent b5dedbe0ad
commit 9176b45a50
6 changed files with 518 additions and 101 deletions

571
cat.html
View File

@ -74,6 +74,8 @@ var TURNSBARSPEEDUP = 0.02;
var TURNSBARSPEEDDOWN = 0.01;
var BAGCAPACITY = 6; // how many cats to pop a bag
var BRICKHP = 9; // how many cats it takes to remove a brick
var SLASHDIST = 3; // space between slash marks on bricks
// for background
var catalpha = 1.0;
@ -90,14 +92,16 @@ var GOALVERB = {
'cat': 'Clear',
'goat': 'Clear',
'door': 'Enter',
'sun': 'Wait out',
'sunlight': 'Wait out',
'bag': 'Burst',
'toad': 'Slap',
'whitecat': 'Attack',
'brick': 'Break',
};
var GOALNAME = {
'whitecat': 'white cat',
'sunlight': 'sun',
};
var prizetypes = [
@ -300,6 +304,21 @@ function loadimage(name, filename) {
image[name].src = filename;
}
function gridxyhasthingtype(gridx, gridy, wanttype) {
var i;
if (things == undefined) return null;
// only include non-animating things
for (i = 0; i < things.length; i += 1) {
if ((things[i].gridx == gridx) && (things[i].gridy == gridy) && (things[i].type == wanttype)) {
if (!things[i].isanimating()) {
return things[i];
}
}
}
return null;
}
function getgridthing(gridx, gridy) {
var i;
if (things == undefined) return null;
@ -572,6 +591,10 @@ function canextendpath(overthing) {
if (!overthing) return false;
if (!isongrid(overthing.gridx, overthing.gridy)) {
return false;
}
pathtype = getpathtype();
if ( isadjacent(overthing, curpath[curpath.length-1]) && // adjacent to last thing in path?
@ -829,6 +852,50 @@ function isadjacenttotype(what, wanttype, exceptionthing) {
return false;
}
function addslash(slashes, w, h) {
slashes.push(Math.floor(rnd(w))); // x1
slashes.push(Math.floor(rnd(h))); // y1
slashes.push(Math.floor(rnd(w))); // x2
slashes.push(Math.floor(rnd(h))); // y2
}
function drawslashes(ctx, x, y, slashes) {
var i,n;
if (slashes == undefined || slashes.length <= 0) {
return;
}
for (i = 0; i < slashes.length; i+= 4) {
var dx,dy,xstep,ystep,angle;
// get angle of line
dx = slashes[i+2] - slashes[i];
dy = slashes[i+1] - slashes[i+3];
//console.log("dxy is " + dx + "," + dy);
angle = Math.atan2(dy,dx);
//angle *= 180/Math.PI; // degrees
// add 90 degrees
angle += 90;
// back to radians
//angle *= Math.PI/180;
xstep = Math.cos(angle);
ystep = Math.sin(angle);
//console.log("line " + i + " - angle is " + (angle * 180/Math.PI) + " steps are " + xstep + "," + ystep);
for (n = 0; n < 3; n++) {
var modx,mody;
modx = xstep * n * SLASHDIST;
mody = ystep * n * SLASHDIST;
drawline(ctx, x + slashes[i] + modx, y + slashes[i+1] + mody,
x + slashes[i+2] + modx, y + slashes[i+3] + mody,
"black", 1);
}
}
}
function drawline(ctx,x1,y1,x2,y2,col,width) {
ctx.strokeStyle = col;
ctx.lineWidth = width;
@ -1276,6 +1343,18 @@ var game = {
},
// x1, x2, y2, x3, y3....
addlevelbricks : function () {
var lev,newbrick,i;
lev = this.levels.length - 1;
for (i = 0 ; i < arguments.length; i += 2) {
newbrick = new Object();
newbrick.gridx = arguments[i];
newbrick.gridy = arguments[i+1];
this.levels[lev].bricks.push(newbrick);
}
},
addlevelbag : function (lev, y ) {
var mybag;
mybag = new Object();
@ -1294,9 +1373,9 @@ var game = {
mylevel.goals = new Array();
mylevel.thinglist = new Array();
mylevel.forcelist = new Array();
mylevel.allowedthings = new Array();
mylevel.maxturns = lev + 4; // default
mylevel.bags = [];
mylevel.bricks = [];
if (lev == 1) {
mylevel.gridsize = DEF_GRIDSIZE;
@ -1313,6 +1392,14 @@ var game = {
mylevel.boardx = this.levels[lev-1].boardx;
}
mylevel.allowedthings = new Array();
if (lev > 1) {
// default to allowed things from previous level.
for (i = 0; i < this.levels[lev-1].allowedthings.length; i++) {
mylevel.allowedthings.push(this.levels[lev-1].allowedthings[i]);
}
}
this.levels[lev] = mylevel;
playerdata.levscore[lev] = 0;
@ -1388,6 +1475,8 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
progress : function(type, amt) {
var i;
if (game.state != "running") return false;
// past last level!
if (curlevel >= game.levels.length) return false;
@ -1473,6 +1562,10 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
min += GOATPOINTS * this.levels[lev].goals[i].count;
turnsreq += this.levels[lev].goals[i].count * 1;
break;
case "brick":
min += Math.min(CATPOINTS, SLEEPYCATPOINTS) * (BRICKHP/3) * this.levels[lev].goals[i].count;
turnsreq += this.levels[lev].goals[i].count * (BRICKHP/3); // avg parades to kill it, maybe a bit less
break;
case "turn":
// assume you'll get a parade on most turns.
num = (Math.min(CATPOINTS, SLEEPYCATPOINTS) * this.levels[lev].goals[i].count);
@ -1542,6 +1635,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
this.levels = [];
this.addlevel(1, true);
this.addlevelgoals("food", 5);
this.addlevelallowedthings("cat", "food");
this.setstarpoints(1, 50, 60, 80);
this.addlevelthings( "cat", 50, "food", 50);
@ -1550,41 +1644,38 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
this.addlevelthings("cat", 45, "food", 55);
this.addlevel(3, true);
this.addlevelallowedthings("cat", "food", "llama");
this.addlevelallowedthings("llama");
this.addlevelgoals("llama", 4);
this.addlevel(4, true);
this.addlevelgoals("llama", 5);
this.addlevelgoals("food", 5);
this.addlevelallowedthings("cat", "food", "llama");
this.addlevel(5, true);
this.addlevelgridwid(5, 6);
this.addlevelgoals("bag", 1);
this.addlevelgoals("turn", 10);
//this.addlevelgoals(5, "points", 600);
this.addlevelallowedthings("cat", "food", "llama");
// introduce goats!
this.addlevel(6, true);
this.addlevelallowedthings("goat");
this.addlevelgoals("goat", 3);
this.addlevelthings("goat", 10, "cat", 50, "food", 30, "llama", 10); // higher than normal goat chance
this.addlevelforcethings("goat", 1);
this.addlevel(7, false);
this.addlevelallowedthings("goat", "cat", "food", "llama");
this.addlevelgoals("llama", 6);
this.addlevelgoals("goat", 3);
this.addlevel(8, false);
this.addlevelallowedthings("goat", "cat", "food", "llama");
this.addlevelgoals("llama", 6);
this.addlevelgoals("goat", 4);
this.addlevelgoals("food", 5);
// introduce doors
this.addlevel(9, true);
this.addlevelallowedthings("goat", "cat", "food", "llama", "door");
this.addlevelallowedthings("door");
this.addlevelgoals("door", 1);
this.addlevelgoals("llama", 5);
this.addlevelgoals("cat", 13);
@ -1592,20 +1683,19 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
this.addlevel(10, false);
this.addlevelgridwid(10, 7);
this.addlevelallowedthings("goat", "cat", "food", "llama", "door");
this.addlevelgoals("turn", 15);
// introduce sunlight
this.addlevel(11, true);
this.addlevelallowedthings("goat", "cat", "food", "llama", "door", "sunlight");
this.addlevelallowedthings("sunlight");
this.addlevelgoals("cat", 13);
this.addlevelgoals("food", 5);
this.addlevelgoals("sun", 1);
this.addlevelgoals("sunlight", 1);
this.addlevelforcethings("sunlight", 1);
// introduce whitecat
this.addlevel(12, true);
this.addlevelallowedthings("goat", "cat", "food", "llama", "door", "sunlight", "whitecat");
this.addlevelallowedthings("whitecat");
this.addlevelgoals("cat", 15);
this.addlevelgoals("whitecat", 1);
this.addlevelgoals("llama", 6);
@ -1613,24 +1703,45 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
// introduce toad
this.addlevel(13, true);
this.addlevelallowedthings("goat", "cat", "food", "llama", "door", "sunlight", "toad");
this.addlevelallowedthings("toad");
this.addlevelgoals("toad", 1);
this.addlevelgoals("cat", 20);
this.addlevelgoals("llama", 5);
this.addlevelforcethings("toad", 1);
this.addlevel(14, false);
this.addlevelallowedthings("goat", "cat", "food", "llama", "door", "sunlight", "toad");
this.addlevelgoals("cat", 25);
this.addlevelgoals("llama", 6);
this.addlevelgoals("food", 15);
this.addlevel(15, false);
// introduce bricks
this.addlevel(15, true);
this.addlevelgridwid(15, 8);
this.addlevelallowedthings("goat", "cat", "food", "llama", "door", "sunlight", "toad");
this.addlevelgoals("cat", 30);
this.addlevelgoals("llama", 7);
this.addlevelgoals("food", 20);
this.addlevelallowedthings("brick");
this.addlevelgoals("brick", 2);
this.addlevelbricks(3, 3,
4, 4
);
this.addlevel(16, false);
this.addlevelbricks(3, 3, 4, 3,
3, 4, 4, 4
);
this.addlevelgoals("brick", 4);
this.addlevel(17, false);
this.addlevelbricks(0,4, 1,4, 2,4, 3,4, 4,4, 5,4, 6,4, 7,4);
this.addlevelgoals("cat", 25);
this.addlevelgoals("llama", 6);
/*
hard brick pattern
this.addlevelbricks(2, 2, 5, 2,
2, 5, 5, 5
);
*/
for (i = 1; i < this.levels.length; i++) {
var extrastars;
@ -1671,16 +1782,25 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
populategrid : function() {
var i;
while (!anyvalidmoves()) {
var x,y,found;
var x,y,found,i;
console.log("populating grid...");
clearthings();
// populate initial things
// add bricks
for (i = 0; i < game.levels[curlevel].bricks.length; i++) {
x = game.levels[curlevel].bricks[i].gridx;
y = game.levels[curlevel].bricks[i].gridy;
things.push(new thing(x, y, "brick"));
console.log("adding brick at " + x + "," + y);
}
// populate initial things in all other spots
for (y = 0; y < GRIDH; y++) {
for (x = 0; x < GRIDW; x++) {
// start off above the grid
things.push(new thing(x, y, "random"));
if (!getgridthing(x, y)) {
things.push(new thing(x, y, "random"));
}
}
}
@ -1698,8 +1818,11 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
// while we don't have enough...
while (countthingsoftype(wanttype) < wantnum) {
// add one.
var idx;
idx = rnd(things.length);
var idx = -1;
// don't overwrite bricks
while (idx == -1 || things[idx].type == "brick") {
idx = rnd(things.length);
}
things[idx].type = wanttype;
donesomething = true;
}
@ -1944,7 +2067,9 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
// goal description
var ess = "s";
if (this.levels[curlevel].goals[n].count == 1) {
if (this.levels[curlevel].goals[n].type == "food") {
ess = "";
} else if (this.levels[curlevel].goals[n].count == 1) {
ess = "";
}
@ -3108,13 +3233,13 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
// next one
x = midpoint2 + gridsize;
ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
//ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
//ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
//ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x += gridsize;
@ -3136,7 +3261,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
y = cury + THINGSIZE/4 - HELPTEXTYSPACE/2;
shadowtext(ctx, "Tissue Box", HELPTEXTSIZE, pointscol,
THINGSIZE*1.5, y);
shadowtext(ctx, "Wakes all sleeping cats.", HELPTEXTSIZE, pointscoldark,
shadowtext(ctx, "All sleeping cats wake up.", HELPTEXTSIZE, pointscoldark,
THINGSIZE*1.5, y + HELPTEXTYSPACE);
ctx.drawImage(image['tissues'], textxspace, cury, THINGSIZE, THINGSIZE);
cury += GRIDSIZE;
@ -3144,7 +3269,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
y = cury + THINGSIZE/4 - HELPTEXTYSPACE/2;
shadowtext(ctx, "Shears", HELPTEXTSIZE, pointscol,
THINGSIZE*1.5, y);
shadowtext(ctx, "Immediately clears all " + llamatext + "s.", HELPTEXTSIZE, pointscoldark,
shadowtext(ctx, "All " + llamatext + "s immediately run away.", HELPTEXTSIZE, pointscoldark,
THINGSIZE*1.5, y + HELPTEXTYSPACE);
ctx.drawImage(image['shears'], textxspace, cury, THINGSIZE, THINGSIZE);
cury += GRIDSIZE;
@ -3152,10 +3277,10 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
y = cury + THINGSIZE/4 - HELPTEXTYSPACE/2;
shadowtext(ctx, "Magic Carpet", HELPTEXTSIZE, pointscol,
THINGSIZE*1.5, y);
shadowtext(ctx, "Grants a magic fez to all cats.",
shadowtext(ctx, "Cats are given a magic fez.",
HELPTEXTSIZE, pointscoldark,
THINGSIZE*1.5, y + HELPTEXTYSPACE);
shadowtext(ctx, "Fez wearing cats are not scared of " + llamatext + "s.",
shadowtext(ctx, "Fez-wearing cats are not scared of " + llamatext + "s.",
HELPTEXTSIZE, pointscoldark,
THINGSIZE*1.5, y + HELPTEXTYSPACE*2);
ctx.drawImage(image['magiccarpet'], textxspace, cury, THINGSIZE, THINGSIZE);
@ -3263,6 +3388,9 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
y += HELPTEXTYSPACE;
shadowtext(ctx, "+" + GOATPOINTS + " points per goat", HELPTEXTSIZE,pointscol, x, y);
y += HELPTEXTYSPACE;
y += HELPTEXTYSPACE;
y += HELPTEXTYSPACE;
y += HELPTEXTYSPACE;
y += HELPTEXTYSPACE;
cury = y;
@ -3681,12 +3809,19 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
x += gridsize;
cury = y;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
ctx.textAlign = "left";
ctx.textBaseline = "bottom";
shadowtext(ctx, "Cats must be awake to attack white cats.", HELPTEXTSIZE,helpcol, textxspace, cury);
cury += HELPTEXTYSPACE;
} else if (curlevel == 13) {
cury = this.drawhelpsubtitle(ctx, "Toad", cury);
cury = this.drawhelpsubtitle(ctx, "Toads", cury);
ctx.textAlign = "left";
ctx.textBaseline = "bottom";
@ -3824,6 +3959,206 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
// line to toad falling
drawarrow(ctx, linex[0], liney[0], linex[1], liney[1], "#dddd00", LINEWIDTH, PATHARROWSIZE);
cury = y;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
ctx.textAlign = "left";
ctx.textBaseline = "bottom";
shadowtext(ctx, "Cats must be awake to slap toads.", HELPTEXTSIZE,helpcol, textxspace, cury);
cury += HELPTEXTYSPACE;
} else if (curlevel == 15) {
var tempslashes;
cury = this.drawhelpsubtitle(ctx, "Bricks", cury);
ctx.textAlign = "left";
ctx.textBaseline = "bottom";
shadowtext(ctx, "Like doors, bricks don't fall downwards.", HELPTEXTSIZE,helpcol, textxspace, cury);
cury += HELPTEXTYSPACE;
shadowtext(ctx, "Hit bricks with parades to damage them.", HELPTEXTSIZE,helpcol, textxspace, cury);
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
// top line of brick demo
x = imgsize;
y = cury;
row1y = y;
ctx.drawImage(image['goat'], x, y, imgsize, imgsize);
linex[1] = x + imgsize/2;
liney[1] = y + imgsize/2;
x += gridsize;
ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['brick'], x, y, imgsize, imgsize);
linex[2] = x + imgsize/2;
liney[2] = y + imgsize/2;
x += gridsize;
x = imgsize;
y += gridsize;
row2y = y;
ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
linex[0] = x + imgsize/2;
liney[0] = y + imgsize/2;
x += gridsize;
ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
x += gridsize;
// line to show path
drawline(ctx, linex[0], liney[0], linex[1], liney[1], PATHLINECOLGOOD, LINEWIDTH);
drawarrow(ctx, linex[1], liney[1], linex[2], liney[2], PATHLINECOLGOOD, LINEWIDTH, PATHARROWSIZE);
// arrow to middle
drawarrow(ctx, x + gridsize/2, row2y, midpoint2 - 10, row2y, "red", HELPLINEWIDTH, HELPARROWSIZE);
// damage explanation
ctx.textAlign = "left";
ctx.textBaseline = "middle";
shadowtext(ctx, "(3 damage)", HELPTEXTSIZE,"#dddd00", midpoint2 + gridsize*3 , row2y);
x = midpoint2;
y = cury;
row1y = y;
//ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x += gridsize;
//ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['brick'], x, y, imgsize, imgsize);
tempslashes = [ imgsize * 0.10, imgsize * 0.25, imgsize * 0.90, imgsize * 0.75 ];
drawslashes(ctx, x, y, tempslashes);
x += gridsize;
x = midpoint2;
y += gridsize;
row2y = y;
//ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
x += gridsize;
cury = y;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
ctx.textAlign = "left";
ctx.textBaseline = "bottom";
shadowtext(ctx, "After " + BRICKHP + " damage, bricks will break.", HELPTEXTSIZE,helpcol, textxspace, cury);
cury += HELPTEXTYSPACE;
// top line of brick breaking demo
x = imgsize;
y = cury;
row1y = y;
ctx.drawImage(image['catscared'], x, y, imgsize, imgsize);
linex[1] = x + imgsize/2;
liney[1] = y + imgsize/2;
x += gridsize;
ctx.drawImage(image['llama'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['brick'], x, y, imgsize, imgsize);
tempslashes = [ imgsize * 0.20, imgsize * 0.15, imgsize * 0.90, imgsize * 0.75,
imgsize * 0.20, imgsize * 0.75, imgsize * 0.90, imgsize * 0.15,
imgsize * 0.33, imgsize * 0.25, imgsize * 0.80, imgsize * 0.25,
imgsize * 0.33, imgsize * 0.65, imgsize * 0.65, imgsize * 0.65 ];
drawslashes(ctx, x, y, tempslashes);
linex[2] = x + imgsize/2;
liney[2] = y + imgsize/2;
x += gridsize;
x = imgsize;
y += gridsize;
row2y = y;
ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
linex[0] = x + imgsize/2;
liney[0] = y + imgsize/2;
x += gridsize;
ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
x += gridsize;
// line to show path
drawline(ctx, linex[0], liney[0], linex[1], liney[1], PATHLINECOLGOOD, LINEWIDTH);
drawarrow(ctx, linex[1], liney[1], linex[2], liney[2], PATHLINECOLGOOD, LINEWIDTH, PATHARROWSIZE);
// arrow to middle
x = x + gridsize/2;
y = row2y;
x2 = midpoint2 - 10;
y2 = y;
drawarrow(ctx, x, y, x2, y2, "red", HELPLINEWIDTH, HELPARROWSIZE);
x = midpoint2;
y = cury;
row1y = y;
//ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x += gridsize;
//ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['pow'], x, y, imgsize, imgsize);
x += gridsize;
x = midpoint2;
y += gridsize;
row2y = y;
//ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
x += gridsize;
ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
x += gridsize;
cury = y;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
cury += HELPTEXTYSPACE;
ctx.textAlign = "left";
ctx.textBaseline = "bottom";
shadowtext(ctx, "Toads and white cats can also break bricks.", HELPTEXTSIZE,helpcol, textxspace, cury);
cury += HELPTEXTYSPACE;
}
ctx.textAlign = "center";
@ -4219,8 +4554,8 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
console.log("changing last clicked thing thing at " + lastmx/GRIDSIZE + "," + lastmy/GRIDSIZE );
what = getthingxy(lastmx, lastmy);
if (what != undefined) {
what.name = "forcedllama";
what.type = "llama";
what.name = "xxx changed xx";
what.type = "sunlight";
game.dirty = true;
}
} else if (ch == 'm') {
@ -4499,10 +4834,11 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
var i;
imagenames = ['cat', 'catfull', 'catscared', 'llama', 'cheese', 'title',
'goat','door','lock','catwalkl','catwalkr','starfull','starempty',
'sunlight', 'toad', // special things
'bag', 'bagpop', 'fez', 'pow', // effects
'tissues', 'shears', 'magiccarpet', 'whitecat' ];
'goat', 'lock','catwalkl','catwalkr','starfull','starempty',
'door', 'sunlight', 'toad', 'whitecat', // special things
'brick', // obstacles
'bag', 'bagpop', 'fez', 'pow', 'brickpop', // effects
'tissues', 'shears', 'magiccarpet' ];
nimages = 0;
maximages = 0;
@ -4663,7 +4999,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
for (i = 0; i < curpath.length; i++) {
// ... except doors
if (curpath[i].type == "door") {
game.progress("door", 1);
//game.progress("door", 1);
console.log("path has doors!");
// add animation
things.push(new thing(curpath[i].gridx, curpath[i].gridy, "text", "x" + (globmulti+1)));
@ -4843,7 +5179,7 @@ function getrandomtype() {
var roll,tot,type = null,i;
var thinglist,maxroll = 0;
var speciallist = null;
var dodb = true;
var dodb = false;
if (curlevel >= game.levels.length) {
thinglist = null;
@ -4862,8 +5198,10 @@ function getrandomtype() {
}
}
if (dodb) console.log("speciallist is " + speciallist);
//if (dodb) console.log("speciallist is " + speciallist);
// normally we use default chances for objects, but some levels
// have special pre-defined chances.
if (thinglist == undefined || thinglist.length == 0) {
var f;
thinglist = new Array();
@ -4908,7 +5246,7 @@ function getrandomtype() {
if (matchesgoal) {
var count;
console.log("****** " + thingtype + " matches goal.");
if (dodb) console.log("****** " + thingtype + " matches goal.");
// check if any exist
count = countalivethingsoftype(lookforthing);
if (count <= 1) {
@ -4937,7 +5275,12 @@ function getrandomtype() {
if (dodb) {
for (i = 0; i < thinglist.length; i++) {
console.log(thinglist[i].type + ": " + ((thinglist[i].pct / maxroll)*100) + "% [roll " + maxroll + "/" + maxroll + "]");
var logline;
logline = thinglist[i].type + ": " + ((thinglist[i].pct / maxroll)*100) + "% [roll " + thinglist[i].pct + "/" + maxroll + "]";
if (thinglist[i].type == "special") {
logline = logline + " - " + speciallist;
}
console.log(logline);
}
}
@ -4974,10 +5317,12 @@ function thing(gridx, gridy, type, text, col) {
this.matched = false; // temp for 'match3' things
this.gotfez = false; // for powerups
this.slashes = []; // drawing slashes on bricks when damaged
// list x,y coords. 0=x1 1=y2 3=x2 4=y2 etc.
if (type == "random") {
type = getrandomtype();
console.log("got random type "+ type);
//console.log("got random type "+ type);
}
// used for various things
if (type == "sunlight") {
@ -5037,6 +5382,11 @@ function thing(gridx, gridy, type, text, col) {
}
this.lifetime = 0;
if (this.type == "brick") {
this.hp = BRICKHP;
} else {
this.hp = -1;
}
this.gridx = gridx;
if (gridy == "top") {
@ -5061,6 +5411,9 @@ function thing(gridx, gridy, type, text, col) {
if (this.type == "bagpop") {
this.yspeed = 0 - rndfloat(8);
this.xspeed = 0 - rndfloat(16) - 1;
} else if (this.type == "brickpop") {
this.yspeed = 0 - rndfloat(8);
this.xspeed = rndfloat(32) - 16;
} else {
this.yspeed = 0;
this.xspeed = 0;
@ -5109,8 +5462,8 @@ function thing(gridx, gridy, type, text, col) {
}
this.canfall = function() {
// doors can't fall after their initial drop
if (this.type == "door") {
// doors and bricks can't fall after their initial drop
if ((this.type == "door") || (this.type == "brick")) {
if ((this.gridy >= 0) && (this.isnew == false)) {
return false;
}
@ -5196,10 +5549,10 @@ function thing(gridx, gridy, type, text, col) {
if (this.type == "food") {
points = FOODPOINTS;
game.progress("food", 1);
//game.progress("food", 1);
} else if (this.type == "llama") {
points = LLAMAPOINTS;
game.progress("llama", 1);
//game.progress("llama", 1);
} else if (this.type == "cat") {
if (this.issleepy()) {
points = SLEEPYCATPOINTS;
@ -5210,10 +5563,10 @@ function thing(gridx, gridy, type, text, col) {
if (this.gotfez) {
points *= 2;
}
game.progress("cat", 1);
//game.progress("cat", 1);
} else if (this.type == "goat") {
points = GOATPOINTS;
game.progress("goat", 1);
//game.progress("goat", 1);
}
// multiplier for path position
@ -5311,9 +5664,8 @@ function thing(gridx, gridy, type, text, col) {
ctx.textBaseline = "middle";
shadowtext(ctx, this.name, this.size, this.color, BOARDX + this.x,BOARDY + this.y);
} else {
var myimage;
if (this.type == "cat") {
var myimage;
if (this.state == "parade") {
myimage = image['cat'];
} else if (this.isscared()) {
@ -5323,25 +5675,12 @@ function thing(gridx, gridy, type, text, col) {
} else {
myimage = image['cat'];
}
} else if (this.type == "llama") {
myimage = image['llama'];
} else if (this.type == "food") {
myimage = image['cheese'];
} else if (this.type == "goat") {
myimage = image['goat'];
} else if (this.type == "door") {
myimage = image['door'];
} else if (this.type == "sunlight") {
myimage = image['sunlight'];
} else if (this.type == "toad") {
myimage = image['toad'];
} else if (this.type == "whitecat") {
myimage = image['whitecat'];
} else if (this.type == "bagpop") {
myimage = image['bagpop'];
} else if (this.type == "pow") {
myimage = image['pow'];
} else {
myimage = image[this.type];
}
if (myimage == undefined || myimage == null) {
console.log("ERROR - no image for type " + this.type);
console.log(this);
}
@ -5378,6 +5717,9 @@ function thing(gridx, gridy, type, text, col) {
ctx.drawImage(myimage, BOARDX + myx, BOARDY + myy, howbig, howbig);
// draw slashes on bricks
drawslashes(ctx, BOARDX + myx, BOARDY + myy, this.slashes);
if (this.gotfez) {
// fw = 0.78 * howbig;
// fh = 0.625 * howbig;
@ -5507,6 +5849,8 @@ function thing(gridx, gridy, type, text, col) {
this.kill = function() {
// kill ourselves
game.progress(this.type, 1);
var idx = things.indexOf(this);
things.splice(idx, 1);
}
@ -5543,7 +5887,7 @@ function thing(gridx, gridy, type, text, col) {
// add "pow"
things.push(new thing(toad.gridx, toad.gridy, "pow"));
game.progress("toad", 1);
//game.progress("toad", 1);
console.log("slap");
}
@ -5575,7 +5919,7 @@ function thing(gridx, gridy, type, text, col) {
whitecat.addabove();
whitecat.startexplode();
game.progress("whitecat", 1);
//game.progress("whitecat", 1);
console.log("whitecat");
}
@ -5616,12 +5960,40 @@ function thing(gridx, gridy, type, text, col) {
return false;
}
this.breakbrick = function() {
var i,nshards = 7;
for (i = 0; i < nshards; i++) {
things.push(new thing(this.gridx, this.gridy, "brickpop"));
}
this.givepoints();
this.addabove();
this.kill();
}
this.losehp = function() {
this.hp--;
console.log("brick hp is at " + this.hp);
if (this.hp <= 0) {
game.dirty = true; // need to redraw
this.breakbrick();
} else {
// add a slash from a random x/y to a random x/y
addslash(this.slashes, THINGSIZE, THINGSIZE);
}
}
this.startexplode = function(why) {
this.expcount=1;
this.expmax=EXPLODETICKS;
this.expfadespeed = EXPLODEFADESPEED;
this.state = "explode";
this.explodereason = why;
if (this.type == "brick") {
// break it instead
this.breakbrick();
} else {
this.expcount=1;
this.expmax=EXPLODETICKS;
this.expfadespeed = EXPLODEFADESPEED;
this.state = "explode";
this.explodereason = why;
}
}
this.startshrink = function() {
@ -5688,7 +6060,7 @@ function thing(gridx, gridy, type, text, col) {
var belowthing = null,atbottom = false;
if (this.type == "bagpop") {
if ((this.type == "bagpop") || (this.type == "brickpop")) {
game.dirty = true; // need to redraw
// regular gravity
@ -5819,7 +6191,7 @@ function thing(gridx, gridy, type, text, col) {
this.calcgridxy();
// cat parade into a bag?
// cat parade into a bag or wall?
if (this.state == "parade") {
var bag;
// hit a bag?
@ -5828,7 +6200,6 @@ function thing(gridx, gridy, type, text, col) {
if (bag.cats < bag.capacity) {
this.path = [];
this.startshrink();
console.log("aaa");
bag.cats++;
if (bag.cats >= bag.capacity) {
@ -5836,6 +6207,16 @@ console.log("aaa");
game.addbagpop(bag.y);
}
}
} else {
var brick;
brick = gridxyhasthingtype(this.gridx, this.gridy, "brick");
if (brick != undefined) {
// parade cat explodes.
this.path = [];
this.startexplode();
brick.losehp();
}
}
}
@ -5843,9 +6224,12 @@ console.log("aaa");
if (xdone && ydone) {
this.poppath();
console.log("poppath for " + this.name + " - new len is " + this.path.length);
// path finished?
if (this.path == undefined || this.path.length == 0) {
if (this.state == "catparade" ){
if (this.state == "parade" ){
console.log("calling kill for parading " + this.type);
this.kill();
} else {
this.state = "stop";
@ -6055,19 +6439,28 @@ function mainloop() {
for (i = 0; i < things.length; i += 1) {
if (things[i].type == "sunlight" && things[i].gridy >= 0 && !things[i].isnew &&
things[i].state != "swapping" && things[i].counter == 0) {
if ((things[i].gridy >= GRIDH-1)) {
var thingbelow,willdie = false;
thingbelow = getgridthing(things[i].gridx, things[i].gridy+1);
if (thingbelow != undefined && thingbelow.type == "brick") {
// bricks stop sun
willdie = true;
} else if ((things[i].gridy >= GRIDH-1)) {
// at bottom - disappear
willdie = true;
}
if (willdie) {
// at bottom - disappear
things[i].addabove();
things[i].startexplode("sun");
game.progress("sun", 1);
//game.progress("sun", 1);
} else {
var thingbelow;
// move down
// move down (swap with thing below us)
things[i].pushpath(things[i].x, things[i].y + GRIDSIZE);
things[i].state = "swapping";
things[i].counter = 1;
thingbelow = getgridthing(things[i].gridx, things[i].gridy+1);
if (thingbelow != undefined && thingbelow.state != "swapping" &&
thingbelow.type != "sunlight") {
thingbelow.pushpath(things[i].x, things[i].y);
@ -6142,7 +6535,7 @@ function matchthreefrom(what, locdb) {
var nn;
// matched!
for (nn = 0; nn < setthings.length; nn++) {
console.log(" "+setthings[nn].name + " x=",setthings[nn].x + ",y=" + setthings[nn].y);
//console.log(" "+setthings[nn].name + " x=",setthings[nn].x + ",y=" + setthings[nn].y);
setthings[nn].matched = true;
}
gotmatch = true;

BIN
images/brick.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
images/brickpop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
images/origdoor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

48
todo
View File

@ -11,13 +11,33 @@ https://www.smashingmagazine.com/2012/10/design-your-own-mobile-game/
-------------------
*only increase chance of goal items if you haven't already met the goal.
*make increase chance work for "special" things!!! (eg. white cat)
*stop increasing goal progress once we hit the required amount
*seperate goal names and goal associated things
OBSTACLES on later levels
fixed position.
*move goal progress increments to thing.kill() function
*Make 'allowedthings' default to previous level's one.
*fix lev6 help
*bugfix: whitecats aren't ever appearing randomly?
*new object: bricks
*Don't allow extending path off the top of the grid.
*fix incorrect pluralisation "foods" in goal text
??????????????
no points for cats hitting bricks
give points when things DIE, not when you start a parade.
make points for parades come from the _side_ of the screen.
(where the cats/whatever disappear)
make kill() take an arg ("don't give progress/points")
adjust brick points goal
??????????????
new door fell down on top of new goat!!
(or the other way around ??)
check code for doors falling when off the top of the screen.
check code for adding new objects at top of screen.
Powerup to break bricks
other colour cats
@ -29,14 +49,22 @@ more goals:
more prizes: ???
mouse - place to clear all cats in grid/column
whitecat - place to clear 3 x 3 grid around it
overeat (cheese changes to niblet bags, can eat without sleep)
arrow/signpost - cat parades bounce off and take out htings in the path
diff colour cats which only match themselves
actual fireworks when you achieve a goal rather than a flash.
fireworks later.
random levels after 100
generate w/h increases (up to a maximum)
generate goals
generate obstacles
use existing maxturns code
---------
@ -54,10 +82,6 @@ sofa/curtain
parade over to scratch
blow up and pow!
fireworks when you achieve a goal
*flash for now
fireworks later.
show points for each element along path??