From 1546c6f4ed28f6cf338beb218bcf7c52e400ca4e Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Sat, 3 Sep 2016 10:52:03 +1000 Subject: [PATCH] New thing: boxes *change layout of levselect screen *curtain is now a 'special' object --- cat.html | 736 ++++++++++++++++++++++++++++++++++++++------ images/box.png | Bin 0 -> 4269 bytes images/boxback.png | Bin 0 -> 1099 bytes images/boxfront.png | Bin 0 -> 3683 bytes images/stargrey.png | Bin 0 -> 2689 bytes todo | 45 ++- 6 files changed, 656 insertions(+), 125 deletions(-) create mode 100644 images/box.png create mode 100644 images/boxback.png create mode 100644 images/boxfront.png create mode 100644 images/stargrey.png diff --git a/cat.html b/cat.html index b662ce6..6a69f9c 100644 --- a/cat.html +++ b/cat.html @@ -74,7 +74,7 @@ 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 BRICKHP = 6; // how many cats it takes to remove a brick var CURTAINHP = 2; // how many climbs it takes to remove a curtain var SLASHDIST = 3; // space between slash marks on bricks @@ -99,6 +99,7 @@ var GOALVERB = { 'whitecat': 'Attack', 'brick': 'Break', 'curtain': 'Shred', + 'ambush': 'Launch', }; var GOALNAME = { @@ -225,7 +226,7 @@ var TITLESIZELEVSELECT = 18; // in points var TEXTSIZELEVSELECT = 20; // in points var TEXTSIZETOTSTARS = 16; // in points var TEXTSIZELEVSCORE = 8; // in points -var TEXTSIZELEVSTARS = 12; // in points +var TEXTSIZELEVSTARS = 10; // in points var HELPLINEWIDTH=4; var HELPARROWSIZE=15; @@ -234,7 +235,7 @@ var HELPSUBTITLESIZE = 14; //var HELPTEXTSIZE = 12; var HELPTEXTSIZE = 9; -var GOALTEXTSIZE = 16; +var GOALTEXTSIZE = 14; var HELPTEXTYSPACE = HELPTEXTSIZE * 1.8; @@ -294,6 +295,7 @@ var LLAMAPOINTS = 100; var GOATPOINTS = 50; var CATPOINTS = 20; var SLEEPYCATPOINTS = 40; +var CATBOXPOINTS = 40; var overdesc = ""; @@ -372,19 +374,29 @@ function pathcomplete() { // get path type switch(getpathtype()) { case "chomp": - if ((curpath.length >= 2) && - (curpath[0].type == "cat") && - !curpath[0].issleepy()) { + if (curpath.length >= 2 && + ( (curpath[0].type == "cat" && !curpath[0].issleepy()) || + (curpath[0].type == "box" && curpath[0].boxfull) ) ) { var i; - var ok = true; - // everything else is food? - for (i = 1; i < curpath.length; i++) { + var ok = true,lastok = false; + // everything else except last is food? + for (i = 1; i < curpath.length-1; i++) { if (curpath[i].type != "food") { ok = false; break; } } - if (ok) { + + // last one is food? + if (curpath[curpath.length-1].type == "food") { + lastok = true; + } else if (curpath[curpath.length-1].type == "box" && + !curpath[curpath.length-1].boxfull && + curpath[0].type == "cat") { + // last one is empty box, and first one was a cat? + lastok = true; + } + if (ok && lastok) { return true; } } @@ -500,16 +512,37 @@ function pathcontainstype(type) { return null; } +function catcolmatches(a, b) { + var cola,colb; + + if (a.type == "box") { + cola = null; + } else { + cola = a.catcol; + } + + if (b.type == "box") { + colb = null; + } else { + colb = b.catcol; + } + if (cola == undefined) return true; + if (colb == undefined) return true; + if (cola == colb) return true; + + return false; +} + function isvalidpath(mypath) { var valid = true; - var firstcat = false; var fcount = 0; var lcount = 0; var gcount = 0; var count = 0; var ccount = 0; var i; - var startcol = null; + //var startcol = null; + var firstone = null; for (i = 0; i < mypath.length - 1; i++) { var thisone,nextone,dirtonext; @@ -523,7 +556,14 @@ function isvalidpath(mypath) { */ if (i == 0) { - startcol = thisone.catcol; + /* + if (thisone.type == "box") { + startcol = null; + } else { + startcol = thisone.catcol; + } + */ + firstone = thisone; } nextone = mypath[i+1]; @@ -543,18 +583,23 @@ function isvalidpath(mypath) { } count++; - if ((i == 0) && (thisone.type == "cat")) { - firstcat = true; - } - - if ((thisone.type == "cat") && (nextone.type == "cat") && (nextone.catcol == startcol) && (ccount == 0)) { + if ((thisone.type == "cat") && (nextone.type == "cat") && catcolmatches(nextone, firstone) && (ccount == 0)) { // no parades on level 1 if (curlevel == 1) { return false; } // ...but otherwise lines of cats are ok if they're the right colour + } else if ((thisone.type == "cat") && (nextone.type == "box") && (nextone.boxfull == true) && (ccount == 0)) { + // full boxes can be part of parades, colour doesn't matter + } else if (thisone.type == "box" && thisone.boxfull && + ((nextone.type == "cat" && catcolmatches(nextone, firstone)) || nextone.type == "llama" || nextone.type == "goat")) { + + // full boxes can be part of parades, colour doesn't matter + } else if (thisone.type == "box" && thisone.boxfull && + nextone.type == "box" && nextone.boxfull) { + // full boxes can parade on to other full boxes } else if ((thisone.type == "goat") && (ccount == 0) && - ((nextone.type == "cat" && nextone.catcol == startcol) || nextone.type == "llama" || nextone.type == "goat")) { + ((nextone.type == "cat" && catcolmatches(nextone, firstone)) || nextone.type == "llama" || nextone.type == "goat")) { // goat can go to llama or correctly coloured cat // ok } else if ((nextone.type == "door") && (count >= PARADELENGTH) && (fcount == 0) && (ccount == 0) && (count >= 3) && @@ -581,7 +626,8 @@ function isvalidpath(mypath) { } } else if ((thisone.type == "cat") && nextone.type == "goat" && (ccount == 0)) { // cat -> goat is okay - } else if ((thisone.type == "llama") && (ccount == 0) && ((nextone.type == "cat" && nextone.catcol == startcol) || nextone.type == "goat")) { + } else if ((thisone.type == "llama") && (ccount == 0) && + ((nextone.type == "cat" && catcolmatches(nextone, firstone)) || nextone.type == "goat")) { // no parades on level 1 if (curlevel == 1) { return false; @@ -597,14 +643,21 @@ function isvalidpath(mypath) { // anywhere from a curtain is okay. (direction checked in canextendpath()) } else if ((i == 0) && (thisone.type == "cat") && (nextone.type == "food")) { // first cat -> food is ok + } else if ((i == 0) && (thisone.type == "box") && thisone.boxfull && (nextone.type == "food")) { + // first full box -> food is ok } else if ((i == 0) && (thisone.type == "cat") && (nextone.type == "toad")) { // first cat -> toad is ok } else if ((i == 0) && (thisone.type == "cat") && (nextone.type == "curtain")) { // first cat -> curtain is ok if we're going UP/DOWN only } else if ((i == 0) && (thisone.type == "cat") && (nextone.type == "whitecat")) { // first cat -> whitecat is ok - } else if ((i != 0) && firstcat && (ccount == 0) && (thisone.type == "food") && (nextone.type == "food")) { - // not the first one, first one was a cat, this one and next are food + } else if ((i == 0) && (thisone.type == "cat") && (nextone.type == "box") && !nextone.boxfull) { + // first cat -> box is ok + } else if ((i != 0) && (firstone.type == "cat" || firstone.type == "box") && (ccount == 0) && (thisone.type == "food") && (nextone.type == "food")) { + // not the first one, first one was a cat/box, this one and next are food + } else if ((i != 0) && (firstone.type == "cat") && (ccount == 0) && (thisone.type == "food") && + (nextone.type == "box") && !nextone.boxfull) { + // not the first one, first one was a cat, food -> box } else { // not ok valid = false; @@ -707,7 +760,7 @@ function getpathtype() { if (curpath.length <= 1) return "none" if (curpath[0].type == "cat") { - if (curpath[1].type == "food") { + if ((curpath[1].type == "food") || (curpath[1].type == "box" && !curpath[1].boxfull)) { return "chomp"; } else if (curpath[1].type == "toad") { return "slap"; @@ -715,7 +768,15 @@ function getpathtype() { return "climb"; } else if (curpath[1].type == "whitecat") { return "attack"; - } else if ((curpath[1].type == "cat") || (curpath[1].type == "llama") || (curpath[1].type == "goat")) { + } else if ((curpath[1].type == "cat") || (curpath[1].type == "llama") || (curpath[1].type == "goat") + || (curpath[1].type == "box" && curpath[1].boxfull) ) { + return "parade"; + } + } else if (curpath[0].type == "box") { + if (curpath[1].type == "food") { + return "chomp"; + } else if ((curpath[1].type == "cat") || (curpath[1].type == "llama") || (curpath[1].type == "goat") + || (curpath[1].type == "box" && curpath[1].boxfull) ) { return "parade"; } } @@ -773,9 +834,13 @@ function thingsmoving() { } function canstartpath(what) { - if (what.type != "cat") { - // only cats can start paths -console.log("not a cat"); + + if (what.type == "cat") { + // cats can start paths + } else if (what.type == "box" && what.boxfull) { + // full boxes can start paths + } else { + console.log("not a cat"); return false; } @@ -865,8 +930,9 @@ function getmousexy(event) { return [ adjustx, adjusty, x, y ]; } + // -function isadjacenttotype(what, wanttype, exceptionthing, catcol) { +function isadjacenttotype(what, wanttype, exceptionthing, catcol, boxfull) { var newgridx,newgridy; var i; @@ -877,9 +943,21 @@ function isadjacenttotype(what, wanttype, exceptionthing, catcol) { if (isonscreen(newgridx,newgridy)) { adjthing = getgridthing(newgridx, newgridy); if ((adjthing != undefined) && (adjthing.type == wanttype) && (adjthing != exceptionthing)) { - if (catcol == undefined) { - return true; - } else if (adjthing.catcol == what.catcol) { + var ok = true; + if (catcol != undefined) { + if (adjthing.catcol != what.catcol) { + ok = false; + } + } + + if (boxfull != undefined) { + if (adjthing.boxfull != boxfull) { + ok = false; + } + } + + + if (ok) { return true; } } @@ -1408,15 +1486,10 @@ var game = { // 15 - 24 = 2 bags // 25 - 34 = 3 bags nbags = Math.floor((curlevel+5) / 10); + for (i = 0; i < nbags; i++) { - var bagy = rnd(GRIDH); - while (getbagaty(bagy)) { - bagy = rnd(GRIDH); - } - this.addlevelbag(curlevel, bagy); + this.addlevelbag(curlevel); } - - }, // x1, x2, y2, x3, y3.... @@ -1431,9 +1504,15 @@ var game = { } }, - addlevelbag : function (lev, y ) { - var mybag; + addlevelbag : function (lev) { + var mybag,y; mybag = new Object(); + + y = rnd(GRIDH); + while (getbagaty(y)) { + y = rnd(GRIDH); + } + mybag.y = y; mybag.cats = 0; mybag.prize = ""; @@ -1553,6 +1632,13 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio); this.levels[lev].goals[idx].type = arguments[i]; this.levels[lev].goals[idx].count = arguments[i+1]; this.levels[lev].goals[idx].progress = 0; + + // make sure the level has enough bags! + if (arguments[i] == "bag") { + while (this.levels[lev].nbags < arguments[i+1]) { + this.addlevelbag(lev); + } + } } }, @@ -1863,8 +1949,45 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio); this.addlevel(21, true); this.addlevelallowedthings("curtain"); this.addlevelforcethings("curtain", 2); - this.addlevelgoals("curtain", 2); - this.addlevelgoals("cat", 30); + this.addlevelgoals("curtain", 2, "cat", 30); + + this.addlevel(22, false); + this.addlevelgoals("curtain", 2, "bag", 2); + + + this.addlevel(23, false); + this.addlevelgoals("cat", 20, "food", 20); + + this.addlevel(24, true); // introduce boxes + this.addlevelallowedthings("box"); + this.addlevelforcethings("box", 2); + this.addlevelgoals("ambush", 5, "cat", 20); + + this.addlevel(25, false); + this.addlevelbricks( 3,4, 5,4 ); + + + this.addlevelgoals("ambush", 2, "door", 3, "cat", 20); + + this.addlevel(26, false); + this.addlevelbricks(8,0, + 8,1, + 8,2, + 8,3, + 8,4, + 8,5, + 8,6, + 8,7, + 8,8); + this.addlevelgoals("cat", 30, "bag", 2); + + + this.addlevel(27, false); + this.addlevelbricks( 4,3, + 3,4,4,4,5,4, + 4,5); + this.addlevelgoals("brick", 3, "ambush", 1, "llama", 15); + /* hard brick pattern @@ -2199,10 +2322,12 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio); // goal description var ess = "s"; - if (this.levels[curlevel].goals[n].type == "food") { + if (this.levels[curlevel].goals[n].count == 1) { ess = ""; - } else if (this.levels[curlevel].goals[n].count == 1) { + } else if (this.levels[curlevel].goals[n].type == "food") { ess = ""; + } else if (this.levels[curlevel].goals[n].type == "ambush") { + var ess = "es"; } @@ -4473,7 +4598,6 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio); ctx.drawImage(image['catfull'], x, y, imgsize, imgsize); x += gridsize; - // oooooooo swap lines cury = y + gridsize; cury += HELPTEXTYSPACE; @@ -4531,6 +4655,244 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio); ctx.drawImage(image['catfull'], x, y, imgsize, imgsize); x += gridsize; + } else if (curlevel == 24) { + var tempslashes; + cury = this.drawhelpsubtitle(ctx, "Boxes", cury); + + ctx.textAlign = "left"; + ctx.textBaseline = "bottom"; + shadowtext(ctx, "Boxes are fantastic. Cats can enter adjacent boxes,", HELPTEXTSIZE,helpcol, textxspace, cury); + cury += HELPTEXTYSPACE; + shadowtext(ctx, "and can even do so after eating food.", HELPTEXTSIZE,helpcol, textxspace, cury); + cury += HELPTEXTYSPACE; + + // top line of box demo - cat -> box + x = imgsize; + y = cury; + row1y = y; + + ctx.drawImage(image['cheese'], x, y, imgsize, imgsize); + x += gridsize; + + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + linex[0] = x + imgsize/2; + liney[0] = y + imgsize/2; + x += gridsize; + + ctx.drawImage(image['box'], x, y, imgsize, imgsize); + linex[1] = x + imgsize/2; + liney[1] = y + imgsize/2; + x += gridsize; + + // cat -> cheese -> box + y += gridsize; + x = imgsize; + + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + linex[2] = x + imgsize/2; + liney[2] = y + imgsize/2; + x += gridsize; + + ctx.drawImage(image['cheese'], x, y, imgsize, imgsize); + x += gridsize; + + ctx.drawImage(image['box'], x, y, imgsize, imgsize); + linex[3] = x + imgsize/2; + liney[3] = y + imgsize/2; + x += gridsize; + + + // line to show path + drawarrow(ctx, linex[0], liney[0], linex[1], liney[1], PATHLINECOLGOOD, LINEWIDTH, PATHARROWSIZE); + drawarrow(ctx, linex[2], liney[2], linex[3], liney[3], PATHLINECOLGOOD, LINEWIDTH, PATHARROWSIZE); + + // arrow to middle + y = row1y + imgsize/2; + + x2 = x + gridsize*2; + y2 = row1y + imgsize/2 + gridsize/2; + + drawarrow(ctx, x, y2, x2, y2, "red", HELPLINEWIDTH, HELPARROWSIZE); + + // rhs - cats in boxes + x = x2 + imgsize/2; + y = row1y; + + ctx.drawImage(image['cheese'], x, y, imgsize, imgsize); + x += gridsize; + + x += gridsize; + + ctx.drawImage(image['boxback'], x, y, imgsize, imgsize); + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + ctx.drawImage(image['boxfront'], x, y, imgsize, imgsize); + + // rhs - cats in boxes + x = x2 + imgsize/2; + y = row1y; + + ctx.drawImage(image['cheese'], x, y, imgsize, imgsize); + x += gridsize; + + y += gridsize; + x = x2 + imgsize/2; + + x += gridsize; + + x += gridsize; + + ctx.drawImage(image['boxback'], x, y, imgsize, imgsize); + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + ctx.drawImage(image['boxfront'], x, y, imgsize, imgsize); + + cury = y + gridsize*1.5; + + shadowtext(ctx, "Cats in boxes can chomp food without getting tired.", HELPTEXTSIZE,helpcol, textxspace, cury); + cury += HELPTEXTYSPACE; + cury += HELPTEXTYSPACE; + shadowtext(ctx, "Cats in boxes can join parades of any colour.", HELPTEXTSIZE,helpcol, textxspace, cury); + cury += HELPTEXTYSPACE; + cury += HELPTEXTYSPACE; + shadowtext(ctx, "Parades started by a cat-in-a-box may contain", HELPTEXTSIZE,helpcol, textxspace, cury); + cury += HELPTEXTYSPACE; + shadowtext(ctx, "cats of any colour.", HELPTEXTSIZE,helpcol, textxspace, cury); + cury += HELPTEXTYSPACE; + + // top line of box parade demo + x = imgsize; + y = cury; + row1y = y; + + ctx.drawImage(image['boxback'], x, y, imgsize, imgsize); + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + ctx.drawImage(image['boxfront'], 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); + linex[1] = x + imgsize/2; + liney[1] = y + imgsize/2; + x += gridsize; + + // next line + x = imgsize; + y += gridsize + row2y = y; + + ctx.drawImage(image['boxback'], x, y, imgsize, imgsize); + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + ctx.drawImage(image['boxfront'], x, y, imgsize, imgsize); + linex[2] = x + imgsize/2; + liney[2] = y + imgsize/2; + x += gridsize; + + ctx.drawImage(image['cat1'], x, y, imgsize, imgsize); + x += gridsize; + + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + linex[3] = x + imgsize/2; + liney[3] = y + imgsize/2; + + + + // fourth example + x = midpoint2; + y = row1y; + + + ctx.drawImage(image['cat1'], x, y, imgsize, imgsize); + linex[4] = x + imgsize/2; + liney[4] = y + imgsize/2; + x += gridsize; + + ctx.drawImage(image['boxback'], x, y, imgsize, imgsize); + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + ctx.drawImage(image['boxfront'], x, y, imgsize, imgsize); + x += gridsize; + + ctx.drawImage(image['cat1'], x, y, imgsize, imgsize); + linex[5] = x + imgsize/2; + liney[5] = y + imgsize/2; + x += gridsize; + + + + + // next line of 4th example + x = midpoint2; + y += gridsize; + + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + linex[6] = x + imgsize/2; + liney[6] = y + imgsize/2; + x += gridsize; + + ctx.drawImage(image['boxback'], x, y, imgsize, imgsize); + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + ctx.drawImage(image['boxfront'], x, y, imgsize, imgsize); + x += gridsize; + + ctx.drawImage(image['cat1'], x, y, imgsize, imgsize); + linex[7] = x + imgsize/2; + liney[7] = y + imgsize/2; + x += gridsize; + + + drawarrow(ctx, linex[0], liney[0], linex[1], liney[1], PATHLINECOLGOOD, LINEWIDTH, PATHARROWSIZE); + drawarrow(ctx, linex[2], liney[2], linex[3], liney[3], PATHLINECOLGOOD, LINEWIDTH, PATHARROWSIZE); + drawarrow(ctx, linex[4], liney[4], linex[5], liney[5], PATHLINECOLGOOD, LINEWIDTH, PATHARROWSIZE); + drawarrow(ctx, linex[6], liney[6], linex[7], liney[7], PATHLINECOLGOOD, LINEWIDTH, PATHARROWSIZE); + + + cury = y + gridsize*1.5; + + shadowtext(ctx, "Cats in boxes will automatically ambush " + llamatext + "s!", HELPTEXTSIZE,helpcol, textxspace, cury); + cury += HELPTEXTYSPACE; + + + // top line of box parade demo + x = imgsize; + y = cury; + row1y = y; + + ctx.drawImage(image['cheese'], x, y, imgsize, imgsize); + x += gridsize; + + ctx.drawImage(image['boxback'], x, y, imgsize, imgsize); + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + ctx.drawImage(image['boxfront'], x, y, imgsize, imgsize); + x += gridsize; + + ctx.drawImage(image['llama'], x, y, imgsize, imgsize); + x += gridsize; + + // arrow to middle + y = row1y + imgsize/2; + + x2 = x + gridsize*2; + + drawarrow(ctx, x, y, x2, y, "red", HELPLINEWIDTH, HELPARROWSIZE); + + // rhs - pow! + x = x2 + imgsize/2; + y = row1y; + + ctx.drawImage(image['cheese'], x, y, imgsize, imgsize); + x += gridsize; + + ctx.drawImage(image['boxback'], x, y, imgsize, imgsize); + ctx.drawImage(image['cat'], x, y, imgsize, imgsize); + ctx.drawImage(image['boxfront'], x, y, imgsize, imgsize); + x += gridsize; + + ctx.drawImage(image['pow'], x, y, imgsize, imgsize); + x += gridsize; + + } @@ -4592,57 +4954,83 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio); ctx.globalAlpha = gridalpha; for (y = 0; y < LEVSELGRIDH*GRIDSIZE; y += GRIDSIZE) { for (x = 0; x < LEVSELGRIDW*GRIDSIZE; x += GRIDSIZE) { + var levy = LEVSEL_Y + y + GRIDSIZE/4; + if (this.levelexists(levnum)) { + ctx.beginPath(); ctx.lineWidth = 3; ctx.strokeStyle = gridcol; gridgrad = this.context.createLinearGradient(x, y, LEVSEL_X+x+GRIDSIZE, LEVSEL_Y+y+GRIDSIZE); //gridgrad.addColorStop(0, "#eeee00"); - if ((playerdata.levscore[levnum] > 0) && !this.levellocked(levnum)) { - gridgrad.addColorStop(0, "#00ee00"); - } else { + //if ((playerdata.levscore[levnum] > 0) && !this.levellocked(levnum)) { + if ( this.levellocked(levnum)) { gridgrad.addColorStop(0, "#eeeeee"); + } else { + // unlocked + gridgrad.addColorStop(0, "#00ee00"); } gridgrad.addColorStop(1, gridblack); ctx.fillStyle = gridgrad; ctx.fillRect(LEVSEL_X + x, LEVSEL_Y + y, GRIDSIZE-1, GRIDSIZE-1); ctx.stroke(); + + // show level num + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + shadowtext(ctx, levnum, TEXTSIZELEVSELECT, textcol, + LEVSEL_X + x + GRIDSIZE/2,levy); + + + if (this.levellocked(levnum)) { + var lockh = GRIDSIZE / 2.8; + var lockw = (lockh / image['lock'].height) * image['lock'].width; + var lockx = LEVSEL_X + x + GRIDSIZE/2 - lockw/2; + var locky = LEVSEL_Y + y + TEXTSIZELEVSELECT*1.5; + // locked - ctx.drawImage(image['lock'], - LEVSEL_X + x + GRIDSIZE/2 - image['lock'].width/3, - LEVSEL_Y + y + GRIDSIZE/3 - image['lock'].height/3, - GRIDSIZE/2, GRIDSIZE/2); + ctx.drawImage(image['lock'], lockx, locky, lockw, lockh); // # stars to unlock + var starreqx = LEVSEL_X + x + GRIDSIZE/2; + //var starreqy = LEVSEL_Y + y + GRIDSIZE - (GRIDSIZE/4) + // - (STARWID_LEVSEL_LOCKED/2); + //var starreqy = locky + lockh * 0.9; + var starreqy = LEVSEL_Y + y + GRIDSIZE - TEXTSIZELEVSTARS*2; - ctx.drawImage(image['starfull'], + + + ctx.drawImage(image['stargrey'], LEVSEL_X + x + GRIDSIZE/2 - STARWID_LEVSEL_LOCKED*1.25, - LEVSEL_Y + y + GRIDSIZE - (GRIDSIZE/4) - (STARWID_LEVSEL_LOCKED/2), + //LEVSEL_Y + y + GRIDSIZE - (GRIDSIZE/4) - (STARWID_LEVSEL_LOCKED/2), + starreqy, STARWID_LEVSEL_LOCKED, STARWID_LEVSEL_LOCKED); ctx.textAlign = "left"; ctx.textBaseline = "top"; - shadowtext(ctx, this.levels[levnum].starsrequired, - TEXTSIZELEVSTARS, starcol, - LEVSEL_X + x + GRIDSIZE/2, LEVSEL_Y + y + GRIDSIZE - (GRIDSIZE/4) - (STARWID_LEVSEL_LOCKED/2)); - + shadowtext(ctx, this.levels[levnum].starsrequired, + TEXTSIZELEVSTARS, "#cccccc", + starreqx, starreqy); + } else { var hiscore,starcount,stars = ""; - var levy = LEVSEL_Y + y + GRIDSIZE/4; var scorey = LEVSEL_Y + y + GRIDSIZE - 5; var stary = levy + ((scorey - levy) / 2); // half way between - // show level num and hiscore + // show level num ctx.textAlign = "center"; ctx.textBaseline = "middle"; shadowtext(ctx, levnum, TEXTSIZELEVSELECT, textcol, LEVSEL_X + x + GRIDSIZE/2,levy); + // show hiscore + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; // get player hiscore hiscore = playerdata.getlevscore(levnum); @@ -4929,8 +5317,8 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio); what = getthingxy(lastmx, lastmy); if (what != undefined) { what.name = "xxx changed xx"; - what.type = "curtain"; - what.hp = CURTAINHP; + what.type = "cat"; + what.catcol = 0; game.dirty = true; } } else if (ch == 'l') { @@ -4939,7 +5327,16 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio); what = getthingxy(lastmx, lastmy); if (what != undefined) { what.name = "xxx changed xx"; - what.type = "cat"; + what.type = "llama"; + game.dirty = true; + } + } else if (ch == 'b') { + var what; + console.log("changing last clicked thing thing at " + lastmx/GRIDSIZE + "," + lastmy/GRIDSIZE ); + what = getthingxy(lastmx, lastmy); + if (what != undefined) { + what.name = "xxx changed xx"; + what.type = "box"; game.dirty = true; } } else if (ch == 'm') { @@ -5246,8 +5643,9 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio); 'cat1', 'catfull1', 'catscared1', 'llama', 'cheese', 'title', 'goat', 'lock','catwalkl','catwalkr','goatwalkl','goatwalkr', - 'starfull','starempty', 'curtain','curtainshred', 'curtainfall', + 'starfull','starempty', 'stargrey', 'curtain','curtainshred', 'curtainfall', 'door', 'sunlight', 'toad', 'whitecat', // special things + 'box', 'boxfront', 'boxback', 'brick', // obstacles 'bag', 'bagpop', 'fez', 'pow', 'brickpop', // effects 'tissues', 'shears', 'magiccarpet' ]; @@ -5389,8 +5787,13 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio); curpath[curpath.length-1].givepoints(); - // first one chomps last one - curpath[0].chomp(curpath[curpath.length - 1]); + + // first one chomps last one (or enters it, if it's a box) + if (curpath[curpath.length - 1].type == "box") { + curpath[0].enterbox(curpath[curpath.length - 1]); + } else { + curpath[0].chomp(curpath[curpath.length - 1]); + } break; case "climb": // cat climbs up the curtain @@ -5631,7 +6034,7 @@ function getrandomtype() { } // construct a list of permitted special things - var poss = [ "door", "sunlight", "toad", "whitecat" ] ; + var poss = [ "door", "sunlight", "toad", "whitecat", "curtain" ] ; for (i in poss ) { if (!game.isbanned(curlevel, poss[i])) { if (speciallist == undefined) { @@ -5656,9 +6059,9 @@ function getrandomtype() { if (dodb) console.log("specials are possible"); thinglist.push({ type: 'special', pct: 5 } ); } - if (!game.isbanned(curlevel, 'curtain')) thinglist.push({ type: 'curtain', pct: 5 } ); - if (!game.isbanned(curlevel, 'goat')) thinglist.push({ type: 'goat', pct: 10 } ); - if (!game.isbanned(curlevel, 'llama')) thinglist.push({ type: 'llama', pct: 10 } ); + if (!game.isbanned(curlevel, 'box')) thinglist.push({ type: 'box', pct: 5 } ); + if (!game.isbanned(curlevel, 'goat')) thinglist.push({ type: 'goat', pct: 8 } ); + if (!game.isbanned(curlevel, 'llama')) thinglist.push({ type: 'llama', pct: 12 } ); if (!game.isbanned(curlevel, 'food')) thinglist.push({ type: 'food', pct: 40 } ); if (!game.isbanned(curlevel, 'cat')) thinglist.push({ type: 'cat', pct: 45 } ); } @@ -5676,6 +6079,10 @@ function getrandomtype() { var goaltype = game.levels[curlevel].goals[n].type; var lookforthing; + if (goaltype == "ambush") { + goaltype = "box"; // need 'box' objects for this + } + if (game.levels[curlevel].goals[n].progress < game.levels[curlevel].goals[n].count) { if (goaltype == thingtype) { matchesgoal = true; @@ -5697,7 +6104,9 @@ function getrandomtype() { console.log("****** no things of type " + lookforthing); // extra chance! thinglist[i].pct *= 4; + if (thinglist[i].pct < 30) thinglist[i].pct = 30; console.log("extra chance of " + thingtype + "(" + lookforthing + ")"); +dodb = true; // if the thing in question is 'special', // cheat on the random check later to make sure we @@ -5760,6 +6169,8 @@ function thing(gridx, gridy, type, text, col) { this.isnew = true; this.matched = false; // temp for 'match3' things + this.boxfull = false; // for box objects + 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. @@ -5967,41 +6378,88 @@ function thing(gridx, gridy, type, text, col) { return false; } if (this.type != "cat") { - return false; + if (this.type == "box" && !this.boxfull) { + } else { + return false; + } } //if (isadjacenttotype(this, "llama")) { - if (this.isscared()) { + if (this.type == "cat" && this.isscared()) { return false; } // chomp - if (isadjacenttotype(this, "food") && !this.issleepy()) { - return true; + if (isadjacenttotype(this, "food")) { + if (this.type == "box" || !this.issleepy()) { + return true; + } } // parade - this is the hardest to check for. // check for any adjacent cats or llamas or goats // cat: if it also has an adjacent cat/llama/goat, we're good // llama: if it also has an adjacent cat/goat, we're good - for (i = 0; i < MAXDIRS; i++) { - var adj; - newx = this.gridx + DIRXMOD[i]; - newy = this.gridy + DIRYMOD[i]; - if (isonscreen(newx, newy)) { - adj = getgridthing(newx, newy); - if (adj != undefined) { - if ((adj.type == "cat") && (adj.catcol == this.catcol)) { - // adjacent cat - if (isadjacenttotype(adj, "llama", this) || - isadjacenttotype(adj, "cat", this, this.catcol) || - isadjacenttotype(adj, "goat", this)) { - return true; - } - } else if (adj.type == "llama") { - // adjacent llama - if (isadjacenttotype(adj, "cat", this, this.catcol) || - isadjacenttotype(adj, "goat", this)) { - return true; + if ((this.type == "cat") || (this.type == "box" && this.boxfull)) { + for (i = 0; i < MAXDIRS; i++) { + var adj; + newx = this.gridx + DIRXMOD[i]; + newy = this.gridy + DIRYMOD[i]; + if (isonscreen(newx, newy)) { + adj = getgridthing(newx, newy); + if (adj != undefined) { + if ((adj.type == "cat") && catcolmatches(adj,this)) { + // cat -> adjacent cat + if (isadjacenttotype(adj, "llama", this) || + isadjacenttotype(adj, "cat", this, this.catcol) || + isadjacenttotype(adj, "goat", this)) { + return true; + } + if (isadjacenttotype(adj, "box", this, null, true)) { + // cat -> adj cat -> full box + return true; + } + } else if (adj.type == "goat") { + // cat -> adjacent goat + if (isadjacenttotype(adj, "llama", this) || + isadjacenttotype(adj, "cat", this, this.catcol) || + isadjacenttotype(adj, "goat", this)) { + return true; + } + if (isadjacenttotype(adj, "box", this, null, true)) { + // cat -> adj goat -> full box + return true; + } + + } else if (adj.type == "llama") { + // cat -> adjacent llama + if (isadjacenttotype(adj, "cat", this, this.catcol) || + isadjacenttotype(adj, "goat", this)) { + return true; + } + if (isadjacenttotype(adj, "box", this, null, true)) { + // cat -> llama -> full box + return true; + } + } else if (adj.type == "box") { + // cat -> adjacent box + if (adj.boxfull) { + // full box - can continue a parade? + if (isadjacenttotype(adj, "cat", this, this.catcol) || + isadjacenttotype(adj, "goat", this) || + isadjacenttotype(adj, "llama", this)) { + return true; + } + } else { + // we can enter the box. + return true; + } + } else if (adj.type == "curtain") { + var nx2,ny2; + // next step along still on the grid? + nx2 = adj.gridx + DIRXMOD[i]; + ny2 = adj.gridy + DIRYMOD[i]; + if (isonscreen(nx2, ny2)) return true; + } } } @@ -6029,6 +6487,8 @@ function thing(gridx, gridy, type, text, col) { } else if (this.type == "llama") { points = LLAMAPOINTS; //game.progress("llama", 1); + } else if (this.type == "box") { + points = BOXCATPOINTS; } else if (this.type == "cat") { if (this.issleepy()) { points = SLEEPYCATPOINTS; @@ -6116,7 +6576,8 @@ function thing(gridx, gridy, type, text, col) { return desc; } - this.draw = function() { + // z is just used for drawing front/back of boxes + this.draw = function(z) { var yoff; var inpath = false; var howbig,myx,myy; @@ -6192,7 +6653,7 @@ function thing(gridx, gridy, type, text, col) { ctx.fillRect(BOARDX + myx, BOARDY + myy, this.size, this.size); ctx.globalAlpha = 1.0; } else { - var myimage; + var myimage,myimage2 = null; if (this.type == "cat") { var imgname; if (this.state == "parade") { @@ -6209,6 +6670,21 @@ function thing(gridx, gridy, type, text, col) { imgname = imgname + this.catcol; } myimage = image[imgname]; + } else if (this.type == "box") { + if (z == 0) { + var imgname2; + imgname = 'boxback'; + if (this.boxfull) { + imgname2 = 'cat'; + if (this.catcol > 0) { + imgname2 = imgname2 + this.catcol; + } + myimage2 = image[imgname2]; + } + } else { + imgname = 'boxfront'; + } + myimage = image[imgname]; } else if (this.type == "curtain") { if (this.hp == CURTAINHP) { imgname = 'curtain'; @@ -6257,6 +6733,9 @@ function thing(gridx, gridy, type, text, col) { */ ctx.drawImage(myimage, BOARDX + myx, BOARDY + myy, howbig, howbig); + if (myimage2 != undefined) { + ctx.drawImage(myimage2, BOARDX + myx, BOARDY + myy, howbig, howbig); + } // draw slashes on bricks drawslashes(ctx, BOARDX + myx, BOARDY + myy, this.slashes); @@ -6503,7 +6982,9 @@ function thing(gridx, gridy, type, text, col) { food.startexplode("chomp"); // mark that we've eaten something - this.sleepy = true; + if (this.type == "cat") { + this.sleepy = true; + } console.log("chomp"); } @@ -6883,11 +7364,17 @@ function thing(gridx, gridy, type, text, col) { } } else { + var below,willfall = false; + below = this.getstoppedbelowthing(); // regular gravity if ((this.gridy >= GRIDH-1)) { atbottom = true; } - if (!atbottom && !this.getstoppedbelowthing() && this.canfall()) { + if (!atbottom && !below && this.canfall()) { + willfall = true; + } + + if (willfall) { game.dirty = true; // need to redraw // accelerate this.yspeed += GRAVITY; @@ -6911,7 +7398,6 @@ function thing(gridx, gridy, type, text, col) { atbottom = true; this.state = "stop"; } - } // hit something? @@ -6930,6 +7416,17 @@ function thing(gridx, gridy, type, text, col) { } } } + + this.enterbox = function(box) { + game.dirty = true; + + box.boxfull = true; + box.catcol = this.catcol; + + // this cat vanishes + this.addabove(); + this.kill(); + } } function mainloop() { @@ -6982,13 +7479,23 @@ function mainloop() { // draw non-animating objects for (i = 0; i < things.length; i += 1) { if (!things[i].isanimating() && things[i].type != "firework") { - things[i].draw(); + things[i].draw(0); + } + } + // draw non-animating box tops + for (i = 0; i < things.length; i += 1) { + if (!things[i].isanimating() && things[i].type == "box") { + things[i].draw(1); } } // draw animating objects for (i = 0; i < things.length; i += 1) { if (things[i].isanimating() && things[i].type != "firework") { - things[i].draw(); + things[i].draw(0); + if (things[i].type == "box") { + // draw top as well + things[i].draw(1); + } } } // draw top of canvas (score etc) @@ -7009,10 +7516,10 @@ function mainloop() { } } - // draw fireworks + // draw fireworks and box tops for (i = 0; i < things.length; i += 1) { if (things[i].type == "firework") { - things[i].draw(); + things[i].draw(1); } } @@ -7192,6 +7699,31 @@ function matchthree() { things[i].matched = false; } } + + // also check for ambushes + for (i = 0; i < things.length; i++) { + if (!things[i].isanimating() && things[i].type == "llama" && + isadjacenttotype(things[i], "box", null, null, true)) { + things[i].matched = true; + } + } + + for (i = 0; i < things.length; i++) { + if (things[i].matched) { + things[i].matched = false; + + // ambush! + things[i].givepoints(); + things[i].addabove(); + + // add "pow" + things.push(new thing(things[i].gridx, things[i].gridy, "pow")); + + things[i].kill(); + + game.progress("ambush", 1); + } + } } function levelfinished() { diff --git a/images/box.png b/images/box.png new file mode 100644 index 0000000000000000000000000000000000000000..5ae9607490d1f9761c317b64f2e9df75058d1ad5 GIT binary patch literal 4269 zcmV;e5K`}nP)qs;8(bVj2bsm~omVNULofUXVl^=@ej}qZbqB1KgvtR%A@wxx=06hM& zo%>pr{))T*T$=iIW;Sf@Wp}5xD9knl1ylr8P?eU5%&E$J0&|EQNmO1G;l*+(dGW9R ziYI{@nkEN-9$jwTrJ7$KvV-{cIOxK~d2%?G#aT8Pp z6+wjjwF-!ctBR@cvWmQ{Dle( z^^w$V(9KHbE~ym^cE=(RW{$ftwct!If(Rrl43-=SF8O~3RQ%48KwU)^1ug)un)?fG z>9_v$pN|~=u>kOwpV^W-&I(c`Ou;O1PIPnoJa zf=2pB;}9e>R)g`05+ad1e@S!%YpbNBV!zi&62Mu#y^NL?`$CwaRQT^Oku(ya&$NnHJ~gQXo>lV5}4X z$pkWZ8xXLZ6iOs?pEMXQ|EBsV^=uUteObzJ!@Yar0n+ zw?Pqc#->-J+_WRm zI9P+qbjaXvOdeWHJPczZPg8V&7eHk^o8p4A0nP-Ve|Lz{}76{$4l#Wq0cb z1GHeMpg1nx3Bn2>g6RP;CuE4!K&1shceTO|n*%7h5f#W+to1TYJO5c^3qUIE5clMf$w z_;XL>0Q}cC|E#OoY(3}5aM93?3l_=aXQeUTalCUcxuvUZZLw2T7MGSea(tZ0sTzHK zT?laO)Hp{@o@I3X5PiM9w4z5lj3p_A!NtcAeLE5PVt04-Q+pr!%<+y8SXf+o78uH? zMS=9W#JIGfxh<`OWU^7Lh&f{ytH?Gtp$oaS5H9MKF>!13b{$(7+7$SPDyI zO4y5M>`3yOq8LJ`a_I00e)Q%M`g(gQm&>R?nugCILU&h%?yfRvJq3hvxx#;Z=ik}& zo*TL8mfM+~o8`=@W6VsR$6Bq>D>xYls{;UV;Nj2D0zZfw0H6Qx$W7O6+4Z->8#eD7 zy?zIS>qbe+W!%YCKhz1tobNH+1-hpa_d$OnOhFGsG!Ka+QKo0-7#p8pdAY$re-D*X z5`xM?$~1E{QF?m1F(478QYlj|CCp4-;CtVBE?!UUH3%iQS?Clm3&5q;(BOuoK3|ji ze2vpb-$2V{dV2fl=^LcCe~7-pVfu$Q(9=JJmb$=Nm>c40tQP_(#43?k6=a&=c$Skn zc<2akA397=PdAmML@7yv0jVKMG(@OW$_!`{`U3$oVxtxJ=D`)Y@qXD>e^mf7pNfQW z6~I!xPGhM~ZR#u$lL=(;tc(&8kR(Zb;ZGp8u7T5{C~T<@si2SI>YjvkPr08hUTh6f+G4a%@lC zocWmx%-1H7gRfAjR_W^QquSF;ci$krgX`$)AEw&fjRR&ah=43EFSE2TM|WB2S~ozY zT%xO5L9zxYulX%6nZr2>Mi$#`F8~wYziI$d2h9p#Gei}$(4U)Gn22QcqG(Wi71CCV z#f4dx>T}FZp3Pg@Ql-Mcx(y7BY@)Y+9o;>BoIi7z#=;EiM}~r6icl$+L+P4^$x>GM z=Z1C+T-u(`!09kP`~KAcfE(taFAs_u@-`MKHaEwW=n;#w4b`)|1>uW>4MecCMeV{k zwF~2DqEsqfnIclsP^M<%E_1^$EM}Q7a?6Zk1qhkJh8uZ!nRy(_TqOYRK~>E`%urEq z!DB3YG}tAQ!3Fq8>YLVO0WoA2&)iq zcu1Y@81AW=mpkJ7BF~5Mn-#>b_*wUBWI*bm9t;WTHHJexaS}h9>w<-mmZu>^%neCm zttjo$mO6-mM}bu}+yvK-xuIpAH!lbv*>t&}`YXgQV~_bePrg?dK}%y93l?X25=YQt zp~}}48qneCL@^IWr{*M4JVhi23I#O-iDgmZv6hfHI=7tG9jYH=JInQE#ah5t2c?NNHh%ditfVy9>!~gDB08m%&=H@1p2q@`b_mZQlVX{3=Y?RZFK+^GeIas zELMJE;X(u56{4YtA+Cspx!%fDXjyj1?ixi5h{Mtt1L53m;SO>dKwr)CZLuT2N09D!gODou+m zaPHZ>2e3;vKIWa(Vg`^3w9G5HPcH$&ssLydA`8w9-gC?Qfgm=a2guT&NSqf%FDjYQ z+NP$(xu9mj7^evqKd;i+*w`gfV8#H7m0&yVi9nhmRpu+ zSv5>}JPKWCctWug+s#W3#5z5*O<&-mj&qOg)x#X)7TQr5d#DO(gNl@d{n1(C-FM~I3q zg~@j;p2&_B_DK6?NXIcDRF?5|s3Xj0Y71s&rDFFNv?+#&#kqw!i3-b2=k>ArOD`Rp z|EcMbKH69|n_5(g#{nb3Zy zLE8^BsGwQ5m%WzoI@}S~_CpY=BuPS}*|d{m6HRxo<~=|`;l03$k_vB+FV)%$jD?)~ZY1C>2}UCGw|?ow}eHOX&}hOV#O z{b>=5{7H}EvFsrTMN}w708X5qXqsEK-2+6ii=G#8Y742oF;;)>=)}^OYxUOmfL8Q6 zmoxrykI2X>$1^cWs%7mfmvl!Zk$blcSAXG_t^N0GAMF_~mo%RRtTea?NX`K5WK1bZ zSZ+4$#Mrr}nOE~!K%pBfCBlCmoj>!&Sp9cu_0}^$?J_pKYXIH}giD>Y1Z*m)+;PkG zeed5f+H?21zUuD5-ty?WzH(AZG(TN<0747EwCS(XX27wriKdxVi#>qgK0eb}`oYop zZ=9QH{6RDIw^mDWmoxsy0l-RD6t_}WIT-==bXD{NcWfVg;MQ#eH*Xs5sf1@6Bt99| zW2pnUujZ)`?AveD-aK+{@$qKr{|YQ#p&eHZz_oyoy_d$<{lLzVzRLdH z*Y_XTvcBiek-o~#4TD{MgFO||e8#AhN(sx&h8;h3wrTEFbNuMU($tHGW}m7prcVN6 z@AA6*TAmZU(jR&!P>SdAa2H&9RApN$wfnY@_I~KD8;AGbwryzRhJh|cgyrR?9XWkA zovo+xt=DE=n3!!m4!l?pWw{o^ujWC?YXM>+lPw{02j-v3iOhwmBaPHr2U zm}z|f@Z4WDQvWJ2vx>T}erw}@;8EFY1>s6TDg%S@#^#wT5V?2l`E30+76KBYdNzWX P00000NkvXXu0mjf+0ZMG literal 0 HcmV?d00001 diff --git a/images/boxback.png b/images/boxback.png new file mode 100644 index 0000000000000000000000000000000000000000..f60cb5a30ef472919fa26580faac23822c8ab276 GIT binary patch literal 1099 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 - ca CU CU ch + update validmoves check - to - - ------------| - | V - ch CU- CU- ca - ^ | - ------------- - - After being climbed twice, curtains are shredded. - - ch ca - - CU- ----> POP ----> ca - - ca ch ch remaining levels. @@ -56,8 +46,18 @@ remaining levels. goal: x parades of y length!!! + random levels. + --- + 1-3 goals + Get max goal counts for level + Split up 100% worth of count over the chosen goals. + ie. 60% of 1, 25% of another, 15% of the third + or. 70% of 1, 30% of another + ---- + move things like "get required stars for level" out of addlevel() + -------------- @@ -66,7 +66,6 @@ random levels. more prizes: ??? - box ? overeat (cheese changes to niblet bags, cans eat without sleepiness) mouse - place to clear all cats in grid/column