diff --git a/cat.html b/cat.html
index 4418a69..16b455c 100644
--- a/cat.html
+++ b/cat.html
@@ -36,9 +36,11 @@ canvas {
// game vars
var things = [];
var score = 0;
+var multiplier = 1;
var overdesc = "";
var curpath = [];
var pathdir = -1;
+var pathdoor = null;
var pathvalid = false;
var curlevel = 1;
var lastmx = -1, lastmy = -1;
@@ -47,11 +49,14 @@ var lastmx = -1, lastmy = -1;
// goal types
var GOALVERB = {
'food': 'Eat',
+ 'turns': 'Survive',
'points': 'Earn',
'parades': 'Form',
'llamas': 'Clear',
'cats': 'Clear',
'goats': 'Clear',
+ 'doors': 'Enter',
+ 'sun cycles': 'Wait out',
};
var FULLSTAR = "\u2605";
@@ -73,6 +78,7 @@ var THINGSIZE = 64;
var TEXTSIZE = 16; // in points
+var TEXTSIZEMULTIPLIER = 28; // in points
var TEXTSPEED = 0.5;
var TEXTFADESPEED = 0.05;
var TEXTTIME = 35;
@@ -112,6 +118,9 @@ var EXPLODETICKS=20;
var EXPLODEGAIN= (THINGSIZE*2) / EXPLODETICKS;
var EXPLODEFADESPEED = 1.0 / EXPLODETICKS;
+var SHRINKTICKS=20;
+var SHRINKLOSE= (THINGSIZE / SHRINKTICKS);
+
var LINEWIDTH=2;
var CROSSWIDTH=2;
@@ -142,7 +151,7 @@ var FOODPOINTS = 10;
var LLAMAPOINTS = 100;
var GOATPOINTS = 50;
var CATPOINTS = 20;
-var SLEEPYCATPOINTS = 30;
+var SLEEPYCATPOINTS = 40;
var overdesc = "";
@@ -203,7 +212,7 @@ function pathcomplete() {
case "chomp":
if ((curpath.length >= 2) &&
(curpath[0].type == "cat") &&
- (curpath[0].eaten == false)) {
+ !curpath[0].issleepy()) {
var i;
var ok = true;
// everything else is food?
@@ -292,12 +301,26 @@ function pathcontains(what) {
return false;
}
+// return sfirst thing of matching type
+function pathcontainstype(type) {
+ var i;
+ if (curpath == undefined) return false;
+
+ for (i = 0; i < curpath.length; i += 1) {
+ if (curpath[i].type == type) {
+ return curpath[i];
+ }
+ }
+ return null;
+}
+
function isvalidpath(mypath) {
var valid = true;
var firstcat = false;
var fcount = 0;
var lcount = 0;
var gcount = 0;
+ var count = 0;
var i;
for (i = 0; i < mypath.length - 1; i++) {
@@ -321,6 +344,7 @@ function isvalidpath(mypath) {
if (thisone.type == "goat") {
gcount++;
}
+ count++;
if ((thisone.type == "cat") && (nextone.type == "cat")) {
// no parades on level 1
@@ -331,6 +355,9 @@ function isvalidpath(mypath) {
} else if ((thisone.type == "goat") && (nextone.type == "cat" || nextone.type == "llama" || nextone.type == "goat")) {
// goat can go to llama or cat
// ok
+ } else if ((nextone.type == "door") && (count >= PARADELENGTH) && (fcount == 0) && (count >= 3) &&
+ (thisone.type == "goat" || thisone.type == "cat" || thisone.type == "llama")) {
+ // completed parades can extend into doors
} else if ((thisone.type == "cat") && nextone.type == "llama") {
// no parades on level 1
if (curlevel == 1) {
@@ -522,7 +549,7 @@ function thingsfalling() {
function thingsmoving() {
var i;
for (i = 0; i < things.length; i += 1) {
- if (things[i].state == "parade") {
+ if ((things[i].state == "parade") || (things[i].state == "shrink")) {
return "parade";
}
}
@@ -878,6 +905,16 @@ var game = {
return true;
},
+ turneffects : function() {
+ var i;
+ for (i = 0; i < things.length; i += 1) {
+ // suns can move again
+ if (things[i].type == "sunlight" && things[i].counter == 1) {
+ things[i].counter = 0;
+ }
+ }
+ },
+
resize : function() {
this.curh = window.innerHeight;
this.curw = this.curh * this.ratio;
@@ -901,6 +938,7 @@ var game = {
initgamevars : function() {
score = 0;
+ multiplier = 1;
this.frameNo = 0;
},
@@ -909,9 +947,7 @@ var game = {
clearthings();
overdesc = "";
- curpath = [];
- pathdir = -1;
- pathvalid = false;
+ clearpath();
},
addlevel : function (lev, hashelp) {
@@ -1028,7 +1064,7 @@ var game = {
calcstarpoints : function( lev ) {
var i;
- var min = 0,gotpointsgoal = false;
+ var min = 0,pointsgoal = false;
// calculate minimum points required to win
// first pass
for (i = 0; i < this.levels[lev].goals.length; i++) {
@@ -1046,31 +1082,31 @@ var game = {
case "goats":
min += GOATPOINTS * this.levels[lev].goals[i].count;
break;
+ case "turns":
+ min += FOODPOINTS * this.levels[lev].goals[i].count;
+ break;
+ case "doors":
+ // double the value of a minimum-score parade
+ min += Math.min(CATPOINTS, SLEEPYCATPOINTS) * 3 * 2 * this.levels[lev].goals[i].count;
+ break;
+ case "sun cycles":
+ min += SLEEPYCATPOINTS*5 * this.levels[lev].goals[i].count;
+ break;
}
}
// second pass - overrides
for (i = 0; i < this.levels[lev].goals.length; i++) {
switch (this.levels[lev].goals[i].type) {
case "points":
- min = this.levels[lev].goals[i].count;
- gotpointsgoal = true;
+ pointsgoal = this.levels[lev].goals[i].count;
break;
}
}
this.levels[lev].starpoints = new Array();
- if (gotpointsgoal) {
- // if the level ends as soon as you get a certain # of points,
- // your only hope of boosting higher is to get LOTS of points
- // on your last turn.
- this.levels[lev].starpoints[0] = min;
- this.levels[lev].starpoints[1] = Math.floor(min * 1.1);
- this.levels[lev].starpoints[2] = Math.floor(min * 1.2);
- } else {
- this.levels[lev].starpoints[0] = Math.floor(min);
- this.levels[lev].starpoints[1] = Math.floor(min * 2);
- this.levels[lev].starpoints[2] = Math.floor(min * 3);
- }
+ this.levels[lev].starpoints[0] = Math.floor(Math.max(min, pointsgoal));
+ this.levels[lev].starpoints[1] = Math.floor(Math.max(min * 2, pointsgoal*1.5));
+ this.levels[lev].starpoints[2] = Math.floor(Math.max(min * 3, pointsgoal*2));
},
initlevels : function ( ) {
@@ -1081,49 +1117,62 @@ var game = {
this.addlevel(1, true);
this.addlevelgoals(1, "food", 5);
this.setstarpoints(1, 50, 60, 80);
- this.addlevelthings(1, "cat", 50, "food", 100);
+ this.addlevelthings(1, "cat", 50, "food", 50);
this.addlevel(2, true);
this.addlevelgoals(2, "cats", 10);
this.addlevelgoals(2, "parades", 3);
- this.addlevelthings(2, "cat", 45, "food", 100);
+ this.addlevelthings(2, "cat", 45, "food", 55);
this.addlevel(3, true);
- this.addlevelthings(3, "cat", 45, "food", 90, "llama", 100);
+ this.addlevelallowedthings(3, "cat", "food", "llama");
this.addlevelgoals(3, "llamas", 3);
this.addlevel(4, true);
this.addlevelgoals(4, "llamas", 5);
this.addlevelgoals(4, "food", 5);
- this.addlevelthings(4, "cat", 45, "food", 90, "llama", 100);
+ this.addlevelallowedthings(4, "cat", "food", "llama");
this.addlevel(5, false);
- this.addlevelgoals(5, "points", 1000);
- this.addlevelthings(5, "cat", 45, "food", 90, "llama", 100);
+ this.addlevelgoals(5, "turns", 10);
+ this.addlevelgoals(5, "points", 600);
+ this.addlevelallowedthings(5, "cat", "food", "llama");
// introduce goats!
this.addlevel(6, true);
this.addlevelgoals(6, "goats", 3);
- this.addlevelthings(6, "goat", 10, "cat", 60, "food", 90, "llama", 100); // higher than normal goat chance
+ this.addlevelthings(6, "goat", 10, "cat", 50, "food", 30, "llama", 10); // higher than normal goat chance
this.addlevelforcethings(6, "goat", 1);
this.addlevel(7, false);
this.addlevelallowedthings(7, "goat", "cat", "food", "llama");
- this.addlevelgoals(7, "points", 1000);
+ this.addlevelgoals(7, "turns", 15);
this.addlevelgoals(7, "llamas", 2);
this.addlevelgoals(7, "goats", 2);
this.addlevel(8, false);
this.addlevelallowedthings(8,"goat", "cat", "food", "llama");
- this.addlevelgoals(8, "points", 1100);
+ this.addlevelgoals(8, "turns", 20);
this.addlevelgoals(8, "llamas", 3);
// introduce doors
-/*
- this.addlevel(8, false);
- this.addlevelgoals(8, "doors", 1);
- this.addlevelforcethings(8, "door", 1);
-*/
+ this.addlevel(9, true);
+ this.addlevelallowedthings(9,"goat", "cat", "food", "llama", "door");
+ this.addlevelgoals(9, "doors", 1);
+ this.addlevelforcethings(9, "door", 1);
+
+ this.addlevel(10, false);
+ this.addlevelallowedthings(10,"goat", "cat", "food", "llama", "door");
+ this.addlevelgoals(10, "points", 2000);
+ this.addlevelgoals(10, "turns", 15);
+
+ // introduce sunlight
+ this.addlevel(11, true);
+ this.addlevelallowedthings(11,"goat", "cat", "food", "llama", "door", "sunlight");
+ this.addlevelgoals(11, "turns", 10);
+ this.addlevelgoals(11, "sun cycles", 1);
+ this.addlevelforcethings(11, "sunlight", 1);
+
for (i = 1; i < this.levels.length; i++) {
var extrastars;
@@ -1175,14 +1224,14 @@ var game = {
}
// force items
- if (game.levels[curlevel].forcethings != undefined) {
- for (i = 0; i < game.levels[curlevel].forcethings.length; i++) {
- var wanttype,thisnum;
- wanttype = game.levels[curlevel].forcethings[i].type;
- wantnum = game.levels[curlevel].forcethings[i].howmany;
+ if (game.levels[curlevel].forcelist != undefined) {
+ for (i = 0; i < game.levels[curlevel].forcelist.length; i++) {
+ var wanttype,wantnum;
+ wanttype = game.levels[curlevel].forcelist[i].type;
+ wantnum = game.levels[curlevel].forcelist[i].howmany;
// while we don't have enough...
- while (countthingsoftype(wanttype) < num) {
+ while (countthingsoftype(wanttype) < wantnum) {
// add one.
var idx;
idx = rnd(things.length);
@@ -1451,7 +1500,7 @@ var game = {
} else {
var zoomw,zoomh;
// draw winning cat image
- console.log("drawing win img. tapx:" + tapx + " tapy:" + tapy + " tapw:" + tapw + " taph:" + taph);
+ //console.log("drawing win img. tapx:" + tapx + " tapy:" + tapy + " tapw:" + tapw + " taph:" + taph);
zoomw = tapw * game.winimgsize;
zoomh = taph * game.winimgsize;
@@ -2314,6 +2363,246 @@ var game = {
y += gridsize;
cury = y;
+ } else if (curlevel == 9) {
+ cury = this.drawhelpsubtitle(ctx, "Doors", cury);
+
+ ctx.textAlign = "left";
+ ctx.textBaseline = "bottom";
+ shadowtext(ctx, "Cats love escaping outside through doors.", HELPTEXTSIZE,helpcol, textxspace, cury);
+ cury += HELPTEXTYSPACE;
+ shadowtext(ctx, "Ending a parade on a door will score double points!", HELPTEXTSIZE,helpcol, textxspace, cury);
+ cury += HELPTEXTYSPACE;
+
+ // top line of parade
+ x = imgsize;
+ y = cury;
+ row1y = y;
+ ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
+ linex[0] = x + imgsize/2;
+ liney[0] = y + imgsize/2;
+ x += gridsize;
+
+ ctx.drawImage(image['catscared'], x, y, imgsize, imgsize);
+ linex[3] = x + imgsize/2;
+ liney[3] = y + imgsize/2;
+ x += gridsize;
+
+ ctx.drawImage(image['llama'], x, y, imgsize, imgsize);
+ linex[4] = x + imgsize/2;
+ liney[4] = y + imgsize/2;
+ x += gridsize;
+
+ // middle line of parade
+ x = imgsize;
+ y += gridsize;
+ row2y = y;
+
+ ctx.drawImage(image['goat'], x, y, imgsize, imgsize);
+ linex[1] = x + imgsize/2;
+ liney[1] = y + imgsize/2;
+ x += gridsize;
+
+ ctx.drawImage(image['catscared'], x, y, imgsize, imgsize);
+ linex[2] = x + imgsize/2;
+ liney[2] = y + imgsize/2;
+ x += gridsize;
+
+ ctx.drawImage(image['door'], x, y, imgsize, imgsize);
+ linex[5] = x + imgsize/2;
+ liney[5] = y + imgsize/2;
+
+
+ // parade lines
+ cury = y + HELPTEXTYSPACE;
+ for (i = 0; i < 5; i++) {
+ drawline(ctx, linex[i], liney[i], linex[i+1], liney[i+1], "green", LINEWIDTH);
+ }
+ drawarrow(ctx, linex[4], liney[4], linex[5], liney[5], "green", LINEWIDTH, PATHARROWSIZE);
+
+ // arrow to middle
+ x = x + gridsize;
+ y = row2y;
+
+ x2 = midpoint2 - 10;
+ y2 = y;
+
+ drawarrow(ctx, x, y, x2, y2, "red", HELPLINEWIDTH, HELPARROWSIZE);
+
+ // explain points for doors
+ ctx.textAlign = "left";
+ ctx.textBaseline = "top";
+ x = midpoint2;
+
+ y = row2y - HELPTEXTYSPACE/2;
+ shadowtext(ctx, "x2 points", HELPTEXTSIZE,pointscol, x, y);
+
+ cury = y;
+ cury += HELPTEXTYSPACE;
+ cury += HELPTEXTYSPACE;
+ cury += HELPTEXTYSPACE;
+ cury += HELPTEXTYSPACE;
+
+ ctx.textAlign = "left";
+ ctx.textBaseline = "bottom";
+ shadowtext(ctx, "Doors don't fall down like other objects.", HELPTEXTSIZE,helpcol, textxspace, cury);
+ cury += HELPTEXTYSPACE;
+ shadowtext(ctx, "They are only removed when a parade enters them.", HELPTEXTSIZE,helpcol, textxspace, cury);
+ cury += HELPTEXTYSPACE;
+
+ // top line of door fall example
+ x = imgsize;
+ y = cury;
+ row1y = y;
+ ctx.drawImage(image['goat'], x, y, imgsize, imgsize);
+ x += gridsize;
+
+ ctx.drawImage(image['door'], x, y, imgsize, imgsize);
+ x += gridsize;
+
+ ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
+ x += gridsize;
+
+ // middle line of parade
+ x = imgsize;
+ y += gridsize;
+ row2y = y;
+
+ ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
+ linex[1] = x + imgsize/2;
+ liney[1] = y + imgsize/2;
+ 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['cheese'], x, y, imgsize, imgsize);
+
+ // cat eating food line
+ drawarrow(ctx, linex[0], liney[0], linex[1], liney[1], "green", LINEWIDTH, PATHARROWSIZE);
+
+ // arrow to middle
+ x = x + gridsize;
+ y = row2y;
+
+ x2 = midpoint2 - 10;
+ y2 = y;
+
+ drawarrow(ctx, x, y, x2, y2, "red", HELPLINEWIDTH, HELPARROWSIZE);
+
+ // top line of part 2 of door fall example
+ x = midpoint2;
+ y = cury;
+ row1y = y;
+ ctx.drawImage(image['goat'], x, y, imgsize, imgsize);
+ x += gridsize;
+
+ ctx.drawImage(image['door'], x, y, imgsize, imgsize);
+ x += gridsize;
+
+ ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
+ x += gridsize;
+
+ // middle line of parade
+ x = midpoint2;
+ y += gridsize;
+ row2y = y;
+
+ ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
+ linex[0] = x + imgsize/2;
+ liney[0] = y + imgsize/2;
+
+ x += gridsize*2;
+
+ ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
+ } else if (curlevel == 11) {
+ cury = this.drawhelpsubtitle(ctx, "Sunlight", cury);
+
+ ctx.textAlign = "left";
+ ctx.textBaseline = "bottom";
+ shadowtext(ctx, "Cats love luxuriating in sunlight.", HELPTEXTSIZE,helpcol, textxspace, cury);
+ cury += HELPTEXTYSPACE;
+ shadowtext(ctx, "Any cats next to a sun will fall asleep.", HELPTEXTSIZE,helpcol, textxspace, cury);
+ cury += HELPTEXTYSPACE;
+
+ x = (SCREENW / 2) - gridsize/2 - gridsize;
+ y = cury;
+ ctx.drawImage(image['catfull'], x, y, imgsize, imgsize);
+
+ x += gridsize;
+ y = cury;
+ ctx.drawImage(image['sunlight'], x, y, imgsize, imgsize);
+
+ x += gridsize;
+ y = cury;
+ ctx.drawImage(image['catfull'], x, y, imgsize, imgsize);
+
+ cury += gridsize;
+
+ x = (SCREENW / 2) - gridsize/2 - gridsize;
+ y = cury;
+ ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
+
+ x += gridsize;
+ y = cury;
+ ctx.drawImage(image['goat'], x, y, imgsize, imgsize);
+
+ x += gridsize;
+ y = cury;
+ ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
+
+ cury += HELPTEXTYSPACE;
+ cury += HELPTEXTYSPACE;
+ cury += HELPTEXTYSPACE;
+ cury += HELPTEXTYSPACE;
+
+ shadowtext(ctx, "Each turn, suns swap places with the object below.", HELPTEXTSIZE,helpcol, textxspace, cury);
+ cury += HELPTEXTYSPACE;
+ shadowtext(ctx, "Cats will awaken once out of the sunlight.", HELPTEXTSIZE,helpcol, textxspace, cury);
+ cury += HELPTEXTYSPACE;
+
+ x = (SCREENW / 2) - gridsize/2 - gridsize;
+ y = cury;
+ ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
+
+ x += gridsize;
+ y = cury;
+ ctx.drawImage(image['goat'], x, y, imgsize, imgsize);
+ linex[0] = x + imgsize/2;
+ liney[0] = y + imgsize/2;
+
+ x += gridsize;
+ y = cury;
+ ctx.drawImage(image['cat'], x, y, imgsize, imgsize);
+
+ cury += gridsize;
+
+ x = (SCREENW / 2) - gridsize/2 - gridsize;
+ y = cury;
+ ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
+
+ x += gridsize;
+ y = cury;
+ ctx.drawImage(image['sunlight'], x, y, imgsize, imgsize);
+ linex[1] = x + imgsize/2;
+ liney[1] = y + imgsize/2;
+
+ x += gridsize;
+ y = cury;
+ ctx.drawImage(image['cheese'], x, y, imgsize, imgsize);
+
+ drawarrow(ctx, linex[0], liney[0], linex[1], liney[1], "#dd0000", LINEWIDTH, PATHARROWSIZE);
+ drawarrow(ctx, linex[1], liney[1], linex[0], liney[0], "#dd0000", LINEWIDTH, PATHARROWSIZE);
+
+ cury += HELPTEXTYSPACE;
+ cury += HELPTEXTYSPACE;
+ cury += HELPTEXTYSPACE;
+ cury += HELPTEXTYSPACE;
+
+
+ shadowtext(ctx, "After reaching the the bottom of the play area, suns will set.", HELPTEXTSIZE,helpcol, textxspace, cury);
+ cury += HELPTEXTYSPACE;
}
@@ -2620,6 +2909,7 @@ var game = {
} else if (game.state == "gameover") {
if ((realx >= tapx) && (realx <= tapx + tapw) &&
(realy >= tapy) && (realy <= tapy + taph)) {
+ game.clearlevelprogress(curlevel);
game.setstate("levselect");
}
} else if (game.state == "title") {
@@ -2838,14 +3128,29 @@ var game = {
// first one chomps last one
curpath[0].chomp(curpath[curpath.length - 1]);
+
+ game.progress("turns", 1);
break;
case "parade":
+ multiplier = 1;
if (curpath.length >= 2) { // should always be true
var i;
// everything in the path exits via a parade
+
+ pathdoor = pathcontainstype("door");
+ if (pathdoor) multiplier++;
+
for (i = 0; i < curpath.length; i++) {
- curpath[i].givepoints();
- curpath[i].startparade();
+ // ... except doors
+ if (curpath[i].type == "door") {
+ game.progress("doors", 1);
+ console.log("path has doors!");
+ // add animation
+ things.push(new thing(curpath[i].gridx, curpath[i].gridy, "text", "x" + multiplier));
+ } else {
+ curpath[i].givepoints();
+ curpath[i].startparade();
+ }
}
clearpath();
} else {
@@ -2857,11 +3162,16 @@ var game = {
curpath.splice(0, 1);
}
}
+ multiplier = 1;
game.progress("parades", 1);
+ game.progress("turns", 1);
break;
}
clearpath();
+
+ // things that happen once per turn.
+ game.turneffects();
},
}
@@ -2932,6 +3242,7 @@ function shadowtext(ctx, text, size, col, x, y) {
function getrandomtype() {
var roll,tot,type = null,i;
var thinglist,maxroll = 0;
+ var speciallist = null;
if (curlevel >= game.levels.length) {
thinglist = null;
@@ -2939,20 +3250,39 @@ function getrandomtype() {
thinglist = game.levels[curlevel].thinglist;
}
+ // construct a list of permitted special things
+ var poss = [ "sunlight" ] ;
+ for (i in poss ) {
+ if (!game.isbanned(curlevel, poss[i])) {
+ if (speciallist == undefined) {
+ speciallist = [];
+ }
+ speciallist.push(poss[i]);
+ }
+ }
+
+ console.log("speciallist is " + speciallist);
+
if (thinglist == undefined || thinglist.length == 0) {
var f;
thinglist = new Array();
// default thinglist
// must be sorted from low to high!
- if (!game.isbanned(curlevel, 'goat')) thinglist.push({ type: 'goat', pct: 5 } );
- if (!game.isbanned(curlevel, 'llama')) thinglist.push({ type: 'llama', pct: 10 } );
- if (!game.isbanned(curlevel, 'cat')) thinglist.push({ type: 'cat', pct: 40 } );
- if (!game.isbanned(curlevel, 'food')) thinglist.push({ type: 'food', pct: 45 } );
+ if (!game.isbanned(curlevel, 'door')) thinglist.push({ type: 'door', pct: 10 } );
+ if (speciallist != undefined) {
+ console.log("specials are possible");
+ thinglist.push({ type: 'special', pct: 10 } );
+ }
+ if (!game.isbanned(curlevel, 'goat')) thinglist.push({ type: 'goat', pct: 10 } );
+ if (!game.isbanned(curlevel, 'llama')) thinglist.push({ type: 'llama', pct: 20 } );
+ if (!game.isbanned(curlevel, 'food')) thinglist.push({ type: 'food', pct: 40 } );
+ if (!game.isbanned(curlevel, 'cat')) thinglist.push({ type: 'cat', pct: 45 } );
}
for (i = 0; i < thinglist.length; i++) {
maxroll += thinglist[i].pct;
+ //console.log(thinglist[i].type + ": " + thinglist[i].pct + " [" + maxroll + "]");
}
roll = rnd(maxroll);
@@ -2960,14 +3290,19 @@ function getrandomtype() {
for (i = 0; i < thinglist.length; i++) {
tot += thinglist[i].pct;
if (roll <= tot) {
+ console.log("rolled " + roll + "/" + maxroll + " --> " + thinglist[i].type + " [<= " + tot + "]");
+
type = thinglist[i].type;
break;
}
}
- if (type == null) {
+ if (type == null || type == undefined) {
console.log("couldn't find type! roll is " + roll);
type = 'cat';
+ } else if (type == "special") {
+ // pick from list of specials
+ type = speciallist[rnd(speciallist.length)];
}
return type;
}
@@ -2979,9 +3314,28 @@ function coord(x,y) {
function thing(gridx, gridy, type, text) {
this.opacity = 1.0;
+ this.isnew = true;
if (type == "random") {
type = getrandomtype();
+ console.log("got random type "+ type);
+ }
+ // used for various things
+ if (type == "sunlight") {
+ this.counter = 1;
+ } else {
+ this.counter = 0;
+ }
+
+ if (type == undefined) {
+ console.log("type is now " + type);
+ debugger;
+ }
+
+ if (text == undefined) {
+ this.name = type + "-" + getrandomname();
+ } else {
+ this.name = text;
}
this.type = type;
@@ -2996,7 +3350,11 @@ function thing(gridx, gridy, type, text) {
this.color = "#cccccc";
break;
case "text":
- this.color = "#00cc00";
+ if (this.name.indexOf("x") == 0) {
+ this.color = "#00dddd";
+ } else {
+ this.color = "#00cc00";
+ }
break;
default: // should never happen
this.color = getrandomcolour();
@@ -3004,17 +3362,16 @@ function thing(gridx, gridy, type, text) {
}
if (this.type == "text") {
- this.size = TEXTSIZE;
+ if (this.name.indexOf("x") == 0) {
+ this.size = TEXTSIZEMULTIPLIER;
+ } else {
+ this.size = TEXTSIZE;
+ }
} else {
this.size = THINGSIZE;
}
this.lifetime = 0;
- if (text == undefined) {
- this.name = type + "-" + getrandomname();
- } else {
- this.name = text;
- }
this.gridx = gridx;
if (gridy == "top") {
@@ -3040,9 +3397,9 @@ function thing(gridx, gridy, type, text) {
this.path = [];
this.pathspeed = PARADESPEED;
-
this.expcount = 0;
this.expmax = 0;
+ this.eaten = false;
if (this.type == "text" ) {
this.x = gridx * GRIDSIZE + (GRIDSIZE/2);
@@ -3052,7 +3409,27 @@ function thing(gridx, gridy, type, text) {
this.y = gridy * GRIDSIZE + (GRIDSIZE/2) - (this.size/2);
}
- this.eaten = false;
+
+ this.issleepy = function() {
+ if (this.type == "cat") {
+ if (this.eaten == true) {
+ return true;
+ } else if (isadjacenttotype(this, "sunlight")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ this.canfall = function() {
+ // doors can't fall after their initial drop
+ if (this.type == "door") {
+ if ((this.gridy >= 0) && (this.new == false)) {
+ return false;
+ }
+ }
+ return true;
+ }
this.pushpath = function(x,y) {
this.path.push(new coord(x, y));
@@ -3077,7 +3454,7 @@ function thing(gridx, gridy, type, text) {
}
// chomp
- if (isadjacenttotype(this, "food") && !this.eaten) {
+ if (isadjacenttotype(this, "food") && !this.issleepy()) {
return true;
}
@@ -3122,7 +3499,7 @@ function thing(gridx, gridy, type, text) {
points = LLAMAPOINTS;
game.progress("llamas", 1);
} else if (this.type == "cat") {
- if (this.eaten == true) {
+ if (this.issleepy()) {
points = SLEEPYCATPOINTS;
} else {
points = CATPOINTS;
@@ -3132,11 +3509,16 @@ function thing(gridx, gridy, type, text) {
points = GOATPOINTS;
game.progress("goats", 1);
}
- score += points;
- game.progress("points", points);
- // add animation
- things.push(new thing(this.gridx, this.gridy, "text", "+" + points));
+ points *= multiplier;
+
+ if (points > 0) {
+ score += points;
+ game.progress("points", points);
+
+ // add animation
+ things.push(new thing(this.gridx, this.gridy, "text", "+" + points));
+ }
}
@@ -3144,12 +3526,12 @@ function thing(gridx, gridy, type, text) {
var desc = "";
if (this.type == "cat") {
if (isadjacenttotype(this, "llama")) {
- if (this.eaten == true) {
+ if (this.issleepy() == true) {
desc = "scared sleepy cat";
} else {
desc = "scared cat";
}
- } else if (this.eaten == true) {
+ } else if (this.issleepy() == true) {
desc = "sleepy cat";
} else {
desc = "cat";
@@ -3187,17 +3569,14 @@ function thing(gridx, gridy, type, text) {
if (this.type == "text") {
ctx.textAlign = "center";
ctx.textBaseline = "middle";
- shadowtext(ctx, this.name, TEXTSIZE, this.color, BOARDX + this.x,BOARDY + this.y);
+ shadowtext(ctx, this.name, this.size, this.color, BOARDX + this.x,BOARDY + this.y);
} else {
if (this.type == "cat") {
var myimage;
- if (this.state == "exploding") {
- }
-
if (isadjacenttotype(this, "llama")) {
myimage = image['catscared'];
- } else if (this.eaten == true) {
+ } else if (this.issleepy() == true) {
myimage = image['catfull'];
} else {
myimage = image['cat'];
@@ -3208,6 +3587,13 @@ function thing(gridx, gridy, type, text) {
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 {
+ console.log("ERROR - no image for type " + this.type);
+ console.log(this);
}
howbig = this.size;
myx = this.x;
@@ -3365,6 +3751,7 @@ function thing(gridx, gridy, type, text) {
this.isanimating = function() {
if (this.type == "text") return true;
if (this.state == "explode") return true;
+ if (this.state == "shrink") return true;
if (this.state == "parade") return true;
return false;
}
@@ -3375,6 +3762,12 @@ function thing(gridx, gridy, type, text) {
this.state = "explode";
}
+ this.startshrink = function() {
+ this.expcount=1;
+ this.expmax=SHRINKTICKS;
+ this.state = "shrink";
+ }
+
this.startparade = function() {
var i,startidx=-1;
// find our position in the current path
@@ -3396,14 +3789,19 @@ function thing(gridx, gridy, type, text) {
nextidx = i+1;
if (nextidx >= curpath.length) {
var dir;
- // we're at the end. move off the screen in the direction of the path.
+ if (pathdoor != undefined) {
+ // we're at a door. vanish.
+ this.pushpath(-1, -1);
+ } else {
+ // we're at the end. move off the screen in the direction of the path.
- // find dir from previous to us...
- // don't worry about checking for being the first element cause
- // parades can't be 1 in length;
- dir = getdir(curpath[i-1],curpath[i]);
- this.pushpath(curpath[i].x + (DIRXMOD[dir]*GRIDSIZE*GRIDW),
- curpath[i].y + (DIRYMOD[dir]*GRIDSIZE*GRIDH));
+ // find dir from previous to us...
+ // don't worry about checking for being the first element cause
+ // parades can't be 1 in length;
+ dir = getdir(curpath[i-1],curpath[i]);
+ this.pushpath(curpath[i].x + (DIRXMOD[dir]*GRIDSIZE*GRIDW),
+ curpath[i].y + (DIRYMOD[dir]*GRIDSIZE*GRIDH));
+ }
} else {
this.pushpath(curpath[nextidx].x, curpath[nextidx].y);
}
@@ -3453,42 +3851,67 @@ function thing(gridx, gridy, type, text) {
this.y = (this.gridy * GRIDSIZE) + (GRIDSIZE/2) - (this.size/2);
}
- } else if (this.state == "parade") {
+ } else if (this.state == "shrink") {
+ game.dirty = true; // need to redraw
+ this.expcount++;
+ if (this.expcount >= this.expmax) {
+ this.kill();
+ } else {
+ // get smaller
+ this.size -= SHRINKLOSE;
+
+ if (this.size < 1) this.size == 1;
+
+ // adjust x/y
+ this.x = (this.gridx * GRIDSIZE) + (GRIDSIZE/2) - (this.size/2);
+ this.y = (this.gridy * GRIDSIZE) + (GRIDSIZE/2) - (this.size/2);
+ }
+ } else if ((this.state == "parade") || (this.state == "swapping")) {
// move towards next cell in path
var nextx = this.path[0].x;
var nexty = this.path[0].y;
var xdone = 0, ydone = 0;
game.dirty = true; // need to redraw
-
- if (this.x < nextx) {
- this.x += this.pathspeed;
- if (this.x > nextx) xdone = true;
- } else if (this.x > nextx) {
- this.x -= this.pathspeed;
- if (this.x < nextx) xdone = true;
+
+ // special case: door.
+ if ((nextx == -1) && (nexty == -1)) {
+ this.path = [];
+ this.startshrink();
} else {
- xdone = true;
- }
+ if (this.x < nextx) {
+ this.x += this.pathspeed;
+ if (this.x > nextx) xdone = true;
+ } else if (this.x > nextx) {
+ this.x -= this.pathspeed;
+ if (this.x < nextx) xdone = true;
+ } else {
+ xdone = true;
+ }
- if (this.y < nexty) {
- this.y += this.pathspeed;
- if (this.y > nexty) ydone = true;
- } else if (this.y > nexty) {
- this.y -= this.pathspeed;
- if (this.y < nexty) ydone = true;
- } else {
- ydone = true;
- }
+ if (this.y < nexty) {
+ this.y += this.pathspeed;
+ if (this.y > nexty) ydone = true;
+ } else if (this.y > nexty) {
+ this.y -= this.pathspeed;
+ if (this.y < nexty) ydone = true;
+ } else {
+ ydone = true;
+ }
- this.calcgridxy();
+ this.calcgridxy();
- // at destination?
- if (xdone && ydone) {
- this.poppath();
- // path finished?
- if (this.path == undefined || this.path.length == 0) {
- this.kill();
+ // at destination?
+ if (xdone && ydone) {
+ this.poppath();
+ // path finished?
+ if (this.path == undefined || this.path.length == 0) {
+ if (this.state == "catparade" ){
+ this.kill();
+ } else {
+ this.state = "stop";
+ }
+ }
}
}
} else {
@@ -3496,7 +3919,7 @@ function thing(gridx, gridy, type, text) {
if ((this.gridy >= GRIDH-1)) {
atbottom = true;
}
- if (!atbottom && !this.getstoppedbelowthing()) {
+ if (!atbottom && !this.getstoppedbelowthing() && this.canfall()) {
game.dirty = true; // need to redraw
// accelerate
this.yspeed += GRAVITY;
@@ -3603,7 +4026,14 @@ function mainloop() {
// check for game over and level over
if (game.state == "running") {
if (!thingsmoving()) {
- if (levelfinished()) {
+ var i;
+ if (pathdoor != undefined) {
+ // still a path door needing to be closed/destroyed?
+ pathdoor.givepoints();
+ pathdoor.addabove();
+ pathdoor.startshrink();
+ pathdoor = null;
+ } else if (levelfinished()) {
// record score
if (score > playerdata.levscore[curlevel]) {
playerdata.setlevscore(curlevel, score);
@@ -3612,7 +4042,37 @@ function mainloop() {
game.setstate("levelcomplete");
} else if (!anyvalidmoves()) {
game.setstate("gameover");
+ }
+ // mark things as not new
+ for (i = 0; i < things.length; i += 1) {
+ if (things[i].gridy >= 0) things[i].isnew = false;
}
+ // suns move down once
+ 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)) {
+ // at bottom - disappear
+ things[i].addabove();
+ things[i].startexplode();
+ game.progress("sun cycles", 1);
+ } else {
+ var thingbelow;
+ // move down
+ 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);
+ thingbelow.state = "swapping";
+ }
+ }
+ }
+ }
+
}
}
}
diff --git a/todo b/todo
index ea2b265..3fdbf9c 100644
--- a/todo
+++ b/todo
@@ -30,31 +30,37 @@ phone fixes as per http://www.html5rocks.com/en/mobile/touch/
https://www.smashingmagazine.com/2012/10/design-your-own-mobile-game/
-*restrict catparades on level 1
-*make help text for llamas come later
- *(keep orig help around for reference)
- *lv1 help: just how to eat cheese
- *lv2 help: just how to make cat parades
- *lv3 help: llamas scaring cats, parades can have one llama
- *lv4 help: (preview of features)
-*Level selection screen
+*make forcethings actually work
-*Store level progress and hiscores using localstorage
+replace points goal with 'survive x turns'
+
+*doors -
+*sunlight
+* - makes nearby cats sleepy
+* - swaps with thing below each turn.
+* - then disappears off the bottom
+
+parademovement bounces up down!
+ slow down parades to test.
-*goats
-* cats and goats can gang up on on llamas.
-* parades with a goat can have multiple llamas
-* goats can't start parades (only cats)
-* 50 points
-*goat help text.
-*level select screen needs "back to title"
-*mechanism to force at least one of a given thing type on a level.
-*better level complete animation - zoom in random cat picture.
-*only redraw screen if dirty!
-*switch to "star" system for unlocking levels
-*fix bug when calculating whether there are any valid moves left
-*fix bug in random thing selection
+still bugs in getarndomtype() ?
+
+bug with 2 suns above each other
+
+special things - 5% chance of any
+{
+
+ white cat -
+ move cat on to it to FIGHT.
+ destroy 9 in a block around.
+ pow pow cloud.
+
+
+ doona - hide under it in the cold ?
+
+ mouse toy - match 3 to explode everything ?
+}
more goals:
form x parades of length y
@@ -68,20 +74,6 @@ sounds:
-
-doors -
- appear on the EDGE of the map ?
- PARADE INTO DOOR = triple points (and door vanishes)
-
-
-sunlight - makes nerby cats sleepy
-
-doona - hide under it in the cold ?
-
-mouse toy - match 3 to explode everything ?
-
-
-
make path part of game object
make things part of game object