added quick restart and crosspad grid
This commit is contained in:
parent
b12ac2fab9
commit
3a571a9c30
6 changed files with 103 additions and 13 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"touchscreen": {
|
"touchscreen": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"mode": "swipe",
|
"mode": "crosspad",
|
||||||
"deadzone": 50,
|
"deadzone": 50,
|
||||||
"buffer": false
|
"buffer": false
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
<main>
|
<main>
|
||||||
<nav></nav>
|
<nav></nav>
|
||||||
<canvas class="hidden"></canvas>
|
<canvas class="hidden"></canvas>
|
||||||
|
<div id="hud" class="hidden"></div>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer>
|
||||||
<img src="assets/icon32.png">
|
<img src="assets/icon32.png">
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
let currentInputs={};
|
let currentInputs={};
|
||||||
let handlers=[];
|
let handlers=[];
|
||||||
let config;
|
let config;
|
||||||
|
let hud;
|
||||||
|
|
||||||
const toAngleMagnitude=(x, y) => {
|
const toAngleMagnitude=(x, y) => {
|
||||||
return {
|
return {
|
||||||
|
@ -25,6 +26,26 @@ const handleAngleMagnitude=(x, y, threshold=0, fn=null, clearBuffer=false) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCrosspad=(() => {
|
const handleCrosspad=(() => {
|
||||||
|
const ns='http://www.w3.org/2000/svg';
|
||||||
|
const cross=document.createElementNS(ns, 'svg');
|
||||||
|
cross.classList.add('crosspadOverlay');
|
||||||
|
cross.setAttribute('width', 1000);
|
||||||
|
cross.setAttribute('height', 1000);
|
||||||
|
let dr=document.createElementNS(ns, 'line');
|
||||||
|
dr.setAttribute('x1', 0);
|
||||||
|
dr.setAttribute('y1', 0);
|
||||||
|
dr.setAttribute('x2', 1000);
|
||||||
|
dr.setAttribute('y2', 1000);
|
||||||
|
dr.setAttribute('stroke', 'black');
|
||||||
|
cross.appendChild(dr);
|
||||||
|
let dl=document.createElementNS(ns, 'line');
|
||||||
|
dl.setAttribute('x1', 1000);
|
||||||
|
dl.setAttribute('y1', 0);
|
||||||
|
dl.setAttribute('x2', 0);
|
||||||
|
dl.setAttribute('y2', 1000);
|
||||||
|
dl.setAttribute('stroke', 'black');
|
||||||
|
cross.appendChild(dl);
|
||||||
|
|
||||||
const fn=e =>
|
const fn=e =>
|
||||||
handleAngleMagnitude(
|
handleAngleMagnitude(
|
||||||
e.touches[0].clientX-window.innerWidth/2,
|
e.touches[0].clientX-window.innerWidth/2,
|
||||||
|
@ -35,7 +56,9 @@ const handleCrosspad=(() => {
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
touchstart: fn,
|
touchstart: fn,
|
||||||
touchmove: fn
|
touchmove: fn,
|
||||||
|
init: () => hud.appendChild(cross),
|
||||||
|
fini: () => hud.removeChild(cross)
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -118,15 +141,23 @@ const handleEvent=(type, evt) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const enableHandler=handler => {
|
const enableHandler=handler => {
|
||||||
if(!handlers.includes(handler)) handlers.push(handler);
|
if(!handlers.includes(handler)) {
|
||||||
|
handlers.push(handler);
|
||||||
|
if(handler.init) handler.init();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const disableHandler=handler => {
|
const disableHandler=handler => {
|
||||||
let idx=handlers.indexOf(handler);
|
let idx=handlers.indexOf(handler);
|
||||||
if(idx!=-1) handlers.splice(idx, 1);
|
if(idx!=-1) {
|
||||||
|
handlers.splice(idx, 1);
|
||||||
|
if(handler.fini) handler.fini();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateConfig=cfg =>
|
const updateConfig=cfg =>
|
||||||
config=cfg;
|
config=cfg;
|
||||||
|
const setHud=elem =>
|
||||||
|
hud=elem;
|
||||||
|
|
||||||
const clear=() =>
|
const clear=() =>
|
||||||
Object
|
Object
|
||||||
|
@ -149,5 +180,5 @@ return module.exports={
|
||||||
touchscreenJoystick: handleJoystick,
|
touchscreenJoystick: handleJoystick,
|
||||||
touchscreenSwipe: handleSwipe
|
touchscreenSwipe: handleSwipe
|
||||||
},
|
},
|
||||||
updateConfig
|
updateConfig, setHud
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
const main=document.querySelector('main');
|
const main=document.querySelector('main');
|
||||||
const nav=main.querySelector('nav');
|
const nav=main.querySelector('nav');
|
||||||
const canvas=main.querySelector('canvas');
|
const canvas=main.querySelector('canvas');
|
||||||
|
const hud=main.querySelector('#hud');
|
||||||
|
|
||||||
// load config
|
// load config
|
||||||
const config=assets.get('config'); //TODO use an actual config module
|
const config=assets.get('config'); //TODO use an actual config module
|
||||||
|
@ -26,7 +27,7 @@
|
||||||
let currentGame=null;
|
let currentGame=null;
|
||||||
|
|
||||||
// forward-declare functions
|
// forward-declare functions
|
||||||
let resizeCanvas, getLevel, startGame, handleWin, handleDeath, menu, help;
|
let resizeCanvas, getLevel, startGame, handleWin, handleDeath, menu, help, restart;
|
||||||
|
|
||||||
// handle window resize and fullscreen
|
// handle window resize and fullscreen
|
||||||
resizeCanvas=() => {
|
resizeCanvas=() => {
|
||||||
|
@ -119,6 +120,7 @@
|
||||||
// setup the DOM
|
// setup the DOM
|
||||||
nav.classList.add('hidden');
|
nav.classList.add('hidden');
|
||||||
canvas.classList.remove('hidden');
|
canvas.classList.remove('hidden');
|
||||||
|
hud.classList.remove('hidden');
|
||||||
|
|
||||||
// push some userdata to the snake
|
// push some userdata to the snake
|
||||||
snek.userdata={
|
snek.userdata={
|
||||||
|
@ -142,12 +144,13 @@
|
||||||
// setup the DOM
|
// setup the DOM
|
||||||
nav.classList.remove('hidden');
|
nav.classList.remove('hidden');
|
||||||
canvas.classList.add('hidden');
|
canvas.classList.add('hidden');
|
||||||
|
hud.classList.add('hidden');
|
||||||
};
|
};
|
||||||
|
|
||||||
// display the win popup
|
// display the win popup
|
||||||
handleWin=async snek => {
|
handleWin=async snek => {
|
||||||
// get userdata back
|
// hide the HUD
|
||||||
const {category, levelId, filename}=snek.userdata;
|
hud.classList.add('hidden');
|
||||||
|
|
||||||
// create and configure popup
|
// create and configure popup
|
||||||
let popup=new Popup("Finished!");
|
let popup=new Popup("Finished!");
|
||||||
|
@ -171,10 +174,11 @@
|
||||||
|
|
||||||
// act on it
|
// act on it
|
||||||
if(result=='retry') {
|
if(result=='retry') {
|
||||||
startGame(category, levelId, filename);
|
restart();
|
||||||
} else if(result=='menu') {
|
} else if(result=='menu') {
|
||||||
location.hash='menu';
|
location.hash='menu';
|
||||||
} else if(result=='next') {
|
} else if(result=='next') {
|
||||||
|
const {category, levelId}=snek.userdata;
|
||||||
let nextId=(+levelId)+1;
|
let nextId=(+levelId)+1;
|
||||||
let {levelString}=getLevel(category, nextId)
|
let {levelString}=getLevel(category, nextId)
|
||||||
location.hash=levelString;
|
location.hash=levelString;
|
||||||
|
@ -183,8 +187,8 @@
|
||||||
|
|
||||||
// display the death popup
|
// display the death popup
|
||||||
handleDeath=async snek => {
|
handleDeath=async snek => {
|
||||||
// get userdata back
|
// hide the HUD
|
||||||
const {category, levelId, filename}=snek.userdata;
|
hud.classList.add('hidden');
|
||||||
|
|
||||||
// create and configure popup
|
// create and configure popup
|
||||||
let popup=new Popup("Finished!");
|
let popup=new Popup("Finished!");
|
||||||
|
@ -204,12 +208,29 @@
|
||||||
|
|
||||||
// act on it
|
// act on it
|
||||||
if(result=='retry') {
|
if(result=='retry') {
|
||||||
startGame(category, levelId, filename);
|
restart();
|
||||||
} else if(result=='menu') {
|
} else if(result=='menu') {
|
||||||
location.hash='menu';
|
location.hash='menu';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// quick restart
|
||||||
|
restart=() => {
|
||||||
|
if(currentGame && currentGame.playing) {
|
||||||
|
const {category, levelId, filename}=currentGame.userdata;
|
||||||
|
startGame(category, levelId, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addEventListener('keydown', e => {
|
||||||
|
if(e.key=='r') restart();
|
||||||
|
});
|
||||||
|
(() => {
|
||||||
|
let restartbtn=hud.appendChild(document.createElement('span'));
|
||||||
|
restartbtn.classList.add('restart');
|
||||||
|
restartbtn.addEventListener('click', restart);
|
||||||
|
restartbtn.addEventListener('touchend', restart);
|
||||||
|
})();
|
||||||
|
|
||||||
// handle page navigation
|
// handle page navigation
|
||||||
window.addEventListener('hashchange', () => {
|
window.addEventListener('hashchange', () => {
|
||||||
const hash=location.hash.substr(1);
|
const hash=location.hash.substr(1);
|
||||||
|
@ -222,6 +243,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
// enable input methods according to config
|
// enable input methods according to config
|
||||||
|
input.setHud(hud);
|
||||||
if(config.keyboard.enabled) {
|
if(config.keyboard.enabled) {
|
||||||
input.enableHandler(input.availableHandlers.keyboard);
|
input.enableHandler(input.availableHandlers.keyboard);
|
||||||
}
|
}
|
||||||
|
|
34
src/less/hud.less
Normal file
34
src/less/hud.less
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#hud {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
position: fixed;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.restart {
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '⟳';
|
||||||
|
font-size: 3rem;
|
||||||
|
opacity: .5;
|
||||||
|
color: @accentfg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.crosspadOverlay {
|
||||||
|
pointer-events: none;
|
||||||
|
top: 50vh;
|
||||||
|
left: 50vw;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
}
|
|
@ -105,3 +105,5 @@ p {
|
||||||
// setup the popups
|
// setup the popups
|
||||||
@import 'popup';
|
@import 'popup';
|
||||||
|
|
||||||
|
// setup the hud
|
||||||
|
@import 'hud';
|
||||||
|
|
Loading…
Reference in a new issue