*random levels.
*bugfix: cat-in-boat to goat should okay *when forcing an goal object because we have none, make the chance higher based on how many things we're dropping. *add more win images * make win images sequential rather than random.
421
cat.html
|
@ -200,7 +200,7 @@ var DIAGDIRXMOD = [ 0, 1, 1, 1, 0, -1, -1, -1 ];
|
|||
var DIAGDIRYMOD = [ -1, -1, 0, 1, 1, 1, 0, -1 ];
|
||||
var DIAGDIRNAME = [ "n", "ne", "e", "se", "s", "sw", "w", "nw"];
|
||||
|
||||
var NUMWINIMAGES = 12;
|
||||
var NUMWINIMAGES = 26;
|
||||
var WINIMGZOOMSPEED = 0.1;
|
||||
|
||||
var SCREENW = 480;
|
||||
|
@ -228,6 +228,8 @@ var TEXTSIZETOTSTARS = 16; // in points
|
|||
var TEXTSIZELEVSCORE = 8; // in points
|
||||
var TEXTSIZELEVSTARS = 10; // in points
|
||||
|
||||
var TEXTSIZELEVSCROLL = 22; // in points
|
||||
|
||||
var HELPLINEWIDTH=4;
|
||||
var HELPARROWSIZE=15;
|
||||
var HELPTITLESIZE = 18;
|
||||
|
@ -599,11 +601,11 @@ function isvalidpath(mypath) {
|
|||
nextone.type == "box" && nextone.boxfull) {
|
||||
// full boxes can parade on to other full boxes
|
||||
} else if ((thisone.type == "goat") && (ccount == 0) &&
|
||||
((nextone.type == "cat" && catcolmatches(nextone, firstone)) || nextone.type == "llama" || nextone.type == "goat")) {
|
||||
// goat can go to llama or correctly coloured cat
|
||||
((nextone.type == "cat" && catcolmatches(nextone, firstone)) || nextone.type == "llama" || nextone.type == "goat") || (nextone.type == "box" && nextone.boxfull == true)) {
|
||||
// goat can go to llama or correctly coloured cat or cat-in-box
|
||||
// ok
|
||||
} else if ((nextone.type == "door") && (count >= PARADELENGTH) && (fcount == 0) && (ccount == 0) && (count >= 3) &&
|
||||
(thisone.type == "goat" || thisone.type == "cat" || thisone.type == "llama")) {
|
||||
(thisone.type == "goat" || thisone.type == "cat" || thisone.type == "llama" || (thisone.type == "box" && thisone.boxfull == true))) {
|
||||
// completed parades can extend into doors
|
||||
} else if ((thisone.type == "cat") && nextone.type == "llama" && (ccount == 0)) {
|
||||
// no parades on level 1
|
||||
|
@ -1212,16 +1214,35 @@ var game = {
|
|||
frameNo: 0,
|
||||
turnsleft: 0,
|
||||
|
||||
levseloff: 0,
|
||||
|
||||
rng: null,
|
||||
|
||||
goatdir: 1,
|
||||
goatx: 0,
|
||||
goaty: 0,
|
||||
|
||||
goalbooster: 0, // extra chance of a goal object appearing
|
||||
|
||||
turnsbarpct: 0,
|
||||
|
||||
screenflash: 0,
|
||||
|
||||
newestlevel: null,
|
||||
|
||||
canvas: null,
|
||||
|
||||
setrndseed : function(seed) {
|
||||
if (this.rng != undefined) {
|
||||
delete this.rng;
|
||||
}
|
||||
this.rng = new RNG(seed);
|
||||
},
|
||||
|
||||
seedrnd : function(min, max) {
|
||||
return this.rng.rndrange(min, max);
|
||||
},
|
||||
|
||||
addfireworks : function() {
|
||||
var delay = 0;
|
||||
for (i = 0; i < FIREWORKCOUNT; i++) {
|
||||
|
@ -1417,6 +1438,8 @@ var game = {
|
|||
if (game.turnsleft < 0) game.turnsleft = 0;
|
||||
|
||||
game.dirty = true;
|
||||
|
||||
game.goalbooster = 0;
|
||||
},
|
||||
|
||||
resize : function() {
|
||||
|
@ -1451,6 +1474,7 @@ var game = {
|
|||
score = 0;
|
||||
globmulti = 0;
|
||||
this.frameNo = 0;
|
||||
this.goalbooster = 0;
|
||||
},
|
||||
|
||||
initlevelvars : function() {
|
||||
|
@ -1485,17 +1509,24 @@ var game = {
|
|||
// 5 - 14 = 1 bag
|
||||
// 15 - 24 = 2 bags
|
||||
// 25 - 34 = 3 bags
|
||||
nbags = Math.floor((curlevel+5) / 10);
|
||||
nbags = game.getmaxbags(curlevel);
|
||||
|
||||
for (i = 0; i < nbags; i++) {
|
||||
this.addlevelbag(curlevel);
|
||||
}
|
||||
},
|
||||
|
||||
getmaxbags : function(lev) {
|
||||
var max;
|
||||
max = Math.floor((lev+5) / 10)
|
||||
if (max > 4) max = 4;
|
||||
return max;
|
||||
},
|
||||
|
||||
// x1, x2, y2, x3, y3....
|
||||
addlevelbricks : function () {
|
||||
var lev,newbrick,i;
|
||||
lev = this.levels.length - 1;
|
||||
lev = this.newestlevel;
|
||||
for (i = 0 ; i < arguments.length; i += 2) {
|
||||
newbrick = new Object();
|
||||
newbrick.gridx = arguments[i];
|
||||
|
@ -1523,6 +1554,13 @@ var game = {
|
|||
|
||||
addlevel : function (lev, hashelp) {
|
||||
var mylevel;
|
||||
var plev;
|
||||
|
||||
// find previous level
|
||||
for (plev = lev-1; plev >= 0; plev--) {
|
||||
if (this.levels[plev] != undefined) break;
|
||||
}
|
||||
|
||||
mylevel = new Object();
|
||||
mylevel.hashelp = hashelp;
|
||||
mylevel.goals = new Array();
|
||||
|
@ -1531,6 +1569,7 @@ var game = {
|
|||
mylevel.maxturns = lev + 4; // default
|
||||
mylevel.bags = [];
|
||||
mylevel.bricks = [];
|
||||
mylevel.random = false;
|
||||
|
||||
if (lev == 1) {
|
||||
mylevel.gridsize = DEF_GRIDSIZE;
|
||||
|
@ -1541,20 +1580,20 @@ var game = {
|
|||
mylevel.catcols = 1;
|
||||
} else {
|
||||
// default to size of previous one
|
||||
mylevel.gridsize = this.levels[lev-1].gridsize;
|
||||
mylevel.thingsize = this.levels[lev-1].thingsize;
|
||||
mylevel.gridw = this.levels[lev-1].gridw;
|
||||
mylevel.gridh = this.levels[lev-1].gridh;
|
||||
mylevel.boardx = this.levels[lev-1].boardx;
|
||||
mylevel.gridsize = this.levels[plev].gridsize;
|
||||
mylevel.thingsize = this.levels[plev].thingsize;
|
||||
mylevel.gridw = this.levels[plev].gridw;
|
||||
mylevel.gridh = this.levels[plev].gridh;
|
||||
mylevel.boardx = this.levels[plev].boardx;
|
||||
// default to # cat colours from previous one
|
||||
mylevel.catcols = this.levels[lev-1].catcols;
|
||||
mylevel.catcols = this.levels[plev].catcols;
|
||||
}
|
||||
|
||||
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]);
|
||||
for (i = 0; i < this.levels[plev].allowedthings.length; i++) {
|
||||
mylevel.allowedthings.push(this.levels[plev].allowedthings[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1562,9 +1601,84 @@ var game = {
|
|||
|
||||
playerdata.levscore[lev] = 0;
|
||||
|
||||
this.newestlevel = lev;
|
||||
},
|
||||
|
||||
addlevelgridwid: function (lev, newwid) {
|
||||
levhasgoal : function(lev, gtype) {
|
||||
var i;
|
||||
for (i = 0; i < game.levels[lev].goals.length; i++) {
|
||||
if (game.levels[lev].goals[i].type == gtype) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
genrandomlevel : function (lev) {
|
||||
var ngoals,i,pctleft;
|
||||
|
||||
// set random seed based on level
|
||||
game.setrndseed(lev+50);
|
||||
|
||||
ngoals = game.seedrnd(2,3);
|
||||
|
||||
// first create the level
|
||||
if (game.levels[lev] == undefined) {
|
||||
game.addlevel(lev, false);
|
||||
}
|
||||
|
||||
// generate goals
|
||||
pctleft = 100;
|
||||
for (i = 0; i < ngoals; i++) {
|
||||
var allgoals = [],goal,goalpct;
|
||||
// make list of all possible goals
|
||||
for (goal in GOALVERB) {
|
||||
if (!game.levhasgoal(lev, goal) && (goal != "turn")) {
|
||||
allgoals.push(goal);
|
||||
}
|
||||
}
|
||||
|
||||
// pick a random goal
|
||||
goal = allgoals[game.seedrnd(0,allgoals.length-1)];
|
||||
|
||||
// generate a percentage of max count for this goal
|
||||
// this will be replaced with an actual number in a second.
|
||||
if (i == ngoals-1) {
|
||||
// last one
|
||||
goalpct = pctleft;
|
||||
} else {
|
||||
goalpct = game.seedrnd(pctleft/4,pctleft/2);
|
||||
}
|
||||
|
||||
game.addlevelgoals(goal, goalpct);
|
||||
}
|
||||
|
||||
for (i = 0; i < ngoals; i++) {
|
||||
var max,maxcount;
|
||||
// turn goal percentages into actual numbers
|
||||
max = game.getgoalmax(lev, game.levels[lev].goals[i].type);
|
||||
maxcount = Math.floor((game.levels[lev].goals[i].count / 100) * max)
|
||||
|
||||
if (maxcount < 1) maxcount = 1;
|
||||
|
||||
game.levels[lev].goals[i].count = maxcount;
|
||||
|
||||
// add forced things based on goals
|
||||
switch (game.levels[lev].goals[i].type) {
|
||||
case "brick":
|
||||
game.addlevelforcethings(game.levels[lev].goals[i].type, maxcount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate star point cutoffs, max turns, etc
|
||||
game.calclevparams(lev);
|
||||
|
||||
game.levels[lev].random = true;
|
||||
|
||||
},
|
||||
|
||||
addlevelgridwid : function (lev, newwid) {
|
||||
var ratio;
|
||||
|
||||
ratio = newwid / DEF_GRIDW;
|
||||
|
@ -1581,7 +1695,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
// thingtype pct
|
||||
addlevelthings: function () {
|
||||
var i,idx,lev;
|
||||
lev = this.levels.length - 1;
|
||||
lev = this.newestlevel;
|
||||
for (i = 0 ; i < arguments.length; i += 2) {
|
||||
idx = this.levels[lev].thinglist.push(new Object()) - 1;
|
||||
this.levels[lev].thinglist[idx].type = arguments[i];
|
||||
|
@ -1592,7 +1706,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
// thingtype howmany
|
||||
addlevelforcethings: function () {
|
||||
var i,idx,lev;
|
||||
lev = this.levels.length - 1;
|
||||
lev = this.newestlevel;
|
||||
for (i = 0 ; i < arguments.length; i += 2) {
|
||||
idx = this.levels[lev].forcelist.push(new Object()) - 1;
|
||||
this.levels[lev].forcelist[idx].type = arguments[i];
|
||||
|
@ -1610,7 +1724,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
// thing1, thing2, etc
|
||||
addlevelallowedthings : function () {
|
||||
var i,lev;
|
||||
lev = this.levels.length - 1;
|
||||
lev = this.newestlevel;
|
||||
for (i = 0 ; i < arguments.length; i++) {
|
||||
this.levels[lev].allowedthings.push(arguments[i]);
|
||||
}
|
||||
|
@ -1625,7 +1739,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
// goal1type goal1count goal2type goal2count etc...
|
||||
addlevelgoals : function () {
|
||||
var i,idx,lev;
|
||||
lev = this.levels.length - 1;
|
||||
lev = this.newestlevel;
|
||||
|
||||
for (i = 0 ; i < arguments.length; i += 2) {
|
||||
idx = this.levels[lev].goals.push(new Object()) - 1;
|
||||
|
@ -1707,6 +1821,42 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
this.levels[lev].starpoints[2] = p3;
|
||||
},
|
||||
|
||||
getgoalmax : function (lev, gtype) {
|
||||
var max = -1;
|
||||
switch (gtype) {
|
||||
case "food":
|
||||
max = lev * 1.2;
|
||||
break;
|
||||
case "llama":
|
||||
max = lev * 0.5;
|
||||
break;
|
||||
case "cat":
|
||||
max = lev * 1.5;
|
||||
break;
|
||||
case "goat":
|
||||
max = lev * 0.25;
|
||||
break;
|
||||
case "brick":
|
||||
max = lev * 0.1;
|
||||
break;
|
||||
case "door":
|
||||
max = lev * 0.1;
|
||||
break;
|
||||
case "sun":
|
||||
max = lev * 0.6;
|
||||
break;
|
||||
case "bag":
|
||||
nbags = game.getmaxbags(lev);
|
||||
break;
|
||||
default: // should never happen
|
||||
max = lev * 0.2;
|
||||
break;
|
||||
}
|
||||
max = Math.floor(max);
|
||||
if (max < 1) max = 1;
|
||||
return max;
|
||||
},
|
||||
|
||||
calclevparams : function( lev ) {
|
||||
var i,num;
|
||||
var min = 0,pointsgoal = false;
|
||||
|
@ -1743,14 +1893,13 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
if (!game.isbanned(curlevel, "door")) {
|
||||
num *= 1.5;
|
||||
}
|
||||
|
||||
min += num;
|
||||
break;
|
||||
case "door":
|
||||
// double the value of a minimum-score parade
|
||||
min += Math.min(CATPOINTS, SLEEPYCATPOINTS) * 3 * 2 * this.levels[lev].goals[i].count;
|
||||
break;
|
||||
turnsreq += this.levels[lev].goals[i].count * 1;
|
||||
break;
|
||||
case "sun":
|
||||
min += SLEEPYCATPOINTS*5 * this.levels[lev].goals[i].count;
|
||||
turnsreq += this.levels[lev].gridh;
|
||||
|
@ -1798,10 +1947,8 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
// must be an integer
|
||||
this.levels[lev].maxturns = Math.floor(this.levels[lev].maxturns);
|
||||
|
||||
/*
|
||||
// calc stars to unlock
|
||||
//extrastars = Math.floor(lev / 5);
|
||||
//this.levels[lev].starsrequired = (lev-1) + extrastars;
|
||||
|
||||
// must use 'lev-1' so that level 1 requires no stars.
|
||||
// 1.2 * level num
|
||||
if (lev < 5) {
|
||||
|
@ -1809,9 +1956,23 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
} else {
|
||||
this.levels[lev].starsrequired = Math.floor(1.5 * (lev-1));
|
||||
}
|
||||
*/
|
||||
|
||||
},
|
||||
|
||||
getstarsrequired : function (lev) {
|
||||
var req;
|
||||
// calc stars to unlock
|
||||
// must use 'lev-1' so that level 1 requires no stars.
|
||||
// 1.2 * level num
|
||||
if (lev < 5) {
|
||||
req = Math.floor(1.2 * (lev-1));
|
||||
} else {
|
||||
req = Math.floor(1.5 * (lev-1));
|
||||
}
|
||||
return req;
|
||||
},
|
||||
|
||||
initlevels : function ( ) {
|
||||
var mylevel,i,n;
|
||||
|
||||
|
@ -2650,7 +2811,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
},
|
||||
|
||||
levellocked : function (lev) {
|
||||
if (playerdata.totstars < game.levels[lev].starsrequired) return true;
|
||||
if (playerdata.totstars < game.getstarsrequired(lev)) return true;
|
||||
|
||||
return false;
|
||||
},
|
||||
|
@ -4916,6 +5077,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
var gridcol = "#000000";
|
||||
var crosscol = "#bbbbbb";
|
||||
var textcol = "#dddd00";
|
||||
var scrollcol = "#dddd00";
|
||||
var titlecol = "#00aaee";
|
||||
var scorecol = "#00dd00";
|
||||
var starcol = "#dddd00";
|
||||
|
@ -4950,20 +5112,81 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
|
||||
gridalpha = wipe.getval(1.0, "up", "down", 1.0);
|
||||
|
||||
|
||||
levnum = 1 + game.levseloff;
|
||||
|
||||
// grid
|
||||
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;
|
||||
var randomlev = false;
|
||||
|
||||
if (this.levelexists(levnum)) {
|
||||
var nextsize = GRIDSIZE * 0.75;
|
||||
|
||||
// "prev" ?
|
||||
if (x == 0 && y == 0 && game.levseloff > 0) {
|
||||
/*
|
||||
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");
|
||||
gridgrad.addColorStop(1, gridblack);
|
||||
ctx.fillStyle = gridgrad;
|
||||
ctx.fillRect(LEVSEL_X + x, LEVSEL_Y + y, GRIDSIZE-1, GRIDSIZE-1);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
shadowtext(ctx, "<<", TEXTSIZELEVSCROLL, scrollcol,
|
||||
LEVSEL_X + x + GRIDSIZE/2, LEVSEL_Y + y + GRIDSIZE/2);
|
||||
*/
|
||||
ctx.drawImage(image['prevlev'],
|
||||
LEVSEL_X + x + GRIDSIZE/2 - nextsize/2, LEVSEL_Y + y + GRIDSIZE/2 - nextsize/2,
|
||||
nextsize,nextsize);
|
||||
|
||||
continue;
|
||||
} else if (y >= (LEVSELGRIDH*GRIDSIZE - GRIDSIZE) && x >= (LEVSELGRIDW*GRIDSIZE - GRIDSIZE)) {
|
||||
// "next" ?
|
||||
/*
|
||||
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");
|
||||
gridgrad.addColorStop(1, gridblack);
|
||||
ctx.fillStyle = gridgrad;
|
||||
ctx.fillRect(LEVSEL_X + x, LEVSEL_Y + y, GRIDSIZE-1, GRIDSIZE-1);
|
||||
ctx.stroke();
|
||||
*/
|
||||
|
||||
ctx.drawImage(image['nextlev'],
|
||||
LEVSEL_X + x + GRIDSIZE/2 - nextsize/2, LEVSEL_Y + y + GRIDSIZE/2 - nextsize/2,
|
||||
nextsize,nextsize);
|
||||
/*
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
shadowtext(ctx, ">>", TEXTSIZELEVSCROLL, scrollcol,
|
||||
LEVSEL_X + x + GRIDSIZE/2, LEVSEL_Y + y + GRIDSIZE/2);
|
||||
*/
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// create it if required.
|
||||
if (!game.levelexists(levnum)) {
|
||||
game.genrandomlevel(levnum);
|
||||
}
|
||||
randomlev = game.levels[levnum].random;
|
||||
|
||||
//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)) {
|
||||
|
||||
if ( this.levellocked(levnum)) {
|
||||
gridgrad.addColorStop(0, "#eeeeee");
|
||||
} else {
|
||||
|
@ -4976,13 +5199,6 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
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;
|
||||
|
@ -4990,6 +5206,16 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
var lockx = LEVSEL_X + x + GRIDSIZE/2 - lockw/2;
|
||||
var locky = LEVSEL_Y + y + TEXTSIZELEVSELECT*1.5;
|
||||
|
||||
// show level num
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
shadowtext(ctx, levnum, TEXTSIZELEVSELECT,
|
||||
//randomlev ? "red" : textcol,
|
||||
textcol,
|
||||
LEVSEL_X + x + GRIDSIZE/2,levy);
|
||||
|
||||
|
||||
|
||||
// locked
|
||||
ctx.drawImage(image['lock'], lockx, locky, lockw, lockh);
|
||||
|
||||
|
@ -5012,7 +5238,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
ctx.textBaseline = "top";
|
||||
|
||||
|
||||
shadowtext(ctx, this.levels[levnum].starsrequired,
|
||||
shadowtext(ctx, game.getstarsrequired(levnum),
|
||||
TEXTSIZELEVSTARS, "#cccccc",
|
||||
starreqx, starreqy);
|
||||
|
||||
|
@ -5025,12 +5251,15 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
// show level num
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
shadowtext(ctx, levnum, TEXTSIZELEVSELECT, textcol,
|
||||
shadowtext(ctx, levnum, TEXTSIZELEVSELECT,
|
||||
//randomlev ? "red" : textcol,
|
||||
textcol,
|
||||
LEVSEL_X + x + GRIDSIZE/2,levy);
|
||||
|
||||
// show hiscore
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
|
||||
// get player hiscore
|
||||
hiscore = playerdata.getlevscore(levnum);
|
||||
|
||||
|
@ -5054,21 +5283,22 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
|
||||
// show hiscore
|
||||
hiscore = playerdata.getlevscore(levnum);
|
||||
if (hiscore != undefined) {
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "bottom";
|
||||
if (hiscore == 0) {
|
||||
shadowtext(ctx, "NEW!", TEXTSIZELEVSCORE, "#ee44ee",
|
||||
LEVSEL_X + x + GRIDSIZE/2,scorey);
|
||||
} else {
|
||||
hiscore = addcommas(hiscore) + "pts";
|
||||
shadowtext(ctx, hiscore, TEXTSIZELEVSCORE, scorecol,
|
||||
LEVSEL_X + x + GRIDSIZE/2,scorey);
|
||||
}
|
||||
if (hiscore == undefined) hiscore = 0;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "bottom";
|
||||
if (hiscore == 0) {
|
||||
shadowtext(ctx, "NEW!", TEXTSIZELEVSCORE, "#ee44ee",
|
||||
LEVSEL_X + x + GRIDSIZE/2,scorey);
|
||||
} else {
|
||||
hiscore = addcommas(hiscore) + "pts";
|
||||
shadowtext(ctx, hiscore, TEXTSIZELEVSCORE, scorecol,
|
||||
LEVSEL_X + x + GRIDSIZE/2,scorey);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//} else {
|
||||
// level doesn't exist
|
||||
|
||||
/*
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 3;
|
||||
ctx.strokeStyle = gridcol;
|
||||
|
@ -5081,7 +5311,8 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
|
||||
// cross it out
|
||||
drawcross(ctx,LEVSEL_X + x, LEVSEL_Y + y, LEVSEL_X + x + GRIDSIZE-1, BOARDY + y + GRIDSIZE-1, crosscol, 3);
|
||||
}
|
||||
*/
|
||||
//}
|
||||
|
||||
// outline square
|
||||
ctx.beginPath();
|
||||
|
@ -5433,7 +5664,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
// find where you clicked
|
||||
if ((realx >= levsel_contx) && (realx <= levsel_contx + levsel_contw) &&
|
||||
(realy >= levsel_conty) && (realy <= levsel_conty + levsel_conth)) {
|
||||
//game.setstate("title");
|
||||
// back to title screen
|
||||
wipe.start("title", "out", 15);
|
||||
} else {
|
||||
var gridx,gridy,levsel;
|
||||
|
@ -5443,13 +5674,26 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
//gridx = Math.floor((realx - BOARDX) / GRIDSIZE);
|
||||
//gridy = Math.floor((realy - BOARDY) / GRIDSIZE);
|
||||
|
||||
levsel = (gridy*LEVSELGRIDW) + gridx + 1;
|
||||
if ((gridx == LEVSELGRIDW-1) && (gridy == LEVSELGRIDH - 1)) {
|
||||
// "next"
|
||||
game.levseloff += ((LEVSELGRIDW*LEVSELGRIDH)-1);
|
||||
} else if (game.levseloff > 0 && gridx == 0 && gridy == 0) {
|
||||
// "next"
|
||||
game.levseloff -= ((LEVSELGRIDW*LEVSELGRIDH)-1);
|
||||
if (game.levseloff < 0) game.levseloff = 0;
|
||||
|
||||
if (game.levelexists(levsel) && !game.levellocked(levsel)) {
|
||||
curlevel = levsel;
|
||||
} else {
|
||||
levsel = game.levseloff + (gridy*LEVSELGRIDW) + gridx + 1;
|
||||
if (game.levseloff > 0) levsel--;
|
||||
|
||||
game.initgamevars();
|
||||
game.helporstartlev();
|
||||
//if (game.levelexists(levsel) && !game.levellocked(levsel)) {
|
||||
if (!game.levellocked(levsel)) {
|
||||
|
||||
curlevel = levsel;
|
||||
|
||||
game.initgamevars();
|
||||
game.helporstartlev();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (game.state == "help") {
|
||||
|
@ -5605,7 +5849,8 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
// get a new cat picture for if we win
|
||||
if (winimg != undefined) delete winimg;
|
||||
winimg = new Image();
|
||||
var n = rnd(NUMWINIMAGES);
|
||||
//var n = rnd(NUMWINIMAGES);
|
||||
var n = curlevel % NUMWINIMAGES;
|
||||
winimg.src = "images/win" + n + ".png";
|
||||
this.winimgsize = 0.1;
|
||||
|
||||
|
@ -5646,6 +5891,7 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
'starfull','starempty', 'stargrey', 'curtain','curtainshred', 'curtainfall',
|
||||
'door', 'sunlight', 'toad', 'whitecat', // special things
|
||||
'box', 'boxfront', 'boxback',
|
||||
'nextlev','prevlev',
|
||||
'brick', // obstacles
|
||||
'bag', 'bagpop', 'fez', 'pow', 'brickpop', // effects
|
||||
'tissues', 'shears', 'magiccarpet' ];
|
||||
|
@ -5875,12 +6121,41 @@ console.log("lev " + lev + " newwid " + newwid + " ratio " + ratio);
|
|||
},
|
||||
}
|
||||
|
||||
// Seeded random numbers, from http://stackoverflow.com/questions/424292/seedable-javascript-random-number-generator
|
||||
function RNG(seed) {
|
||||
// LCG using GCC's constants
|
||||
this.m = 0x80000000; // 2**31;
|
||||
this.a = 1103515245;
|
||||
this.c = 12345;
|
||||
|
||||
this.state = seed ? seed : Math.floor(Math.random() * (this.m-1));
|
||||
}
|
||||
RNG.prototype.rndint = function() {
|
||||
this.state = (this.a * this.state + this.c) % this.m;
|
||||
return this.state;
|
||||
}
|
||||
RNG.prototype.rndfloat = function() {
|
||||
// returns in range [0,1]
|
||||
return this.rndint() / (this.m - 1);
|
||||
}
|
||||
RNG.prototype.rndrange = function(start, end) {
|
||||
// returns in range [start, end): including start, excluding end
|
||||
// can't modulu nextInt because of weak randomness in lower bits
|
||||
var rangeSize = end - start;
|
||||
var randomUnder1 = this.rndint() / this.m;
|
||||
return start + Math.floor(randomUnder1 * rangeSize);
|
||||
}
|
||||
RNG.prototype.rndchoice = function(array) {
|
||||
return array[this.rndrange(0, array.length)];
|
||||
}
|
||||
|
||||
function getimgsize(srcWidth, srcHeight, maxWidth, maxHeight) {
|
||||
|
||||
var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
|
||||
|
||||
return { width: srcWidth*ratio, height: srcHeight*ratio };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// returns number in range 0 .. num-1
|
||||
function rnd(num) {
|
||||
|
@ -6026,6 +6301,7 @@ function getrandomtype() {
|
|||
var thinglist,maxroll = 0;
|
||||
var speciallist = null;
|
||||
var dodb = false;
|
||||
var goalthings;
|
||||
|
||||
if (curlevel >= game.levels.length) {
|
||||
thinglist = null;
|
||||
|
@ -6060,12 +6336,13 @@ function getrandomtype() {
|
|||
thinglist.push({ type: 'special', pct: 5 } );
|
||||
}
|
||||
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, 'goat')) thinglist.push({ type: 'goat', pct: 12 } );
|
||||
if (!game.isbanned(curlevel, 'llama')) thinglist.push({ type: 'llama', pct: 10 } );
|
||||
if (!game.isbanned(curlevel, 'food')) thinglist.push({ type: 'food', pct: 40 } );
|
||||
if (!game.isbanned(curlevel, 'cat')) thinglist.push({ type: 'cat', pct: 45 } );
|
||||
}
|
||||
|
||||
goalthings = [];
|
||||
|
||||
// increase the chance of something appearing if
|
||||
// a. it's a goal
|
||||
|
@ -6102,11 +6379,15 @@ function getrandomtype() {
|
|||
count = countalivethingsoftype(lookforthing);
|
||||
if (count <= 1) {
|
||||
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 + ")");
|
||||
//thinglist[i].pct *= goalbooster;
|
||||
|
||||
game.goalbooster += 15;
|
||||
if (thinglist[i].pct < game.goalbooster) thinglist[i].pct = game.goalbooster;
|
||||
console.log("extra chance of " + thingtype + "(" + lookforthing + ") - " + game.goalbooster);
|
||||
dodb = true;
|
||||
goalthings.push(thingtype);
|
||||
|
||||
// if the thing in question is 'special',
|
||||
// cheat on the random check later to make sure we
|
||||
|
@ -6149,6 +6430,11 @@ dodb = true;
|
|||
}
|
||||
}
|
||||
|
||||
if (goalthings.indexOf(type)) {
|
||||
console.log("resetting goalbooster");
|
||||
game.goalbooster = 0;
|
||||
}
|
||||
|
||||
if (type == null || type == undefined) {
|
||||
console.log("couldn't find type! roll is " + roll);
|
||||
type = 'cat';
|
||||
|
@ -6488,7 +6774,7 @@ function thing(gridx, gridy, type, text, col) {
|
|||
points = LLAMAPOINTS;
|
||||
//game.progress("llama", 1);
|
||||
} else if (this.type == "box") {
|
||||
points = BOXCATPOINTS;
|
||||
points = CATBOXPOINTS;
|
||||
} else if (this.type == "cat") {
|
||||
if (this.issleepy()) {
|
||||
points = SLEEPYCATPOINTS;
|
||||
|
@ -7569,11 +7855,12 @@ function mainloop() {
|
|||
}
|
||||
// mark things as not new
|
||||
for (i = 0; i < things.length; i += 1) {
|
||||
if (things[i].gridy >= 0) things[i].isnew = false;
|
||||
if ((things[i].gridy >= 0) && !things[i].isanimating()) 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 &&
|
||||
if (things[i].type == "sunlight" &&
|
||||
isonscreen(things[i].gridx, things[i].gridy) && !things[i].isnew &&
|
||||
things[i].state != "swapping" && things[i].counter == 0) {
|
||||
var thingbelow,willdie = false;
|
||||
thingbelow = getgridthing(things[i].gridx, things[i].gridy+1);
|
||||
|
@ -7614,6 +7901,8 @@ function mainloop() {
|
|||
function canmatchthree(what) {
|
||||
if (what.isanimating()) return false; // ignore moving things, though there shouldnt be any anyway
|
||||
|
||||
if (!isonscreen(what.gridx, what.gridy)) return false;
|
||||
|
||||
switch (what.type) {
|
||||
case "llama": return true;
|
||||
}
|
||||
|
@ -7632,8 +7921,8 @@ function matchthreefrom(what, locdb) {
|
|||
var n,gotmatch = false;
|
||||
|
||||
if (locdb == undefined) debug = false;
|
||||
|
||||
if (!canmatchthree(what)) return false;
|
||||
|
||||
if (what.matched) return false; // ignore things already in sets of 3
|
||||
|
||||
for (n = 0; n < MAXDIRS; n++) {
|
||||
|
|
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 298 KiB |
After Width: | Height: | Size: 277 KiB |
After Width: | Height: | Size: 211 KiB |
After Width: | Height: | Size: 265 KiB |
After Width: | Height: | Size: 261 KiB |
After Width: | Height: | Size: 371 KiB |
After Width: | Height: | Size: 258 KiB |
After Width: | Height: | Size: 288 KiB |
After Width: | Height: | Size: 340 KiB |
After Width: | Height: | Size: 282 KiB |
After Width: | Height: | Size: 248 KiB |
After Width: | Height: | Size: 368 KiB |
After Width: | Height: | Size: 246 KiB |
After Width: | Height: | Size: 285 KiB |
68
todo
|
@ -10,53 +10,48 @@ https://www.smashingmagazine.com/2012/10/design-your-own-mobile-game/
|
|||
-------------------
|
||||
|
||||
|
||||
*random levels.
|
||||
*bugfix: cat-in-boat to goat should okay
|
||||
*when forcing an goal object because we have none, make the chance higher based on how many things we're dropping.
|
||||
*add more win images
|
||||
* make win images sequential rather than random.
|
||||
|
||||
tweak random goal numbers
|
||||
|
||||
sometimes add random bricks
|
||||
randoms:
|
||||
add 1-4 bricks
|
||||
quads:
|
||||
pick quad
|
||||
add 1-2 bricks
|
||||
flip to others
|
||||
vert flip
|
||||
pick side
|
||||
add 1-3 bricks
|
||||
flip
|
||||
horz flip
|
||||
pick top/bottom
|
||||
add 1-3 bricks
|
||||
flip
|
||||
|
||||
|
||||
|
||||
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.
|
||||
*attempt to fix bug with multiple things on top of each other
|
||||
*check code for doors falling when off the top of the screen.
|
||||
*check code for adding new objects at top of screen.
|
||||
|
||||
change 'thing' to have a constructor!!
|
||||
then remove dupe hp code
|
||||
|
||||
*change layout of levselect screen
|
||||
|
||||
*points for catbox in parade!
|
||||
|
||||
*make curtain be a kind of 'special'
|
||||
*Boxes are great!
|
||||
*cats enter as part of a chomp, to become a catbox
|
||||
|
||||
|
||||
*catboxes auto-ambush any llama which falls nearby
|
||||
|
||||
*catboxes are anonymous, so they can join parades of any colour
|
||||
*parades starting with a catbox can include any colour cats.
|
||||
|
||||
*catboxes can even chomp food!
|
||||
|
||||
update validmoves check
|
||||
|
||||
|
||||
|
||||
remaining levels.
|
||||
22/23/24 - curtains (shred 2, 4, 6)
|
||||
24/25/26 - boxes
|
||||
26/27/28 - cat toys
|
||||
29/30 - ???
|
||||
|
||||
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()
|
||||
|
||||
|
||||
|
||||
|
@ -71,11 +66,6 @@ more prizes: ???
|
|||
|
||||
arrow/signpost - cat parades bounce off and take out htings in the path
|
||||
|
||||
random levels after 100
|
||||
generate w/h increases (up to a maximum)
|
||||
generate goals
|
||||
generate obstacles
|
||||
use existing maxturns code
|
||||
|
||||
|
||||
---------
|
||||
|
|