Countdown timer built.

master
Ben Burlingham 5 years ago
parent 9afd3d8364
commit 94130bd067
  1. 47
      client/connection.js
  2. 3
      client/content.js
  3. 287
      client/controls.js
  4. 30
      controls.css
  5. 6
      index.css
  6. 22
      index.html
  7. 1
      notes.txt
  8. 18
      server.js

@ -2,16 +2,28 @@
const Connection = function() { const Connection = function() {
// Local event listeners // Local event listeners
document.addEventListener('L-robots', () => { document.addEventListener('L-start', () => {
this.ws.send(JSON.stringify({ head: { type: 'reposition-robots' }})); this.ws.send(JSON.stringify({ type: 'start' }));
}); });
document.addEventListener('L-walls', () => { document.addEventListener('L-stop', () => {
this.ws.send(JSON.stringify({ head: { type: 'regenerate-walls' }})); this.ws.send(JSON.stringify({ type: 'stop' }));
});
document.addEventListener('L-skip', () => {
this.ws.send(JSON.stringify({ type: 'skip' }));
}); });
document.addEventListener('L-guess', (evt) => { document.addEventListener('L-guess', (evt) => {
this.ws.send(JSON.stringify({ head: { type: 'guess' }, rawBody: evt.detail })); this.ws.send(JSON.stringify({ type: 'guess', rawBody: evt.detail }));
});
document.addEventListener('L-robots', () => {
this.ws.send(JSON.stringify({ type: 'robots' }));
});
document.addEventListener('L-walls', () => {
this.ws.send(JSON.stringify({ type: 'walls' }));
}); });
document.addEventListener('L-join', (evt) => { document.addEventListener('L-join', (evt) => {
@ -20,7 +32,8 @@ const Connection = function() {
}; };
Connection.prototype.connect = function(){ Connection.prototype.connect = function(){
const names = ["Biff", "Morty", "Herb", "Chester", "Lyle", "Cap", "Dale", "Ned", "Mindy"] const names = ["Biff", "Morty", "Herb", "Chester", "Lyle", "Cap", "Dale", "Ned", "Mindy", "Frankie", "Gabriel", "Mona", "Dolores",
"Sepulveda", "Venus", "Blingbing", "Cyrpt"]
const r = Math.floor(Math.random() * names.length); const r = Math.floor(Math.random() * names.length);
const rawInput = names[r] //prompt("What is your name?"); const rawInput = names[r] //prompt("What is your name?");
@ -57,21 +70,13 @@ Connection.prototype.onReceiveMessage = function({ data }) {
let eventName; let eventName;
switch (msg.type) { switch (msg.type) {
case 'players': case 'guess': eventName = 'G-guess'; break;
eventName = 'G-players'; case 'players': eventName = 'G-players'; break;
break; case 'robots': eventName = 'G-robots'; break;
case 'skip': eventName = 'G-skip'; break;
case 'robots': case 'start': eventName = 'G-start'; break;
eventName = 'G-robots'; case 'stop': eventName = 'G-stop'; break;
break; case 'walls': eventName = 'G-walls'; break;
case 'walls':
eventName = 'G-walls';
break;
case 'guess':
eventName = 'G-guess';
break;
} }
if (eventName) { if (eventName) {

@ -11,7 +11,8 @@ const Content = function({ parent, squares }) {
// this.drawSquares(); // this.drawSquares();
// document.addEventListener('L-conn-open', this.msgStartGame.bind(this)); // document.addEventListener('L-conn-open', this.msgStartGame.bind(this));
// document.addEventListener('G-walls', this.msgStart.bind(this));
// document.addEventListener('G-robots', this.msgStart.bind(this));
// document.addEventListener('board-reset', this.onReset.bind(this)); // document.addEventListener('board-reset', this.onReset.bind(this));
// from connection: board.drawRobots(data.body); // from connection: board.drawRobots(data.body);
// from connection: board.drawWalls(data.body); // from connection: board.drawWalls(data.body);

287
client/controls.js vendored

@ -4,39 +4,58 @@ const Controls = function() {
this.moves = 0; this.moves = 0;
this.names = {}; this.names = {};
// this.buildGuesses(); this.drawGuesses();
// this.setUi('connecting');
document.addEventListener('L-conn-open', this.msgJoin.bind(this)); document.addEventListener('L-conn-open', this.msgJoin.bind(this));
document.addEventListener('L-move', this.msgMove.bind(this));
// Message handlers: "Local message" and "Global message" // Message handlers: "Local message" and "Global message"
// document.addEventListener('G-move', this.onMoveIncrement.bind(this)); // document.addEventListener('G-move', this.msgMove.bind(this));
// document.addEventListener('G-win', this.onMoveIncrement.bind(this)); // document.addEventListener('G-win', this.msgWin.bind(this));
// document.addEventListener('G-start', this.msgStartGame.bind(this)); document.addEventListener('G-guess', this.msgGuess.bind(this));
// document.addEventListener('G-stop', this.msgStartGame.bind(this)); document.addEventListener('G-skip', this.msgSkip.bind(this));
// document.addEventListener('G-players', this.msgStartGame.bind(this)); <--- controls.playersUpdate(data.body) document.addEventListener('G-start', this.msgStart.bind(this));
document.addEventListener('G-stop', this.msgStop.bind(this));
document.addEventListener('G-players', this.msgPlayers.bind(this));
// document.addEventListener('G-walls', this.msgStartGame.bind(this));
// document.addEventListener('G-robots', this.msgStartGame.bind(this));
// document.addEventListener('G-guess', this.msgStartGame.bind(this)); <--- controls.onReceiveGuess(data.body);
// document.addEventListener('L-move', this.onMoveIncrement.bind(this));
// document.addEventListener('L-conn-error', this.onConnectionError.bind(this));
// document.addEventListener('L-skip-timer', this.msgStartGame.bind(this));
// document.addEventListener('L-skip-timer', this.msgStartGame.bind(this));
// Click handlers // Click handlers
// document.getElementById('controls-moves-reset').addEventListener('click', this.onMoveReset.bind(this)); document.getElementById('controls-start').addEventListener('click', this.onClickStart.bind(this));
// document.getElementById('controls-start-game').addEventListener('click', this.onStartGame.bind(this)); document.getElementById('controls-stop').addEventListener('click', this.onClickStop.bind(this));
// document.getElementById('controls-stop-game').addEventListener('click', this.onStopGame.bind(this)); document.getElementById('controls-walls').addEventListener('click', this.onClickWalls.bind(this));
// document.getElementById('controls-regenerate-walls').addEventListener('click', this.onRegenWalls.bind(this)); document.getElementById('controls-robots').addEventListener('click', this.onClickRobots.bind(this));
// document.getElementById('controls-reposition-robots').addEventListener('click', this.onRepositionRobots.bind(this)); document.getElementById('controls-reset').addEventListener('click', this.onClickReset.bind(this));
// document.getElementById('controls-timer-skip').addEventListener('click', this.onSkipTimer.bind(this)); document.getElementById('controls-skip').addEventListener('click', this.onClickSkip.bind(this));
} }
//===== UI //===== UI
Controls.prototype.countdownStart = function(seconds) {
const countdown = document.getElementById('controls-countdown');
countdown.dataset.tick = seconds - 1;
setTimeout(this.countdownTick.bind(this), 1000);
};
Controls.prototype.countdownTick = function() {
const countdown = document.getElementById('controls-countdown');
const tick = countdown.dataset.tick * 1;
countdown.dataset.tick = tick - 1;
if (tick === 0) {
this.countdownComplete();
return;
}
const s = (tick !== 1) ? 's' : '';
countdown.innerHTML = `${tick} second${s}!`;
setTimeout(this.countdownTick.bind(this), 1000);
};
Controls.prototype.countdownComplete = function() {
alert("boom")
};
Controls.prototype.drawGuesses = function() { Controls.prototype.drawGuesses = function() {
const container = document.getElementById('controls-guesses'); const container = document.getElementById('controls-guesses');
container.querySelectorAll('.controls-guess').forEach(el => el.parentNode.removeChild(el)); container.querySelectorAll('.controls-guess').forEach(el => el.parentNode.removeChild(el));
@ -58,117 +77,131 @@ Controls.prototype.showWaiting = function() {
document.getElementById('controls-stop').parentNode.style.display = 'none'; document.getElementById('controls-stop').parentNode.style.display = 'none';
// document.getElementById('controls-moves-reset').parentNode.style.display = 'none'; // document.getElementById('controls-moves-reset').parentNode.style.display = 'none';
// document.getElementById('controls-timer-skip').parentNode.style.display = 'none'; document.getElementById('controls-guesses').style.display = 'none';
// document.getElementById('controls-guesses').parentNode.style.display = 'none'; document.getElementById('controls-panic').style.display = 'none';
}; };
Controls.prototype.showGuessing = function() {
document.getElementById('controls-start').parentNode.style.display = 'none';
document.getElementById('controls-walls').parentNode.style.display = 'none';
document.getElementById('controls-robots').parentNode.style.display = 'none';
document.getElementById('controls-panic').style.display = 'none';
document.getElementById('controls-stop').parentNode.style.display = '';
// document.getElementById('controls-moves-reset').parentNode.style.display = '';
document.getElementById('controls-guesses').style.display = '';
}
Controls.prototype.showPanic = function() {
this.showGuessing();
document.getElementById('controls-panic').style.display = '';
};
//===== Message handlers //===== Message handlers
Controls.prototype.msgGuess = function(evt) {
const blurbs = [ " has a solution: ", " can do it in ", " says, maybe ", " wagers ",
" reckons ", " is pretty sure it's ", ", confidently: ", " wants it to be ",
" says ", " hazards ", " guesses ", " thinks it might be "];
const blurb = blurbs[Math.floor(Math.random() * blurbs.length)];
const msg = evt.detail;
const guess = msg.guess;
document.getElementById('controls-panic').querySelector('.controls-alert-urgent').innerHTML = (`${this.names[msg.id]}${blurb}${guess} moves.`);
this.showPanic();
this.countdownStart(30);
}
Controls.prototype.msgJoin = function() { Controls.prototype.msgJoin = function() {
this.showWaiting(); this.showWaiting();
}; };
// Controls.prototype.playersUpdate = function(names) { Controls.prototype.msgMove = function() {
// const container = document.getElementById('controls-players'); this.moves++;
// const keys = Object.keys(names); document.getElementById('controls-moves').innerHTML = this.moves;
};
// if (keys.length > 0) {
// const nobody = document.getElementById('controls-players-nobody'); Controls.prototype.msgPlayers = function(evt) {
// nobody.parentNode.removeChild(nobody); const container = document.getElementById('controls-players');
// } const names = evt.detail.body;
const keys = Object.keys(names);
// keys.forEach(connectionId => {
// const id = `player-${connectionId}`; if (keys.length > 0) {
const nobody = document.getElementById('controls-players-nobody');
// if (document.getElementById(id)) { nobody && nobody.parentNode.removeChild(nobody);
// return; }
// }
keys.forEach(connectionId => {
// const n = document.createElement('div'); const id = `player-${connectionId}`;
// n.id = id;
// n.innerHTML = names[connectionId]; if (document.getElementById(id)) {
// n.className = 'controls-player'; return;
// container.appendChild(n) }
// });
// console.log(names) const n = document.createElement('div');
// this.names = names; n.id = id;
n.innerHTML = names[connectionId];
// // container.querySelectorAll('.controls-player').forEach(el => { n.className = 'controls-player';
// // if (!names[el.id]) { container.appendChild(n)
// // container.removeChild(el); });
// // }
// // }) this.names = names;
// };
container.querySelectorAll('.controls-player').forEach(el => {
// Controls.prototype.onReceiveGuess = function(message) { const id = el.id.split('player-').pop();
// console.log(this.names[message.id] + ' has a solution') if (!this.names[id]) {
// } container.removeChild(el);
}
// Controls.prototype.onClickGuess = function(evt) { });
// const e = new CustomEvent('guess', { detail: { moves: evt.currentTarget.dataset.value } }); };
// document.dispatchEvent(e);
// } Controls.prototype.msgSkip = function() {
this.coundownComplete();
// Controls.prototype.onMoveIncrement = function() { };
// this.moves++;
// document.getElementById('controls-moves').innerHTML = this.moves; Controls.prototype.msgStart = function() {
// }; this.showGuessing();
};
// Controls.prototype.onMoveReset = function() {
// this.moves = 0; Controls.prototype.msgStop = function() {
// document.getElementById('controls-moves').innerHTML = this.moves; this.showWaiting();
}
// const event = new Event('board-reset');
// document.dispatchEvent(event); //===== Click handlers
// };
Controls.prototype.dispatch = function(evt, data) {
// Controls.prototype.onStartGame = function() { const e = (data ? new CustomEvent(evt, { detail: data }) : new Event(evt));
// this.setUi('gameStarted'); document.dispatchEvent(e);
}
// const evt = new Event('startGame');
// document.dispatchEvent(evt); Controls.prototype.onClickGuess = function(evt) {
// } this.dispatch('L-guess', { moves: evt.currentTarget.dataset.value });
}
// Controls.prototype.onStopGame = function() {
// this.setUi('gameStopped'); Controls.prototype.onClickRobots = function() {
this.dispatch('L-robots');
// const evt = new Event('stopGame'); }
// document.dispatchEvent(evt);
// } Controls.prototype.onClickSkip = function() {
this.dispatch('L-skip');
// Controls.prototype.onRegenWalls = function() { }
// const evt = new Event('regenerateWalls');
// document.dispatchEvent(evt); Controls.prototype.onClickStart = function() {
// } this.dispatch('L-start');
}
// Controls.prototype.onRepositionRobots = function() {
// const evt = new Event('repositionRobots'); Controls.prototype.onClickStop = function() {
// document.dispatchEvent(evt); this.dispatch('L-stop');
// } }
// Controls.prototype.setUi = function(state) { Controls.prototype.onClickWalls = function() {
// switch(state) { this.dispatch('L-walls');
// case 'gameStarted': }
// document.getElementById('controls-start-round').parentNode.style.display = 'none';
// document.getElementById('controls-regenerate-walls').parentNode.style.display = 'none'; Controls.prototype.onClickReset = function() {
// document.getElementById('controls-reposition-robots').parentNode.style.display = 'none'; this.moves = 0;
document.getElementById('controls-moves').innerHTML = this.moves;
// document.getElementById('controls-stop-round').parentNode.style.display = '';
// document.getElementById('controls-moves-reset').parentNode.style.display = ''; this.dispatch('L-reset');
// document.getElementById('controls-timer-skip').parentNode.style.display = ''; };
// document.getElementById('controls-guesses').parentNode.style.display = '';
// break;
// case 'gameStopped':
// document.getElementById('controls-start-round').parentNode.style.display = '';
// document.getElementById('controls-regenerate-walls').parentNode.style.display = '';
// document.getElementById('controls-reposition-robots').parentNode.style.display = '';
// document.getElementById('controls-stop-round').parentNode.style.display = 'none';
// document.getElementById('controls-moves-reset').parentNode.style.display = 'none';
// document.getElementById('controls-timer-skip').parentNode.style.display = 'none';
// document.getElementById('controls-guesses').parentNode.style.display = 'none';
// break;
// }
// }

@ -28,13 +28,20 @@
margin: 24px 0 12px 0; margin: 24px 0 12px 0;
} }
.controls-alert { .controls-alert-info {
background: #21dfae; background: #21dfae;
color: #222; color: #222;
padding: 12px; padding: 12px;
margin: 24px 0 12px 0; margin: 24px 0 12px 0;
} }
.controls-alert-urgent {
background: #DE4F21;
color: #fff;
padding: 12px;
margin: 24px 0 12px 0;
}
.controls-row { .controls-row {
align-items: center; align-items: center;
display: flex; display: flex;
@ -48,21 +55,14 @@
width: 100%; width: 100%;
} }
#controls-players {
}
.controls-player { .controls-player {
padding: 8px; padding: 8px;
} }
#controls-local {
}
.controls-guess { .controls-guess {
background: none; background: none;
cursor: pointer; cursor: pointer;
float: left; display: inline-block;
font-size: 12px; font-size: 12px;
height: 30px; height: 30px;
line-height: 30px; line-height: 30px;
@ -75,12 +75,22 @@
} }
#controls-footer { #controls-footer {
background: #9A748C;
bottom: 0; bottom: 0;
left: 0; left: 0;
padding: 24px; padding: 24px;
position: absolute; position: absolute;
right: 0; right: 0;
text-align: center;
}
#controls-footer a {
color: #639699;
font-size: 24px;
text-decoration: none;
}
#controls-footer a:hover {
text-decoration: underline;
} }
.controls-button { .controls-button {

@ -12,9 +12,5 @@ PALETTE:
21DFAE Aquamarine 21DFAE Aquamarine
4D3243 Plum 4D3243 Plum
DE4F21 Fire DE4F21 Fire
639699 Cadet
EXPERIMENTAL:
9A748C
639699
364B4D
*/ */

@ -75,23 +75,27 @@
<div class='controls-subtitle'>Local</div> <div class='controls-subtitle'>Local</div>
<div class="controls-row"> <div class="controls-row">
<div>Moves:</div> <div>Moves:</div>
<div id="controls-moves">4</div> <div id="controls-moves">-</div>
<div class='controls-button' id='controls-moves-reset'>Reset</div> <div class='controls-button' id='controls-reset'>Reset</div>
</div> </div>
<div class="controls-row"> <div id="controls-guesses">
<div>Timer:</div> <div class="controls-alert-info">How many moves to win?</div>
<div id="controls-timer">0:42</div>
<div class='controls-button' id='controls-timer-skip'>Skip</div>
</div> </div>
<div id="controls-guesses"> <div id="controls-panic">
<div class="controls-alert">How many moves to win?</div> <div class='controls-alert-urgent'></div>
<div class="controls-row">
<div>Countdown:</div>
<div id="controls-countdown">30 seconds!</div>
<div class='controls-button' id='controls-skip'>Skip</div>
</div>
</div> </div>
</div> </div>
<div id="controls-footer"> <div id="controls-footer">
<div>Heart (match head height)</div> <a href='http://buymeacoff.ee/5EGitAV' target='_blank'>&#9825;</a>
</div> </div>
</div> </div>

@ -10,3 +10,4 @@
// TODO walls algorigthm // TODO walls algorigthm
// TODO fix overlapping robot arrows // TODO fix overlapping robot arrows
// TODO win declare/add/remove // TODO win declare/add/remove
// TODO restore state on join

@ -23,7 +23,7 @@ const Server = {
}, },
messageOthers: (ws, message) => { messageOthers: (ws, message) => {
DEBUG && console.log(`Sending to other ${wss.clients.size - 1} client(s):`); DEBUG && console.log(`Sending to other client(s):`);
DEBUG && console.log(message); DEBUG && console.log(message);
wss.clients.forEach((client) => { wss.clients.forEach((client) => {
@ -49,7 +49,7 @@ const Server = {
DEBUG && console.log(ws.id); DEBUG && console.log(ws.id);
G.removePlayer(ws.id); G.removePlayer(ws.id);
Server.messageOthers({ type: 'players', body: G.getPlayers() }); Server.messageOthers(ws, { type: 'players', body: G.getPlayers() });
}, },
onConnect: (ws, req) => { onConnect: (ws, req) => {
@ -75,21 +75,22 @@ const Server = {
DEBUG && console.log('Received message: '); DEBUG && console.log('Received message: ');
DEBUG && console.log(message); DEBUG && console.log(message);
if (!message.head) { if (!message.type) {
DEBUG && console.warn("Unprocessable message: ") DEBUG && console.warn("Unprocessable message: ")
DEBUG && console.warn(message); DEBUG && console.warn(message);
return; return;
} }
switch (message.head.type) { switch (message.type) {
case 'guess': case 'guess':
Server.messageAll({ type: 'guess', guess: 29, id: ws.id }); const santizedGuess = message.rawBody.moves * 1;
santizedGuess && Server.messageAll({ type: 'guess', guess: santizedGuess, id: ws.id });
break; break;
case 'robots': case 'robots':
Server.messageAll({ type: 'robots', body: G.getRobots()}); Server.messageAll({ type: 'robots', body: G.getRobots()});
break; break;
case 'walls': case 'skip':
Server.messageAll({ type: 'walls', body: G.getWalls()}); Server.messageAll({ type: 'start' });
break; break;
case 'start': case 'start':
Server.messageAll({ type: 'start' }); Server.messageAll({ type: 'start' });
@ -97,6 +98,9 @@ const Server = {
case 'stop': case 'stop':
Server.messageAll({ type: 'stop' }); Server.messageAll({ type: 'stop' });
break; break;
case 'walls':
Server.messageAll({ type: 'walls', body: G.getWalls()});
break;
default: default:
console.warn("Unknown message type: ", message.head.type) console.warn("Unknown message type: ", message.head.type)
} }

Loading…
Cancel
Save