added quick restart and crosspad grid

This commit is contained in:
Nathan DECHER 2020-04-05 20:58:35 +02:00
parent b12ac2fab9
commit 3a571a9c30
6 changed files with 103 additions and 13 deletions

View file

@ -1,7 +1,7 @@
{
"touchscreen": {
"enabled": true,
"mode": "swipe",
"mode": "crosspad",
"deadzone": 50,
"buffer": false
},

View file

@ -19,6 +19,7 @@
<main>
<nav></nav>
<canvas class="hidden"></canvas>
<div id="hud" class="hidden"></div>
</main>
<footer>
<img src="assets/icon32.png">

View file

@ -1,6 +1,7 @@
let currentInputs={};
let handlers=[];
let config;
let hud;
const toAngleMagnitude=(x, y) => {
return {
@ -25,6 +26,26 @@ const handleAngleMagnitude=(x, y, threshold=0, fn=null, clearBuffer=false) => {
}
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 =>
handleAngleMagnitude(
e.touches[0].clientX-window.innerWidth/2,
@ -35,7 +56,9 @@ const handleCrosspad=(() => {
);
return {
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 => {
if(!handlers.includes(handler)) handlers.push(handler);
if(!handlers.includes(handler)) {
handlers.push(handler);
if(handler.init) handler.init();
}
};
const disableHandler=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 =>
config=cfg;
const setHud=elem =>
hud=elem;
const clear=() =>
Object
@ -149,5 +180,5 @@ return module.exports={
touchscreenJoystick: handleJoystick,
touchscreenSwipe: handleSwipe
},
updateConfig
updateConfig, setHud
};

View file

@ -15,6 +15,7 @@
const main=document.querySelector('main');
const nav=main.querySelector('nav');
const canvas=main.querySelector('canvas');
const hud=main.querySelector('#hud');
// load config
const config=assets.get('config'); //TODO use an actual config module
@ -26,7 +27,7 @@
let currentGame=null;
// 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
resizeCanvas=() => {
@ -119,6 +120,7 @@
// setup the DOM
nav.classList.add('hidden');
canvas.classList.remove('hidden');
hud.classList.remove('hidden');
// push some userdata to the snake
snek.userdata={
@ -142,12 +144,13 @@
// setup the DOM
nav.classList.remove('hidden');
canvas.classList.add('hidden');
hud.classList.add('hidden');
};
// display the win popup
handleWin=async snek => {
// get userdata back
const {category, levelId, filename}=snek.userdata;
// hide the HUD
hud.classList.add('hidden');
// create and configure popup
let popup=new Popup("Finished!");
@ -171,10 +174,11 @@
// act on it
if(result=='retry') {
startGame(category, levelId, filename);
restart();
} else if(result=='menu') {
location.hash='menu';
} else if(result=='next') {
const {category, levelId}=snek.userdata;
let nextId=(+levelId)+1;
let {levelString}=getLevel(category, nextId)
location.hash=levelString;
@ -183,8 +187,8 @@
// display the death popup
handleDeath=async snek => {
// get userdata back
const {category, levelId, filename}=snek.userdata;
// hide the HUD
hud.classList.add('hidden');
// create and configure popup
let popup=new Popup("Finished!");
@ -204,12 +208,29 @@
// act on it
if(result=='retry') {
startGame(category, levelId, filename);
restart();
} else if(result=='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
window.addEventListener('hashchange', () => {
const hash=location.hash.substr(1);
@ -222,6 +243,7 @@
});
// enable input methods according to config
input.setHud(hud);
if(config.keyboard.enabled) {
input.enableHandler(input.availableHandlers.keyboard);
}

34
src/less/hud.less Normal file
View 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;
}
}

View file

@ -41,7 +41,7 @@ em {
header, footer {
background: @accentbg;
img {
border: 4px solid @accentfg;
border-radius: 2px;
@ -105,3 +105,5 @@ p {
// setup the popups
@import 'popup';
// setup the hud
@import 'hud';