added decaying fruit

This commit is contained in:
Nathan DECHER 2020-04-06 15:17:21 +02:00
parent bf06218815
commit 530260ac54
4 changed files with 62 additions and 4 deletions

View File

@ -1,7 +1,7 @@
.PHONY: all clean
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)
IMAGES = $(foreach name, apple wall, public/assets/$(name)32.png)

View File

@ -10,6 +10,7 @@
[16, 10]
],
"rules": {
"superFruitGrow": true
"superFruitGrow": true,
"decayingFruitGrow": true
}
}

View File

@ -3,6 +3,7 @@ const ProgressBar=require('progress');
const assetSpecs=[
{ name: 'fruit', filename: 'apple32.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: 'hole', filename: 'hole-ts.png', type: 'image' },
{ name: 'fire', filename: 'fire-anim.png', type: 'image' },
@ -15,7 +16,8 @@ const assetSpecs=[
const tasks=[
{ from: 'hole', type: 'tileset', steps: 3, tiles: ['base', 'ul', 'dr', 'dl', 'ur', 'l', 'r', 'd', 'u'] },
{ 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');

View File

@ -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 {
constructor(settings, canvas, rules) {
@ -18,6 +18,7 @@ class SnekGame {
case ' ': return EMPTY;
case 'f': return FOOD;
case 'F': return SUPER_FOOD;
case 'd': return DECAY_FOOD;
case 'w': return WALL;
case 'o': return HOLE;
case 'i': return FIRE;
@ -37,6 +38,15 @@ class SnekGame {
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
// get the dimensions
@ -64,6 +74,14 @@ class SnekGame {
// add the 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
@ -93,6 +111,7 @@ class SnekGame {
this.rules=Object.assign({
fruitRegrow: true,
superFruitGrow: false,
decayingFruitGrow: false,
speedIncrease: true,
worldWrap: true,
winCondition: 'none',
@ -151,6 +170,7 @@ class SnekGame {
const hole=assets.get('hole');
const fire=assets.get('fire');
const superFruit=assets.get('superFruit');
const decayFruit=assets.get('decayFruit');
const putTile=(x, y, tile) => this.ctx.drawImage(
tile,
offsetX+cellSize*x,
@ -161,6 +181,9 @@ class SnekGame {
const putTileAnim=(x, y, tile) => putTile(x, y, tile[
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) => {
let adj={};
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
const snake=assets.get('snake');
this.ctx.fillStyle=snake.color;
@ -377,6 +405,14 @@ class SnekGame {
this.score+=10;
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
case FOOD:
// 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) {
this.delay*=this.rules.speedMultiplier;
if(this.delay<this.rules.speedCap) this.delay=this.rules.speedCap;
@ -437,6 +482,16 @@ class SnekGame {
}
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
if(this.rules.autoSpeedIncrease) {
if(this.delay>50 && this.tickId%this.rules.autoSpeadIncreaseTicks==0) this.delay--;