added win popup

main
Codinget 5 years ago
parent 11c90949fb
commit 30061272e8
  1. 25
      src/js/main.js
  2. 87
      src/js/popup.js
  3. 13
      src/js/snek.js
  4. 79
      src/less/popup.less

@ -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;

@ -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…
Cancel
Save