added fire and a stub for level 5

Nathan DECHER 5 years ago
parent f050baafbc
commit 02e72795cc
  1. 1
      .gitignore
  2. 15
      Makefile
  3. BIN
      assets/fire.png
  4. 0
      build/.gitkeep
  5. 41
      levels/level5.json
  6. 27
      src/js/assets.js
  7. 13
      src/js/snek.js

1
.gitignore vendored

@ -4,4 +4,5 @@ public/assets/*.json
public/css/*.css public/css/*.css
public/js/*.js public/js/*.js
public/favicon.ico public/favicon.ico
build/*.png

@ -1,18 +1,22 @@
.PHONY: all clean .PHONY: all clean
FIRE_ANIM = $(foreach angle, $(shell seq 0 6 359), build/fire$(angle).png)
IMAGES = $(foreach name, apple wall, public/assets/$(name)32.png) IMAGES = $(foreach name, apple wall, public/assets/$(name)32.png)
TILESETS = $(foreach name, hole, public/assets/$(name)-ts.png) TILESETS = $(foreach name, hole, public/assets/$(name)-ts.png)
ANIMATIONS = $(foreach name, fire, public/assets/$(name)-anim.png)
JSON = $(foreach name, snake levelList config, public/assets/$(name).json) JSON = $(foreach name, snake levelList config, public/assets/$(name).json)
ICON = public/assets/icon32.png public/assets/icon256.png public/favicon.ico ICON = public/assets/icon32.png public/assets/icon256.png public/favicon.ico
CSS = public/css/snek.css CSS = public/css/snek.css
JS = public/js/snek.js JS = public/js/snek.js
OUTPUT = $(IMAGES) $(TILESETS) $(JSON) $(ICON) $(CSS) $(JS) OUTPUT = $(IMAGES) $(TILESETS) $(ANIMATIONS) $(JSON) $(ICON) $(CSS) $(JS)
all: images tilesets json icon css js all: images tilesets animations json icon css js
images: $(IMAGES) images: $(IMAGES)
tilesets: $(TILESETS) tilesets: $(TILESETS)
animations: $(ANIMATIONS)
json: $(JSON) json: $(JSON)
icon: $(ICON) icon: $(ICON)
css: $(CSS) css: $(CSS)
@ -34,6 +38,12 @@ public/assets/%256.png: assets/%.jpg
public/assets/%-ts.png: assets/%.png public/assets/%-ts.png: assets/%.png
convert $^ -scale 32x $@ convert $^ -scale 32x $@
public/assets/fire-anim.png: $(FIRE_ANIM)
convert $^ -append -scale 32x $@
build/fire%.png: assets/fire.png
convert $^ -distort ScaleRotateTranslate $(shell echo $@ | sed 's/[^0-9]*//g') $@
public/assets/%.json: assets/%.json public/assets/%.json: assets/%.json
cp $^ $@ cp $^ $@
@ -44,4 +54,5 @@ public/js/snek.js: $(wildcard src/js/*.js)
node mergejs.js $^ > $@ node mergejs.js $^ > $@
clean: clean:
rm -f build/*.*
rm -f $(OUTPUT) rm -f $(OUTPUT)

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 KiB

@ -0,0 +1,41 @@
{
"world": [
" i ",
" i ",
" iiiiiii i iiiiiii ",
" i f i ",
" i i ",
" i iiiiiiiiiiiii i ",
" i i ",
" i f i ",
" i i i ",
" i i i ",
" i i i ",
" i i i ",
" i i i ",
" i i i ",
" i i i ",
"iiif i fiiiiiiiiiiiiiiif i fiii",
" i i i ",
" i i i ",
" i i i ",
" i i i ",
" i i i ",
" i i i ",
" i i i ",
" i f i ",
" i i ",
" i iiiiiiiiiiiii i ",
" i i ",
" i f i ",
" iiiiiii i iiiiiii ",
" i ",
" i "
],
"delay": 200,
"snake": [
[16, 4],
[15, 4],
[14, 4]
]
}

@ -3,14 +3,16 @@ const ProgressBar=require('progress');
const assetSpecs=[ const assetSpecs=[
{ name: 'fruit', filename: 'apple32.png', type: 'image' }, { name: 'fruit', filename: 'apple32.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: 'snake', filename: 'snake.json', type: 'json' }, { name: 'snake', filename: 'snake.json', type: 'json' },
{ name: 'levelList', filename: 'levelList.json', type: 'json' }, { name: 'levelList', filename: 'levelList.json', type: 'json' },
{ name: 'config', filename: 'config.json', type: 'json' } { name: 'config', filename: 'config.json', type: 'json' }
]; ];
const tasks=[ const tasks=[
{ from: 'hole', type: 'tileset', tiles: ['base', 'ul', 'dr', 'dl', 'ur', 'l', 'r', 'd', 'u'], steps: 9 } { from: 'hole', type: 'tileset', tiles: ['base', 'ul', 'dr', 'dl', 'ur', 'l', 'r', 'd', 'u'], steps: 3 },
{ from: 'fire', type: 'animation', steps: 6 }
]; ];
const cvs=document.createElement('canvas'); const cvs=document.createElement('canvas');
@ -32,7 +34,7 @@ bar.addReadyListener(() => {
}); });
//XXX purposefully slow down asset loading //XXX purposefully slow down asset loading
const sleep=(ms=1000) => new Promise(ok => setTimeout(ok, ms*Math.random())); const sleep=(ms=500) => new Promise(ok => setTimeout(ok, ms*Math.random()));
const loadAsset=async (asset) => { const loadAsset=async (asset) => {
const response=await fetch('assets/'+asset.filename); const response=await fetch('assets/'+asset.filename);
@ -75,8 +77,23 @@ let readyListeners=[];
for(let tId in task.tiles) { for(let tId in task.tiles) {
const tName=task.tiles[tId]; const tName=task.tiles[tId];
asset[tName]=await createImageBitmap(source, 0, source.width*tId, source.width, source.width); asset[tName]=await createImageBitmap(source, 0, source.width*tId, source.width, source.width);
await sleep(100); if(tId%(task.tiles.length/task.steps)==0) {
bar.update(); await sleep(100);
bar.update();
}
}
break;
}
case 'animation': {
let anim=assets[task.from]=[];
let frameCount=source.height/source.width;
for(let i=0; i<frameCount; i++) {
anim[i]=await createImageBitmap(source, 0, source.width*i, source.width, source.width);
if(i%(frameCount/task.steps)==0) {
await sleep(100);
bar.update();
}
} }
break; break;
} }

@ -1,4 +1,4 @@
const [EMPTY, FOOD, WALL, HOLE, HOLE_S, SNAKE]=Array(6).keys(); const [EMPTY, FOOD, WALL, FIRE, HOLE, HOLE_S, SNAKE]=Array(7).keys();
class SnekGame { class SnekGame {
constructor(settings, canvas, rules) { constructor(settings, canvas, rules) {
@ -19,6 +19,7 @@ class SnekGame {
case 'f': return FOOD; case 'f': return FOOD;
case 'w': return WALL; case 'w': return WALL;
case 'o': return HOLE; case 'o': return HOLE;
case 'i': return FIRE;
} }
})(); })();
} }
@ -53,6 +54,9 @@ class SnekGame {
// add the holes // add the holes
if(settings.holes) settings.holes.forEach(([x, y]) => this.world[x][y]=HOLE); if(settings.holes) settings.holes.forEach(([x, y]) => this.world[x][y]=HOLE);
// add the fires
if(settings.fires) settings.fires.forEach(([x, y]) => this.world[x][y]=FIRE);
// add the food // add the food
settings.food.forEach(([x, y]) => this.world[x][y]=FOOD); settings.food.forEach(([x, y]) => this.world[x][y]=FOOD);
this.fruits=[...settings.food]; this.fruits=[...settings.food];
@ -122,7 +126,7 @@ class SnekGame {
// draw our walls // draw our walls
const wall=assets.get('wall'); const wall=assets.get('wall');
const hole=assets.get('hole'); const hole=assets.get('hole');
const fire=assets.get('fire');
const putTile=(x, y, tile) => this.ctx.drawImage( const putTile=(x, y, tile) => this.ctx.drawImage(
tile, tile,
offsetX+cellSize*x, offsetX+cellSize*x,
@ -149,6 +153,10 @@ class SnekGame {
putTile(x, y, wall); putTile(x, y, wall);
break; break;
case FIRE:
putTile(x, y, fire[Math.floor(Date.now()/1000*60)%60]);
break;
case HOLE: case HOLE:
case HOLE_S: { case HOLE_S: {
putTile(x, y, hole.base); putTile(x, y, hole.base);
@ -253,6 +261,7 @@ class SnekGame {
switch(this.world[head[0]][head[1]]) { switch(this.world[head[0]][head[1]]) {
// you hit, you die // you hit, you die
case WALL: case WALL:
case FIRE:
case SNAKE: case SNAKE:
case HOLE_S: case HOLE_S:
return this.die(); return this.die();

Loading…
Cancel
Save