added config manager (closes #18) and fixed crash at win
This commit is contained in:
parent
a7e2d1c201
commit
d339dd0a06
8 changed files with 331 additions and 120 deletions
2
Makefile
2
Makefile
|
@ -5,7 +5,7 @@ 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)
|
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 metaConfig, 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
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
{
|
{
|
||||||
"touchscreen": {
|
"input.touchscreen.crosspad.enabled": true,
|
||||||
"enabled": true,
|
"input.touchscreen.crosspad.overlay": true,
|
||||||
"mode": "crosspad",
|
|
||||||
"deadzone": 50,
|
"input.touchscreen.joystick.enabled": false,
|
||||||
"buffer": false
|
"input.touchscreen.joystick.overlay": true,
|
||||||
},
|
"input.touchscreen.joystick.deadzone": 10,
|
||||||
"keyboard": {
|
|
||||||
"enabled": true,
|
"input.touchscreen.swipe.enabled": false,
|
||||||
"buffer": false
|
"input.touchscreen.swipe.deadzone": 50,
|
||||||
},
|
|
||||||
"gamepad": {
|
"input.gamepad.enabled": true,
|
||||||
"enabled": true,
|
"input.gamepad.deadzone": 0.5,
|
||||||
"deadzone": 0.5,
|
|
||||||
"buffer": true
|
"input.keyboard.enabled": true,
|
||||||
},
|
|
||||||
"appearance": {
|
"input.buffer": false,
|
||||||
"grid": "none"
|
|
||||||
}
|
"appearance.grid": "none"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,121 @@
|
||||||
{
|
{
|
||||||
"touchscreen": {
|
"input": {
|
||||||
"mode": [
|
"name": "Input settings"
|
||||||
"crosspad",
|
|
||||||
"joystick",
|
|
||||||
"swipe"
|
|
||||||
],
|
|
||||||
"deadzone": {
|
|
||||||
"min": 1,
|
|
||||||
"max": 100
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"gamepad": {
|
|
||||||
"deadzone": {
|
"input.touchscreen": {
|
||||||
"min": 0,
|
"name": "Touchscreen settings"
|
||||||
"max": 1
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"appearance": {
|
|
||||||
"grid": [
|
"input.touchscreen.crosspad": {
|
||||||
"grid",
|
"name": "Crosspad mode"
|
||||||
"checkerboard",
|
},
|
||||||
"none"
|
"input.touchscreen.crosspad.enabled": {
|
||||||
|
"name": "Enable crosspad",
|
||||||
|
"type": "boolean",
|
||||||
|
"excludes": [
|
||||||
|
"input.touchscreen.joystick.enabled",
|
||||||
|
"input.touchscreen.swipe.enabled"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"input.touchscreen.crosspad.overlay": {
|
||||||
|
"name": "Show overlay",
|
||||||
|
"type": "boolean",
|
||||||
|
"parent": "input.touchscreen.crosspad.enabled"
|
||||||
|
},
|
||||||
|
|
||||||
|
"input.touchscreen.joystick": {
|
||||||
|
"name": "Joystick mode"
|
||||||
|
},
|
||||||
|
"input.touchscreen.joystick.enabled": {
|
||||||
|
"name": "Enable joystick",
|
||||||
|
"type": "boolean",
|
||||||
|
"excludes": [
|
||||||
|
"input.touchscreen.crosspad.enabled",
|
||||||
|
"input.touchscreen.swipe.enabled"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"input.touchscreen.joystick.overlay": {
|
||||||
|
"name": "Show overlay",
|
||||||
|
"type": "boolean",
|
||||||
|
"parent": "input.touchscreen.joystick.enabled"
|
||||||
|
},
|
||||||
|
"input.touchscreen.joystick.deadzone": {
|
||||||
|
"name": "Deadzone",
|
||||||
|
"type": "number",
|
||||||
|
"parent": "input.touchscreen.joystick.enabled",
|
||||||
|
"bounds": {
|
||||||
|
"min": 1,
|
||||||
|
"max": 100,
|
||||||
|
"inc": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"input.touchscreen.swipe": {
|
||||||
|
"name": "Swipe mode"
|
||||||
|
},
|
||||||
|
"input.touchscreen.swipe.enabled": {
|
||||||
|
"name": "Enable swipe",
|
||||||
|
"type": "boolean",
|
||||||
|
"excludes": [
|
||||||
|
"input.touchscreen.crosspad.enabled",
|
||||||
|
"input.touchscreen.joystick.enabled"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"input.touchscreen.swipe.deadzone": {
|
||||||
|
"name": "Deadzone",
|
||||||
|
"type": "number",
|
||||||
|
"parent": "input.touchscreen.swipe.enabled",
|
||||||
|
"bounds": {
|
||||||
|
"min": 1,
|
||||||
|
"max": 100,
|
||||||
|
"inc": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"input.gamepad": {
|
||||||
|
"name": "Gamepad settings"
|
||||||
|
},
|
||||||
|
"input.gamepad.enabled": {
|
||||||
|
"name": "Enable gamepad",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"input.gamepad.deadzone": {
|
||||||
|
"name": "Deadzone",
|
||||||
|
"type": "number",
|
||||||
|
"parent": "input.gamepad.enabled",
|
||||||
|
"bounds": {
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"inc": 0.1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"input.keyboard": {
|
||||||
|
"name": "Keyboard settings"
|
||||||
|
},
|
||||||
|
"input.keyboard.enabled": {
|
||||||
|
"name": "Enable keyboard",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
|
||||||
|
"input.buffer": {
|
||||||
|
"name": "Enable input buffering",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
|
||||||
|
"appearance": {
|
||||||
|
"name": "Appearance"
|
||||||
|
},
|
||||||
|
"appearance.grid": {
|
||||||
|
"name": "Grid type",
|
||||||
|
"type": "choice",
|
||||||
|
"bounds": {
|
||||||
|
"choices": [
|
||||||
|
"none",
|
||||||
|
"grid",
|
||||||
|
"checkerboard"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
const ProgressBar=require('progress');
|
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: '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' },
|
||||||
|
{ name: 'metaConfig', filename: 'metaConfig.json', type: 'json' }
|
||||||
];
|
];
|
||||||
|
|
||||||
const tasks=[
|
const tasks=[
|
||||||
|
@ -84,7 +85,7 @@ let readyListeners=[];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'animation': {
|
case 'animation': {
|
||||||
let anim=assets[task.from]=[];
|
let anim=assets[task.from]=[];
|
||||||
let frameCount=source.height/source.width;
|
let frameCount=source.height/source.width;
|
||||||
|
|
76
src/js/config.js
Normal file
76
src/js/config.js
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
const assets=require('assets');
|
||||||
|
|
||||||
|
let watchers=Object.create(null);
|
||||||
|
let lastWatchCode=1;
|
||||||
|
|
||||||
|
const toBoolean=v => {
|
||||||
|
if(v=='false' || v==false) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const get=key => {
|
||||||
|
let confVal=localStorage.getItem('config.'+key);
|
||||||
|
if(confVal===null) return assets.get('config')[key];
|
||||||
|
return confVal;
|
||||||
|
};
|
||||||
|
const getB=key => toBoolean(get(key));
|
||||||
|
const getN=key => +get(key);
|
||||||
|
const getS=key => ''+get(key);
|
||||||
|
|
||||||
|
const set=(key, value) => {
|
||||||
|
localStorage.setItem('config.'+key, value);
|
||||||
|
let interested=watchers[key];
|
||||||
|
if(interested) interested.forEach(watcher => watcher(key, value));
|
||||||
|
};
|
||||||
|
|
||||||
|
const remove=key => {
|
||||||
|
localStorage.removeItem('config.'+key, value);
|
||||||
|
let interested=watchers[key];
|
||||||
|
if(interested) interested.forEach(watcher => watcher(key, assets.get('config')[key]));
|
||||||
|
};
|
||||||
|
const clear=() =>
|
||||||
|
Object
|
||||||
|
.keys(assets.get('config'))
|
||||||
|
.forEach(remove);
|
||||||
|
|
||||||
|
const watch=(key, fn) => {
|
||||||
|
if(!watchers[key]) watchers[key]=[];
|
||||||
|
const code='w'+lastWatchCode++;
|
||||||
|
watchers[key][code]=fn;
|
||||||
|
return code;
|
||||||
|
};
|
||||||
|
const watchB=(key, fn) => watch(key, (k, v) => fn(k, toBoolean(v)));
|
||||||
|
const watchN=(key, fn) => watch(key, (k, v) => fn(k, +v));
|
||||||
|
const watchS=(key, fn) => watch(key, (k, v) => fn(k, ''+v));
|
||||||
|
|
||||||
|
const unwatch=(key, code) => {
|
||||||
|
if(!watchers[key]) return;
|
||||||
|
delete watchers[key][code];
|
||||||
|
};
|
||||||
|
|
||||||
|
const list=() =>
|
||||||
|
Object
|
||||||
|
.keys(assets.get('config'));
|
||||||
|
const dict=() => {
|
||||||
|
let dict=Object.create(null);
|
||||||
|
Object
|
||||||
|
.keys(assets.get('config'))
|
||||||
|
.forEach(
|
||||||
|
key => dict[key]={
|
||||||
|
raw: get(key),
|
||||||
|
b: getB(key),
|
||||||
|
n: getN(key),
|
||||||
|
s: getS(key)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return dict;
|
||||||
|
};
|
||||||
|
|
||||||
|
return module.exports={
|
||||||
|
get, getB, getN, getS,
|
||||||
|
set,
|
||||||
|
remove, clear,
|
||||||
|
watch, watchB, watchN, watchS,
|
||||||
|
unwatch,
|
||||||
|
list, dict
|
||||||
|
};
|
138
src/js/input.js
138
src/js/input.js
|
@ -1,6 +1,7 @@
|
||||||
|
const config=require('config');
|
||||||
|
|
||||||
let currentInputs={};
|
let currentInputs={};
|
||||||
let handlers=[];
|
let handlers=[];
|
||||||
let config;
|
|
||||||
let hud;
|
let hud;
|
||||||
|
|
||||||
const toAngleMagnitude=(x, y) => {
|
const toAngleMagnitude=(x, y) => {
|
||||||
|
@ -10,7 +11,7 @@ const toAngleMagnitude=(x, y) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAngleMagnitude=(x, y, threshold=0, fn=null, clearBuffer=false) => {
|
const handleAngleMagnitude=(x, y, threshold=0, fn=null) => {
|
||||||
const {angle, magnitude}=toAngleMagnitude(x, y);
|
const {angle, magnitude}=toAngleMagnitude(x, y);
|
||||||
|
|
||||||
if(magnitude>threshold) {
|
if(magnitude>threshold) {
|
||||||
|
@ -20,7 +21,6 @@ const handleAngleMagnitude=(x, y, threshold=0, fn=null, clearBuffer=false) => {
|
||||||
else if(angle>1.25 && angle<1.75) inputs.left=true;
|
else if(angle>1.25 && angle<1.75) inputs.left=true;
|
||||||
else inputs.down=true;
|
else inputs.down=true;
|
||||||
|
|
||||||
if(clearBuffer) inputs.clearBuffer=true;
|
|
||||||
if(fn) fn(angle, magnitude);
|
if(fn) fn(angle, magnitude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,19 +46,42 @@ const handleCrosspad=(() => {
|
||||||
dl.setAttribute('stroke', 'black');
|
dl.setAttribute('stroke', 'black');
|
||||||
cross.appendChild(dl);
|
cross.appendChild(dl);
|
||||||
|
|
||||||
|
let useOverlay=false;
|
||||||
|
let enabled=false;
|
||||||
|
const displayOverlay=() => {
|
||||||
|
if(hud) {
|
||||||
|
if(useOverlay && enabled) hud.appendChild(cross);
|
||||||
|
else hud.removeChild(cross);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
config.watchB('input.touchscreen.crosspad.overlay', (k, v) => {
|
||||||
|
useOverlay=v;
|
||||||
|
displayOverlay();
|
||||||
|
});
|
||||||
|
|
||||||
const fn=e =>
|
const fn=e =>
|
||||||
handleAngleMagnitude(
|
handleAngleMagnitude(
|
||||||
e.touches[0].clientX-window.innerWidth/2,
|
e.touches[0].clientX-window.innerWidth/2,
|
||||||
e.touches[0].clientY-window.innerHeight/2,
|
e.touches[0].clientY-window.innerHeight/2,
|
||||||
0,
|
0,
|
||||||
null,
|
null
|
||||||
!config.touchscreen.buffer
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const init=() => {
|
||||||
|
useOverlay=config.getB('input.touchscreen.crosspad.overlay');
|
||||||
|
enabled=true;
|
||||||
|
displayOverlay();
|
||||||
|
};
|
||||||
|
const fini=() => {
|
||||||
|
enabled=false;
|
||||||
|
displayOverlay();
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
touchstart: fn,
|
touchstart: fn,
|
||||||
touchmove: fn,
|
touchmove: fn,
|
||||||
init: () => hud.appendChild(cross),
|
init,
|
||||||
fini: () => hud.removeChild(cross)
|
fini
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -69,8 +92,6 @@ const handleKeyboard={
|
||||||
else if(e.key=='ArrowDown') inputs.down=true;
|
else if(e.key=='ArrowDown') inputs.down=true;
|
||||||
else if(e.key=='ArrowLeft') inputs.left=true;
|
else if(e.key=='ArrowLeft') inputs.left=true;
|
||||||
else if(e.key=='ArrowRight') inputs.right=true;
|
else if(e.key=='ArrowRight') inputs.right=true;
|
||||||
|
|
||||||
if(!config.keyboard.buffer) inputs.clearBuffer=true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,7 +100,17 @@ const handleJoystick=(() => {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0
|
y: 0
|
||||||
};
|
};
|
||||||
|
let deadzone;
|
||||||
|
|
||||||
|
const init=() => {
|
||||||
|
deadzone=config.getN('input.touchscreen.joystick.deadzone');
|
||||||
|
};
|
||||||
|
config.watchN('input.touchscreen.joystick.deadzone', (k, v) => {
|
||||||
|
deadzone=v;
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
init,
|
||||||
touchstart: e => {
|
touchstart: e => {
|
||||||
center.x=e.touches[0].clientX;
|
center.x=e.touches[0].clientX;
|
||||||
center.y=e.touches[0].clientY;
|
center.y=e.touches[0].clientY;
|
||||||
|
@ -88,9 +119,8 @@ const handleJoystick=(() => {
|
||||||
handleAngleMagnitude(
|
handleAngleMagnitude(
|
||||||
e.touches[0].clientX-center.x,
|
e.touches[0].clientX-center.x,
|
||||||
e.touches[0].clientY-center.y,
|
e.touches[0].clientY-center.y,
|
||||||
config.touchscreen.deadzone,
|
deadzone,
|
||||||
null,
|
null
|
||||||
!config.touchscreen.buffer
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -100,38 +130,59 @@ const handleSwipe=(() => {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0
|
y: 0
|
||||||
};
|
};
|
||||||
|
let deadzone;
|
||||||
|
|
||||||
let resetCenter=e => {
|
let resetCenter=e => {
|
||||||
center.x=e.touches[0].clientX;
|
center.x=e.touches[0].clientX;
|
||||||
center.y=e.touches[0].clientY;
|
center.y=e.touches[0].clientY;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const init=() => {
|
||||||
|
deadzone=config.getN('input.touchscreen.swipe.deadzone');
|
||||||
|
};
|
||||||
|
config.watchN('input.touchscreen.swipe.deadzone', (k, v) => {
|
||||||
|
deadzone=v;
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
init,
|
||||||
touchstart: resetCenter,
|
touchstart: resetCenter,
|
||||||
touchmove: e =>
|
touchmove: e =>
|
||||||
handleAngleMagnitude(
|
handleAngleMagnitude(
|
||||||
e.touches[0].clientX-center.x,
|
e.touches[0].clientX-center.x,
|
||||||
e.touches[0].clientY-center.y,
|
e.touches[0].clientY-center.y,
|
||||||
config.touchscreen.deadzone,
|
deadzone,
|
||||||
() => resetCenter(e),
|
() => resetCenter(e)
|
||||||
!config.touchscreen.buffer
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const handleGamepads={
|
const handleGamepads=(() => {
|
||||||
frame: () => {
|
let deadzone;
|
||||||
const gp=navigator.getGamepads()[0];
|
|
||||||
let inputs=currentInputs;
|
|
||||||
if(!gp || !gp.axes) return;
|
|
||||||
|
|
||||||
handleAngleMagnitude(
|
const init=() => {
|
||||||
gp.axes[0],
|
deadzone=config.getN('input.touchscreen.swipe.deadzone');
|
||||||
gp.axes[1],
|
};
|
||||||
config.gamepad.deadzone,
|
config.watchN('input.touchscreen.swipe.deadzone', (k, v) => {
|
||||||
null,
|
deadzone=v;
|
||||||
!config.gamepad.buffer
|
});
|
||||||
);
|
|
||||||
}
|
return {
|
||||||
};
|
init,
|
||||||
|
frame: () => {
|
||||||
|
const gp=navigator.getGamepads()[0];
|
||||||
|
let inputs=currentInputs;
|
||||||
|
if(!gp || !gp.axes) return;
|
||||||
|
|
||||||
|
handleAngleMagnitude(
|
||||||
|
gp.axes[0],
|
||||||
|
gp.axes[1],
|
||||||
|
deadzone,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
const handleEvent=(type, evt) => {
|
const handleEvent=(type, evt) => {
|
||||||
for(let handler of handlers) {
|
for(let handler of handlers) {
|
||||||
|
@ -153,11 +204,22 @@ const disableHandler=handler => {
|
||||||
if(handler.fini) handler.fini();
|
if(handler.fini) handler.fini();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const linkHandler=(handler, key) => {
|
||||||
|
if(config.getB(key)) enableHandler(handler);
|
||||||
|
config.watchB(key, (k, v) => {
|
||||||
|
if(v) enableHandler(handler);
|
||||||
|
else disableHandler(handler);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const updateConfig=cfg =>
|
const init=({hud: hudElem}) => {
|
||||||
config=cfg;
|
hud=hudElem;
|
||||||
const setHud=elem =>
|
linkHandler(handleCrosspad, 'input.touchscreen.crosspad.enabled');
|
||||||
hud=elem;
|
linkHandler(handleJoystick, 'input.touchscreen.joystick.enabled');
|
||||||
|
linkHandler(handleSwipe, 'input.touchscreen.swipe.enabled');
|
||||||
|
linkHandler(handleGamepads, 'input.gamepad.enabled');
|
||||||
|
linkHandler(handleKeyboard, 'input.keyboard.enabled');
|
||||||
|
};
|
||||||
|
|
||||||
const clear=() =>
|
const clear=() =>
|
||||||
Object
|
Object
|
||||||
|
@ -171,14 +233,6 @@ for(let type of ['keydown', 'touchstart', 'touchmove']) {
|
||||||
return module.exports={
|
return module.exports={
|
||||||
inputs: currentInputs,
|
inputs: currentInputs,
|
||||||
clear,
|
clear,
|
||||||
enableHandler, disableHandler,
|
|
||||||
framefn: handleEvent.bind(null, 'frame'),
|
framefn: handleEvent.bind(null, 'frame'),
|
||||||
availableHandlers: {
|
init
|
||||||
keyboard: handleKeyboard,
|
|
||||||
gamepad: handleGamepads,
|
|
||||||
touchscreenCrosspad: handleCrosspad,
|
|
||||||
touchscreenJoystick: handleJoystick,
|
|
||||||
touchscreenSwipe: handleSwipe
|
|
||||||
},
|
|
||||||
updateConfig, setHud
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
const SnekGame=require('snek');
|
const SnekGame=require('snek');
|
||||||
const input=require('input');
|
const input=require('input');
|
||||||
const levels=require('levels');
|
const levels=require('levels');
|
||||||
|
const config=require('config');
|
||||||
|
|
||||||
// get a known state
|
// get a known state
|
||||||
await new Promise(ok => assets.onReady(ok));
|
await new Promise(ok => assets.onReady(ok));
|
||||||
|
@ -17,9 +18,6 @@
|
||||||
const canvas=main.querySelector('canvas');
|
const canvas=main.querySelector('canvas');
|
||||||
const hud=main.querySelector('#hud');
|
const hud=main.querySelector('#hud');
|
||||||
|
|
||||||
// load config
|
|
||||||
const config=assets.get('config'); //TODO use an actual config module
|
|
||||||
|
|
||||||
// load data from server
|
// load data from server
|
||||||
const levelList=assets.get('levelList');
|
const levelList=assets.get('levelList');
|
||||||
|
|
||||||
|
@ -115,7 +113,6 @@
|
||||||
handleDeath(snek);
|
handleDeath(snek);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
snek.config=config;
|
|
||||||
|
|
||||||
// setup the DOM
|
// setup the DOM
|
||||||
nav.classList.add('hidden');
|
nav.classList.add('hidden');
|
||||||
|
@ -152,6 +149,9 @@
|
||||||
// hide the HUD
|
// hide the HUD
|
||||||
hud.classList.add('hidden');
|
hud.classList.add('hidden');
|
||||||
|
|
||||||
|
// fetch userdata from the game
|
||||||
|
const {category, levelId, filename}=snek.userdata;
|
||||||
|
|
||||||
// create and configure popup
|
// create and configure popup
|
||||||
let popup=new Popup("Finished!");
|
let popup=new Popup("Finished!");
|
||||||
popup.addStrong("You won!");
|
popup.addStrong("You won!");
|
||||||
|
@ -174,7 +174,6 @@
|
||||||
|
|
||||||
// act on it
|
// act on it
|
||||||
if(result=='retry') {
|
if(result=='retry') {
|
||||||
const {category, levelId, filename}=snek.userdata;
|
|
||||||
startGame(category, levelId, filename);
|
startGame(category, levelId, filename);
|
||||||
} else if(result=='menu') {
|
} else if(result=='menu') {
|
||||||
location.hash='menu';
|
location.hash='menu';
|
||||||
|
@ -244,22 +243,6 @@
|
||||||
startGame(category, levelId, filename);
|
startGame(category, levelId, filename);
|
||||||
});
|
});
|
||||||
|
|
||||||
// enable input methods according to config
|
// enable input methods overlay
|
||||||
input.setHud(hud);
|
input.init({hud});
|
||||||
if(config.keyboard.enabled) {
|
|
||||||
input.enableHandler(input.availableHandlers.keyboard);
|
|
||||||
}
|
|
||||||
if(config.gamepad.enabled) {
|
|
||||||
input.enableHandler(input.availableHandlers.gamepad);
|
|
||||||
}
|
|
||||||
if(config.touchscreen.enabled) {
|
|
||||||
if(config.touchscreen.mode=='crosspad') {
|
|
||||||
input.enableHandler(input.availableHandlers.touchscreenCrosspad);
|
|
||||||
} else if(config.touchscreen.mode=='joystick') {
|
|
||||||
input.enableHandler(input.availableHandlers.touchscreenJoystick);
|
|
||||||
} else if(config.touchscreen.mode=='swipe') {
|
|
||||||
input.enableHandler(input.availableHandlers.touchscreenSwipe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
input.updateConfig(config);
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -104,7 +104,7 @@ class SnekGame {
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
const assets=require('assets');
|
const assets=require('assets');
|
||||||
const config=this.config;
|
const config=require('config');
|
||||||
|
|
||||||
// clear the canvas, because it's easier than having to deal with everything
|
// clear the canvas, because it's easier than having to deal with everything
|
||||||
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
@ -125,7 +125,7 @@ class SnekGame {
|
||||||
this.ctx.fillRect(0, offsetY+cellSize*this.dimensions[1], this.canvas.width, offsetY);
|
this.ctx.fillRect(0, offsetY+cellSize*this.dimensions[1], this.canvas.width, offsetY);
|
||||||
|
|
||||||
// draw a grid/checkerboard if requested
|
// draw a grid/checkerboard if requested
|
||||||
if(config.appearance.grid=='grid') {
|
if(config.get('appearance.grid')=='grid') {
|
||||||
this.ctx.strokeStyle='rgba(0, 0, 0, 50%)';
|
this.ctx.strokeStyle='rgba(0, 0, 0, 50%)';
|
||||||
this.ctx.lineCap='square';
|
this.ctx.lineCap='square';
|
||||||
this.ctx.lineWidth=1;
|
this.ctx.lineWidth=1;
|
||||||
|
@ -139,7 +139,7 @@ class SnekGame {
|
||||||
this.ctx.lineTo(this.canvas.width-offsetX, offsetY+y*cellSize);
|
this.ctx.lineTo(this.canvas.width-offsetX, offsetY+y*cellSize);
|
||||||
}
|
}
|
||||||
this.ctx.stroke();
|
this.ctx.stroke();
|
||||||
} else if(config.appearance.grid=='checkerboard') {
|
} else if(config.get('appearance.grid')=='checkerboard') {
|
||||||
this.ctx.fillStyle='rgba(0, 0, 0, 10%)';
|
this.ctx.fillStyle='rgba(0, 0, 0, 10%)';
|
||||||
for(let x=0; x<this.dimensions[0]; x++) {
|
for(let x=0; x<this.dimensions[0]; x++) {
|
||||||
for(let y=(x+1)%2; y<this.dimensions[1]; y+=2) {
|
for(let y=(x+1)%2; y<this.dimensions[1]; y+=2) {
|
||||||
|
@ -400,6 +400,8 @@ class SnekGame {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleInputs(inputs) {
|
handleInputs(inputs) {
|
||||||
|
const config=require('config');
|
||||||
|
|
||||||
// change direction if the input is valid
|
// change direction if the input is valid
|
||||||
const trySet=(dir) => {
|
const trySet=(dir) => {
|
||||||
if(!dir.every((e, i) => e==this.lastDirection[i] || e==-this.lastDirection[i])) {
|
if(!dir.every((e, i) => e==this.lastDirection[i] || e==-this.lastDirection[i])) {
|
||||||
|
@ -420,13 +422,13 @@ class SnekGame {
|
||||||
});
|
});
|
||||||
|
|
||||||
// try all inputs in order and unbuffer them if valid
|
// try all inputs in order and unbuffer them if valid
|
||||||
if(inputs.left && trySet([-1, 0])) return delete inputs.left;
|
if(inputs.left && trySet([-1, 0])) delete inputs.left;
|
||||||
else if(inputs.right && trySet([ 1, 0])) return delete inputs.right;
|
else if(inputs.right && trySet([ 1, 0])) delete inputs.right;
|
||||||
else if(inputs.up && trySet([ 0,-1])) return delete inputs.up;
|
else if(inputs.up && trySet([ 0,-1])) delete inputs.up;
|
||||||
else if(inputs.down && trySet([ 0, 1])) return delete inputs.down;
|
else if(inputs.down && trySet([ 0, 1])) delete inputs.down;
|
||||||
|
|
||||||
// buffering might be disabled
|
// buffering might be disabled
|
||||||
if(inputs.clearBuffer) {
|
if(!config.getB('input.buffer')) {
|
||||||
Object
|
Object
|
||||||
.keys(inputs)
|
.keys(inputs)
|
||||||
.forEach(k => delete inputs[k]);
|
.forEach(k => delete inputs[k]);
|
||||||
|
|
Loading…
Reference in a new issue