Win stack replay loop.

master
Ben Burlingham 5 years ago
parent fa66d296fc
commit a7a26a9837
  1. 4
      README.txt
  2. 21
      client/controls.js
  3. 43
      client/grid.js
  4. 2
      index.html
  5. 22
      server/ricochet.js
  6. 3
      style/controls.css
  7. 4
      style/grid.css

@ -13,11 +13,9 @@ A victory state can be stored by taking a snapshot of the current stack.
Icons from [https://game-icons.net](https://game-icons.net)
## TODO
- replay stack
- chat box
- walls and winstate algorithm
- shuffle colors (easy)
- tutorial (easy)
- tutorial
# Final install
- move websocket server to /core

21
client/controls.js vendored

@ -12,6 +12,7 @@ const Controls = function() {
document.addEventListener('L-complete', this.msgComplete.bind(this));
document.addEventListener('L-join', this.msgJoin.bind(this));
document.addEventListener('L-newround', this.msgNewRound.bind(this));
document.addEventListener('L-replay-complete', this.msgReplayComplete.bind(this));
document.addEventListener('L-skip', this.msgSkip.bind(this));
document.addEventListener('L-stack', this.msgStack.bind(this));
@ -32,8 +33,6 @@ const Controls = function() {
document.getElementById('controls-options-walls').addEventListener('click', this.onClickOptionsWalls.bind(this));
document.getElementById('controls-countdown-skip').addEventListener('click', this.onClickCountdownSkip.bind(this));
document.getElementById('controls-win-replay').addEventListener('click', this.onClickWinReplay.bind(this));
document.getElementById('controls-win-next').addEventListener('click', this.onClickWinNext.bind(this));
this.setState('CONNECTING');
@ -189,12 +188,18 @@ Controls.prototype.msgState = function(evt) {
};
Controls.prototype.msgWin = function(evt) {
document.getElementById('controls-win-message').innerHTML = `Congratulations ${this.names[evt.detail.body.id]} !`;
document.getElementById('controls-win-message').innerHTML = `Congratulations ${this.names[evt.detail.player_id]} !`;
document.getElementById('controls-win-count').innerHTML = evt.detail.body.moveCount;
};
Controls.prototype.msgNewRound = function() {
this.winningMoveCount = Infinite;
this.winningMoveCount = Infinity;
document.getElementById('controls-win-next').style.display = 'none';
// SHOW ARROWS IN GRID
};
Controls.prototype.msgReplayComplete = function() {
document.getElementById('controls-win-next').style.display = 'block';
};
//===== Click handlers
@ -232,18 +237,12 @@ Controls.prototype.onClickMovesUndo = function() {
this.dispatch('L-undo');
};
// Countdown block
// Countdown/win block
Controls.prototype.onClickCountdownSkip = function() {
this.dispatch('L-skip');
};
// Win block
Controls.prototype.onClickWinReplay = function() {
// this.dispatch('L-skip');
alert('win replay')
}
Controls.prototype.onClickWinNext = function() {
this.dispatch('L-newround');
};

@ -8,16 +8,19 @@ const Grid = function() {
this.shadows = [];
this.walls = [];
this.objective = {};
this.timers = {};
this.squaresPerSide = 20;
this.squareSideLength = 0;
document.addEventListener('L-newround', this.msgNewRound.bind(this));
document.addEventListener('L-stack', this.msgStack.bind(this));
document.addEventListener('L-shadows', this.msgShadows.bind(this));
document.addEventListener('G-robots', this.msgRobots.bind(this));
document.addEventListener('G-walls', this.msgWalls.bind(this));
document.addEventListener('G-objective', this.msgObjective.bind(this));
document.addEventListener('G-win', this.msgWin.bind(this));
window.addEventListener('resize', this.debounce(this.onResize.bind(this), 500));
@ -336,6 +339,37 @@ Grid.prototype.checkObjective = function({ id, i, j }) {
document.dispatchEvent(evtSolve);
};
Grid.prototype.replayStack = function(stack) {
// All to initial positions
for (let i = 0; i < this.robots.length; i++) {
this.replayMove(stack[i]);
document.getElementById(`arrows-${stack[i].id}`).style.display = 'none';
}
function replayRemaining(remainingStack) {
if (remainingStack.length > 0) {
this.replayMove(remainingStack[0]);
this.timers.replay = setTimeout(replayRemaining.bind(this, remainingStack.slice(1)), 750);
}
else {
const evtSolve = new Event('L-replay-complete');
document.dispatchEvent(evtSolve);
this.timers.replay = setTimeout(this.replayStack.bind(this, stack), 750);
}
}
this.timers.replay = setTimeout(replayRemaining.bind(this, stack.slice(this.robots.length)), 750)
};
Grid.prototype.replayMove = function({ id, i, j }) {
const robot = document.getElementById(`robot-${id}`);
const s = this.squareSideLength;
robot.style.left = `${i * s}px`;
robot.style.top = `${j * s}px`;
};
//===== DOM event handlers
Grid.prototype.onArrowClick = function(evt) {
@ -398,6 +432,11 @@ Grid.prototype.debounce = function(fn, ms) {
//===== Message handlers
Grid.prototype.msgNewRound = function() {
this.robots.forEach(({ id }) => document.getElementById(`arrows-${id}`).style.display = 'block');
clearTimeout(this.timers.replay);
};
Grid.prototype.msgRobots = function(evt) {
// Do not assign position or redraw here: movements are fully managed using the stack.
this.colors = {};
@ -442,3 +481,7 @@ Grid.prototype.msgObjective = function(evt) {
this.objective = evt.detail.body;
this.drawObjective();
};
Grid.prototype.msgWin = function(evt) {
this.replayStack(evt.detail.body.stack)
};

@ -63,8 +63,6 @@
<div id='controls-win-count'></div>
<div class='controls-button' id='controls-win-replay'>Replay</div>
<div class='controls-button' id='controls-win-next'>Start next round</div>
</div>

@ -33,8 +33,9 @@ const Ricochet = function({ messenger }) {
// Reference lookups
this.robotIds = Array.from(Array(5).keys()).map(_ => uuid.v4());
const shuffledColors = this.shuffle(COLORS);
this.colors = this.robotIds.reduce((acc, id, i) => {
acc[id] = COLORS[i];
acc[id] = shuffledColors[i];
return acc;
}, {});
@ -360,6 +361,23 @@ Ricochet.prototype.sanitizeId = function(id) {
return id.replace(/[^0-9a-zA-Z\-]/g, '');
};
Ricochet.prototype.shuffle = function(arr) {
const result = [];
let CONTROL_COUNTER = 0;
while (arr.length && CONTROL_COUNTER < 50) {
const x = Math.floor(Math.random() * arr.length);
result.push(arr[x]);
arr.splice(x, 1);
}
if (CONTROL_COUNTER > 39) {
console.log(`==================\n\nCRITICAL ERROR!\n\shuffle()() while() short-circuited!\n\n==================`);
}
return result;
};
Ricochet.prototype.onCountdownComplete = function() {
clearTimeout(this.countdownTimer);
@ -382,7 +400,7 @@ Ricochet.prototype.getCountdownStateBody = function() {
Ricochet.prototype.getWinStateBody = function() {
return {
moveCount: this.winningStack.length - this.robots.length,
id: this.winningPlayerId,
player_id: this.winningPlayerId,
stack: this.winningStack
};
};

@ -175,7 +175,8 @@
margin-top: -12px;
}
#controls-win-replay {
#controls-win-next {
display: none;
}
/*===== FOOTER BLOCK =====*/

@ -25,6 +25,7 @@
height: 8px;
margin-top: -4px;
position: absolute;
z-index: 3;
}
.content-wall-y {
@ -32,6 +33,7 @@
margin-left: -4px;
position: absolute;
width: 8px;
z-index: 3;
}
.content-robot {
@ -57,7 +59,7 @@
.content-arrows {
position: absolute;
transition: left 0.4s cubic-bezier(0,1,.5,1), top 0.4s cubic-bezier(0,1,.5,1);
z-index: 5;
z-index: 4;
}
.content-arrow {

Loading…
Cancel
Save