diff --git a/cat.html b/cat.html index 62d176c..1fc09fe 100644 --- a/cat.html +++ b/cat.html @@ -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; diff --git a/images/brick.png b/images/brick.png new file mode 100644 index 0000000..7fbbfe3 Binary files /dev/null and b/images/brick.png differ diff --git a/images/brickpop.png b/images/brickpop.png new file mode 100644 index 0000000..da21d60 Binary files /dev/null and b/images/brickpop.png differ diff --git a/images/door.png b/images/door.png index dca4204..6b1db10 100644 Binary files a/images/door.png and b/images/door.png differ diff --git a/images/origdoor.png b/images/origdoor.png new file mode 100644 index 0000000..dca4204 Binary files /dev/null and b/images/origdoor.png differ diff --git a/todo b/todo index c8f39c4..f97bb83 100644 --- a/todo +++ b/todo @@ -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??