added decaying fruit
This commit is contained in:
parent
bf06218815
commit
530260ac54
4 changed files with 62 additions and 4 deletions
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
FIRE_ANIM = $(foreach angle, $(shell seq 0 6 359), build/fire$(angle).png)
|
FIRE_ANIM = $(foreach angle, $(shell seq 0 6 359), build/fire$(angle).png)
|
||||||
PEACH_DECAY_ANIM = $(foreach percent, $(shell seq 100 -1 0), build/peach-decay$(percent).png)
|
PEACH_DECAY_ANIM = $(foreach percent, $(shell seq 99 -1 0), build/peach-decay$(percent).png)
|
||||||
PEACH_RAINBOW_ANIM = $(foreach percent, $(shell seq 100 2 299), build/peach-rainbow$(percent).png)
|
PEACH_RAINBOW_ANIM = $(foreach percent, $(shell seq 100 2 299), build/peach-rainbow$(percent).png)
|
||||||
|
|
||||||
IMAGES = $(foreach name, apple wall, public/assets/$(name)32.png)
|
IMAGES = $(foreach name, apple wall, public/assets/$(name)32.png)
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
[16, 10]
|
[16, 10]
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"superFruitGrow": true
|
"superFruitGrow": true,
|
||||||
|
"decayingFruitGrow": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ const ProgressBar=require('progress');
|
||||||
const assetSpecs=[
|
const assetSpecs=[
|
||||||
{ name: 'fruit', filename: 'apple32.png', type: 'image' },
|
{ name: 'fruit', filename: 'apple32.png', type: 'image' },
|
||||||
{ name: 'superFruit', filename: 'peach-rainbow-anim.png', type: 'image' },
|
{ name: 'superFruit', filename: 'peach-rainbow-anim.png', type: 'image' },
|
||||||
|
{ name: 'decayFruit', filename: 'peach-decay-anim.png', type: 'image' },
|
||||||
{ name: 'wall', filename: 'wall32.png', type: 'image' },
|
{ name: 'wall', filename: 'wall32.png', type: 'image' },
|
||||||
{ name: 'hole', filename: 'hole-ts.png', type: 'image' },
|
{ name: 'hole', filename: 'hole-ts.png', type: 'image' },
|
||||||
{ name: 'fire', filename: 'fire-anim.png', type: 'image' },
|
{ name: 'fire', filename: 'fire-anim.png', type: 'image' },
|
||||||
|
@ -15,7 +16,8 @@ const assetSpecs=[
|
||||||
const tasks=[
|
const tasks=[
|
||||||
{ from: 'hole', type: 'tileset', steps: 3, tiles: ['base', 'ul', 'dr', 'dl', 'ur', 'l', 'r', 'd', 'u'] },
|
{ from: 'hole', type: 'tileset', steps: 3, tiles: ['base', 'ul', 'dr', 'dl', 'ur', 'l', 'r', 'd', 'u'] },
|
||||||
{ from: 'fire', type: 'animation', steps: 6 },
|
{ from: 'fire', type: 'animation', steps: 6 },
|
||||||
{ from: 'superFruit', type: 'animation', steps: 5 }
|
{ from: 'superFruit', type: 'animation', steps: 5 },
|
||||||
|
{ from: 'decayFruit', type: 'animation', steps: 5 }
|
||||||
];
|
];
|
||||||
|
|
||||||
const cvs=document.createElement('canvas');
|
const cvs=document.createElement('canvas');
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const [EMPTY, FOOD, SUPER_FOOD, WALL, FIRE, HOLE, HOLE_S, SNAKE]=Array(7).keys();
|
const [EMPTY, FOOD, SUPER_FOOD, DECAY_FOOD, WALL, FIRE, HOLE, HOLE_S, SNAKE]=Array(255).keys();
|
||||||
|
|
||||||
class SnekGame {
|
class SnekGame {
|
||||||
constructor(settings, canvas, rules) {
|
constructor(settings, canvas, rules) {
|
||||||
|
@ -18,6 +18,7 @@ class SnekGame {
|
||||||
case ' ': return EMPTY;
|
case ' ': return EMPTY;
|
||||||
case 'f': return FOOD;
|
case 'f': return FOOD;
|
||||||
case 'F': return SUPER_FOOD;
|
case 'F': return SUPER_FOOD;
|
||||||
|
case 'd': return DECAY_FOOD;
|
||||||
case 'w': return WALL;
|
case 'w': return WALL;
|
||||||
case 'o': return HOLE;
|
case 'o': return HOLE;
|
||||||
case 'i': return FIRE;
|
case 'i': return FIRE;
|
||||||
|
@ -37,6 +38,15 @@ class SnekGame {
|
||||||
if(c==FOOD) this.fruits.push([x, y]);
|
if(c==FOOD) this.fruits.push([x, y]);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// extract the decaying fruits
|
||||||
|
this.decayFood=[];
|
||||||
|
this.world
|
||||||
|
.forEach((l, x) => l.forEach(
|
||||||
|
(c, y) => {
|
||||||
|
if(c==DECAY_FOOD) this.decaying.push([x, y, 0]);
|
||||||
|
}
|
||||||
|
));
|
||||||
} else { // dimension and objects
|
} else { // dimension and objects
|
||||||
|
|
||||||
// get the dimensions
|
// get the dimensions
|
||||||
|
@ -64,6 +74,14 @@ class SnekGame {
|
||||||
|
|
||||||
// add the super food
|
// add the super food
|
||||||
if(settings.superFood) settings.superFood.forEach(([x, y]) => this.world[x][y]=SUPER_FOOD);
|
if(settings.superFood) settings.superFood.forEach(([x, y]) => this.world[x][y]=SUPER_FOOD);
|
||||||
|
|
||||||
|
// add the decaying food
|
||||||
|
if(settings.decayFood) {
|
||||||
|
settings.decayFood.forEach(([x, y]) => this.world[x][y]=DECAY_FOOD);
|
||||||
|
this.decayFood=settings.decayFood.map(([x, y]) => [x, y, 0]);
|
||||||
|
} else {
|
||||||
|
this.decayFood=[];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the snake to the world
|
// add the snake to the world
|
||||||
|
@ -93,6 +111,7 @@ class SnekGame {
|
||||||
this.rules=Object.assign({
|
this.rules=Object.assign({
|
||||||
fruitRegrow: true,
|
fruitRegrow: true,
|
||||||
superFruitGrow: false,
|
superFruitGrow: false,
|
||||||
|
decayingFruitGrow: false,
|
||||||
speedIncrease: true,
|
speedIncrease: true,
|
||||||
worldWrap: true,
|
worldWrap: true,
|
||||||
winCondition: 'none',
|
winCondition: 'none',
|
||||||
|
@ -151,6 +170,7 @@ class SnekGame {
|
||||||
const hole=assets.get('hole');
|
const hole=assets.get('hole');
|
||||||
const fire=assets.get('fire');
|
const fire=assets.get('fire');
|
||||||
const superFruit=assets.get('superFruit');
|
const superFruit=assets.get('superFruit');
|
||||||
|
const decayFruit=assets.get('decayFruit');
|
||||||
const putTile=(x, y, tile) => this.ctx.drawImage(
|
const putTile=(x, y, tile) => this.ctx.drawImage(
|
||||||
tile,
|
tile,
|
||||||
offsetX+cellSize*x,
|
offsetX+cellSize*x,
|
||||||
|
@ -161,6 +181,9 @@ class SnekGame {
|
||||||
const putTileAnim=(x, y, tile) => putTile(x, y, tile[
|
const putTileAnim=(x, y, tile) => putTile(x, y, tile[
|
||||||
Math.floor(Date.now()/1000*60+x+y)%tile.length
|
Math.floor(Date.now()/1000*60+x+y)%tile.length
|
||||||
]);
|
]);
|
||||||
|
const putTileAnimPercent=(x, y, tile, percent) => putTile(x, y, tile[
|
||||||
|
Math.min(Math.round(percent*tile.length), tile.length-1)
|
||||||
|
]);
|
||||||
const checkAdj=(x, y) => {
|
const checkAdj=(x, y) => {
|
||||||
let adj={};
|
let adj={};
|
||||||
adj.u=this.world[x][y-1];
|
adj.u=this.world[x][y-1];
|
||||||
|
@ -204,6 +227,11 @@ class SnekGame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// draw our decaying fruits
|
||||||
|
this.decayFood.forEach(([x, y, birth]) =>
|
||||||
|
putTileAnimPercent(x, y, decayFruit, (this.playTime-birth)/2000)
|
||||||
|
);
|
||||||
|
|
||||||
// draw our snake
|
// draw our snake
|
||||||
const snake=assets.get('snake');
|
const snake=assets.get('snake');
|
||||||
this.ctx.fillStyle=snake.color;
|
this.ctx.fillStyle=snake.color;
|
||||||
|
@ -377,6 +405,14 @@ class SnekGame {
|
||||||
this.score+=10;
|
this.score+=10;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// you eat, you get a small score boost
|
||||||
|
case DECAY_FOOD:
|
||||||
|
this.score+=5;
|
||||||
|
this.decayFood=this.decayFood.filter(
|
||||||
|
([x, y, _]) => !(x==head[0] && y==head[1])
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
// you eat, you grow
|
// you eat, you grow
|
||||||
case FOOD:
|
case FOOD:
|
||||||
// re-grow the snake
|
// re-grow the snake
|
||||||
|
@ -421,6 +457,15 @@ class SnekGame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(this.rules.decayingFruitGrow) {
|
||||||
|
if(Math.random()<.2) { // 20% chance
|
||||||
|
const emptyCells=getEmptyCells();
|
||||||
|
const cell=emptyCells[Math.floor(Math.random()*emptyCells.length)];
|
||||||
|
this.world[cell[0]][cell[1]]=DECAY_FOOD;
|
||||||
|
this.decayFood.push([cell[0], cell[1], this.playTime]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(this.rules.speedIncrease) {
|
if(this.rules.speedIncrease) {
|
||||||
this.delay*=this.rules.speedMultiplier;
|
this.delay*=this.rules.speedMultiplier;
|
||||||
if(this.delay<this.rules.speedCap) this.delay=this.rules.speedCap;
|
if(this.delay<this.rules.speedCap) this.delay=this.rules.speedCap;
|
||||||
|
@ -437,6 +482,16 @@ class SnekGame {
|
||||||
}
|
}
|
||||||
this.snake.unshift(head);
|
this.snake.unshift(head);
|
||||||
|
|
||||||
|
// decay decaying food
|
||||||
|
this.decayFood.forEach(
|
||||||
|
([x, y, birth]) => {
|
||||||
|
if(this.playTime>=birth+2000) this.world[x][y]=EMPTY;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.decayFood=this.decayFood.filter(
|
||||||
|
([_, __, birth]) => this.playTime<birth+2000
|
||||||
|
);
|
||||||
|
|
||||||
// automatic speed increase
|
// automatic speed increase
|
||||||
if(this.rules.autoSpeedIncrease) {
|
if(this.rules.autoSpeedIncrease) {
|
||||||
if(this.delay>50 && this.tickId%this.rules.autoSpeadIncreaseTicks==0) this.delay--;
|
if(this.delay>50 && this.tickId%this.rules.autoSpeadIncreaseTicks==0) this.delay--;
|
||||||
|
|
Loading…
Reference in a new issue