added win popup
This commit is contained in:
parent
76f1765be7
commit
3997e94a68
4 changed files with 192 additions and 12 deletions
|
@ -2,6 +2,9 @@
|
||||||
location.hash='';
|
location.hash='';
|
||||||
|
|
||||||
const assets=require('assets');
|
const assets=require('assets');
|
||||||
|
const Popup=require('popup');
|
||||||
|
const SnekGame=require('snek');
|
||||||
|
|
||||||
await new Promise(ok => assets.onReady(ok));
|
await new Promise(ok => assets.onReady(ok));
|
||||||
|
|
||||||
const main=document.querySelector('main');
|
const main=document.querySelector('main');
|
||||||
|
@ -60,7 +63,7 @@
|
||||||
const gp=navigator.getGamepads()[0];
|
const gp=navigator.getGamepads()[0];
|
||||||
let inputs=currentInputs;
|
let inputs=currentInputs;
|
||||||
if(!gp || !gp.axes) return;
|
if(!gp || !gp.axes) return;
|
||||||
|
|
||||||
const magnitude=Math.hypot(gp.axes[0], gp.axes[1]);
|
const magnitude=Math.hypot(gp.axes[0], gp.axes[1]);
|
||||||
const angle=((Math.atan2(gp.axes[0], gp.axes[1])+2*Math.PI)%(2*Math.PI))/Math.PI;
|
const angle=((Math.atan2(gp.axes[0], gp.axes[1])+2*Math.PI)%(2*Math.PI))/Math.PI;
|
||||||
if(magnitude>config.gamepad.deadzone) {
|
if(magnitude>config.gamepad.deadzone) {
|
||||||
|
@ -73,6 +76,10 @@
|
||||||
if(!config.gamepad.buffer) inputs.clearBuffer=true;
|
if(!config.gamepad.buffer) inputs.clearBuffer=true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const startGame=async (category, filename) => {
|
||||||
|
//TODO migrate relevant code here
|
||||||
|
};
|
||||||
|
|
||||||
window.addEventListener('hashchange', async () => {
|
window.addEventListener('hashchange', async () => {
|
||||||
nav.classList.add('hidden');
|
nav.classList.add('hidden');
|
||||||
|
|
||||||
|
@ -83,7 +90,6 @@
|
||||||
return await resp.json();
|
return await resp.json();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const SnekGame=require('snek');
|
|
||||||
const snek=new SnekGame(level, canvas, rules);
|
const snek=new SnekGame(level, canvas, rules);
|
||||||
canvas.classList.remove('hidden');
|
canvas.classList.remove('hidden');
|
||||||
snek.start();
|
snek.start();
|
||||||
|
@ -91,6 +97,21 @@
|
||||||
if(evt=='tick') {
|
if(evt=='tick') {
|
||||||
if(navigator.getGamepads) handleGamepads();
|
if(navigator.getGamepads) handleGamepads();
|
||||||
snek.handleInputs(currentInputs);
|
snek.handleInputs(currentInputs);
|
||||||
|
} else if(evt=='win') {
|
||||||
|
let popup=new Popup("Finished!");
|
||||||
|
popup.addStrong("You won!");
|
||||||
|
popup.addContent({
|
||||||
|
"Time": snek.playTime/1000+'s',
|
||||||
|
"Score": snek.score,
|
||||||
|
"Final length": snek.snake.length
|
||||||
|
});
|
||||||
|
popup.buttons={
|
||||||
|
retry: "Retry",
|
||||||
|
next: "Next level",
|
||||||
|
menu: "Main menu"
|
||||||
|
};
|
||||||
|
popup.display();
|
||||||
|
//TODO do something with the result
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
currentGame=snek;
|
currentGame=snek;
|
||||||
|
|
87
src/js/popup.js
Normal file
87
src/js/popup.js
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
const objToDom=obj => {
|
||||||
|
if(obj[Popup.EM]) {
|
||||||
|
let em=document.createElement('em');
|
||||||
|
em.appendChild(document.createTextNode(obj[Popup.EM]));
|
||||||
|
return em;
|
||||||
|
} else if(obj[Popup.STRONG]) {
|
||||||
|
let em=document.createElement('strong');
|
||||||
|
em.appendChild(document.createTextNode(obj[Popup.STRONG]));
|
||||||
|
return em;
|
||||||
|
} else if(typeof obj=='string' || typeof obj=='number') {
|
||||||
|
return document.createTextNode(obj+'');
|
||||||
|
} else if(Array.isArray(obj)) {
|
||||||
|
let ul=document.createElement('ul');
|
||||||
|
obj.forEach(elem => ul.appendChild(objToDom(elem)));
|
||||||
|
return ul;
|
||||||
|
} else {
|
||||||
|
let table=document.createElement('table');
|
||||||
|
Object
|
||||||
|
.keys(obj)
|
||||||
|
.forEach(key => {
|
||||||
|
let tr=table.appendChild(document.createElement('tr'));
|
||||||
|
tr.appendChild(document.createElement('th')).appendChild(document.createTextNode(key));
|
||||||
|
tr.appendChild(document.createElement('td')).appendChild(objToDom(obj[key]));
|
||||||
|
});
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Popup {
|
||||||
|
constructor(title, content=[], buttons={}) {
|
||||||
|
this.title=title;
|
||||||
|
this.content=content.map(objToDom);
|
||||||
|
this.buttons={...buttons};
|
||||||
|
}
|
||||||
|
|
||||||
|
addContent(cnt) {
|
||||||
|
this.content.push(objToDom(cnt));
|
||||||
|
}
|
||||||
|
addText(cnt) {
|
||||||
|
this.content.push(document.createTextNode(cnt));
|
||||||
|
}
|
||||||
|
addEm(cnt) {
|
||||||
|
this.content.push(objToDom({[Popup.EM]: cnt}));
|
||||||
|
}
|
||||||
|
addStrong(cnt) {
|
||||||
|
this.content.push(objToDom({[Popup.STRONG]: cnt}));
|
||||||
|
}
|
||||||
|
|
||||||
|
async display() {
|
||||||
|
let outer=document.createElement('div');
|
||||||
|
outer.classList.add('popup');
|
||||||
|
let popup=outer.appendChild(document.createElement('div'));
|
||||||
|
popup.classList.add('content');
|
||||||
|
|
||||||
|
let title=popup.appendChild(document.createElement('h1'));
|
||||||
|
title.innerText=this.title;
|
||||||
|
|
||||||
|
let contentSection=popup.appendChild(document.createElement('section'));
|
||||||
|
this.content.forEach(elem => contentSection.appendChild(elem));
|
||||||
|
|
||||||
|
let buttonSection=popup.appendChild(document.createElement('section'));
|
||||||
|
let buttons=Object.keys(this.buttons).map(btn => {
|
||||||
|
let button=document.createElement('button');
|
||||||
|
button.innerText=this.buttons[btn];
|
||||||
|
button.dataset.code=btn;
|
||||||
|
return button;
|
||||||
|
});
|
||||||
|
buttons.forEach(btn => buttonSection.appendChild(btn));
|
||||||
|
|
||||||
|
document.body.appendChild(outer);
|
||||||
|
|
||||||
|
const code=await Promise.race(buttons.map(btn => new Promise(ok => {
|
||||||
|
btn.addEventListener('click', e => {
|
||||||
|
e.preventDefault();
|
||||||
|
return ok(btn.dataset.code);
|
||||||
|
});
|
||||||
|
})));
|
||||||
|
|
||||||
|
document.body.removeChild(outer);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Popup.EM=Symbol('EM');
|
||||||
|
Popup.STRONG=Symbol('STRONG');
|
||||||
|
|
||||||
|
return module.exports=Popup;
|
|
@ -84,7 +84,7 @@ class SnekGame {
|
||||||
// get our canvas, like, if we want to actually draw
|
// get our canvas, like, if we want to actually draw
|
||||||
this.canvas=canvas;
|
this.canvas=canvas;
|
||||||
this.ctx=canvas.getContext('2d');
|
this.ctx=canvas.getContext('2d');
|
||||||
|
|
||||||
// load the custom rules
|
// load the custom rules
|
||||||
this.rules=Object.assign({
|
this.rules=Object.assign({
|
||||||
fruitRegrow: true,
|
fruitRegrow: true,
|
||||||
|
@ -160,7 +160,7 @@ class SnekGame {
|
||||||
putTileAnim(x, y, fire);
|
putTileAnim(x, y, fire);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HOLE:
|
case HOLE:
|
||||||
case HOLE_S: {
|
case HOLE_S: {
|
||||||
putTile(x, y, hole.base);
|
putTile(x, y, hole.base);
|
||||||
let adj=checkAdj(x, y);
|
let adj=checkAdj(x, y);
|
||||||
|
@ -293,6 +293,9 @@ class SnekGame {
|
||||||
([x, y]) => !(x==head[0] && y==head[1])
|
([x, y]) => !(x==head[0] && y==head[1])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// increase score
|
||||||
|
this.score++;
|
||||||
|
|
||||||
// custom rules
|
// custom rules
|
||||||
if(this.rules.fruitRegrow) {
|
if(this.rules.fruitRegrow) {
|
||||||
const emptyCells=this.world
|
const emptyCells=this.world
|
||||||
|
@ -301,7 +304,7 @@ class SnekGame {
|
||||||
.map(
|
.map(
|
||||||
(r, y) => r==EMPTY?[x,y]:null
|
(r, y) => r==EMPTY?[x,y]:null
|
||||||
).filter(
|
).filter(
|
||||||
a => a
|
a => a
|
||||||
)
|
)
|
||||||
).flat();
|
).flat();
|
||||||
const cell=emptyCells[Math.floor(Math.random()*emptyCells.length)];
|
const cell=emptyCells[Math.floor(Math.random()*emptyCells.length)];
|
||||||
|
@ -409,9 +412,9 @@ class SnekGame {
|
||||||
this.firstStep=Date.now();
|
this.firstStep=Date.now();
|
||||||
this.tickId=0;
|
this.tickId=0;
|
||||||
this.playing=true;
|
this.playing=true;
|
||||||
|
this.score=0;
|
||||||
requestAnimationFrame(() => this.tick());
|
requestAnimationFrame(() => this.tick());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports=SnekGame;
|
return module.exports=SnekGame;
|
||||||
return SnekGame;
|
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
@keyframes popupAppear {
|
@keyframes popupAppear {
|
||||||
0% {
|
0% {
|
||||||
background: transparent;
|
background: rgba(0, 0, 0, 0%);
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
background: black;
|
background: rgba(0, 0, 0, 90%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup {
|
.popup {
|
||||||
animation: popupAppear 1s linear no-repeat;
|
animation: popupAppear 1s linear;
|
||||||
|
background: rgba(0, 0, 0, 90%);
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -18,12 +19,80 @@
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
border-radius: 2rem;
|
border-radius: 2rem;
|
||||||
background: @accentbg;
|
background: @bg;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
box-shadow: black 0 0 1rem;
|
||||||
|
|
||||||
postion: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
max-width: 50vw;
|
||||||
|
max-height: 50vh;
|
||||||
|
|
||||||
|
padding: 2rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
font-size: 1.4rem;
|
||||||
|
|
||||||
|
& > section {
|
||||||
|
margin: 1rem;
|
||||||
|
|
||||||
|
&:first-of-type {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
margin: .5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-of-type {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
tr {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
text-align: right;
|
||||||
|
&::after {
|
||||||
|
content: ':';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
padding: 0 .5rem;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
display: inline;
|
||||||
|
color: @accentfg;
|
||||||
|
background: @accentbg;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
border-radius: 1rem;
|
||||||
|
border: 0;
|
||||||
|
padding: 2rem;
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue