added fire and a stub for level 5
This commit is contained in:
parent
f050baafbc
commit
02e72795cc
7 changed files with 88 additions and 9 deletions
1
.gitignore
vendored
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
|
||||||
|
|
||||||
|
|
15
Makefile
15
Makefile
|
@ -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)
|
||||||
|
|
BIN
assets/fire.png
Executable file
BIN
assets/fire.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 368 KiB |
0
build/.gitkeep
Normal file
0
build/.gitkeep
Normal file
41
levels/level5.json
Normal file
41
levels/level5.json
Normal file
|
@ -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…
Reference in a new issue