From: Benjamin Auder Date: Sat, 21 Mar 2020 10:49:53 +0000 (+0100) Subject: Revert to news button in red, no blinking. Add autoplay option X-Git-Url: https://git.auder.net/game/current/doc/DESCRIPTION?a=commitdiff_plain;h=54ec15ebc0cc874cb40307d0d674964b2f0e11a4;p=vchess.git Revert to news button in red, no blinking. Add autoplay option --- diff --git a/TODO b/TODO index 77f3f2d0..4a638435 100644 --- a/TODO +++ b/TODO @@ -13,16 +13,6 @@ Goal is still checkmate. Take(a)n(d)make : if capture a piece, take its power for the last of the turn and make a move like it. If a pawn taken: direction of the capturer. -"Ball" Chess: 9x9 board, ball on center square. 2 queens ? -To take the ball when it's free you need to capture it. -To take the ball when it's used, u need to take the piece. -Goal: bring ball to final rank. -Possibles passes : soit à une pièce, soit sur une case. - --> remplace un déplacement de pièce. Par exemple pion a2 passe à cavalier a4 = 1 coup. - --> selon le mode de déplacement standard (donc tout droit pour les pions) -Pas de notion d'échec ou de mat (?) -Si une pièce est mat elle donne le ballon (?) - Maxima, Interweave, Roccoco Synchrone Chess: allow to anticipate en-passant capture as well :) diff --git a/client/public/images/icons/SOURCE b/client/public/images/icons/SOURCE index 88c25021..4d22cabf 100644 --- a/client/public/images/icons/SOURCE +++ b/client/public/images/icons/SOURCE @@ -15,3 +15,4 @@ https://www.flaticon.com/free-icon/clear_565313?term=delete&page=1&position=33 https://www.flaticon.com/free-icon/clear_1632708?term=delete&page=1&position=3 https://iconscout.com/icon/discord-1 https://www.onlinewebfonts.com/icon/154680 +https://www.flaticon.com/free-icon/bleach_481058?term=triangle&page=1&position=2 diff --git a/client/public/images/icons/autoplay.svg b/client/public/images/icons/autoplay.svg new file mode 100644 index 00000000..433826db --- /dev/null +++ b/client/public/images/icons/autoplay.svg @@ -0,0 +1,100 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/client/src/App.vue b/client/src/App.vue index 15e2f101..25ec25eb 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -280,19 +280,10 @@ footer padding: 5px 0 .menuitem.somenews - animation: blinkNews 1s infinite; color: red &:link, &:visited, &:hover color: red -@keyframes blinkNews - 0%, 49% - background-color: yellow - padding: 3px - 50%, 100% - background-color: grey - padding: 3px - // Styles for diagrams and board (partial). // TODO: where to put that ? diff --git a/client/src/components/BaseGame.vue b/client/src/components/BaseGame.vue index e86c551e..cd71fcb6 100644 --- a/client/src/components/BaseGame.vue +++ b/client/src/components/BaseGame.vue @@ -30,6 +30,11 @@ div#baseGame img.inline(src="/images/icons/play_rev.svg") button(v-if="canFlip" @click="flip()") img.inline(src="/images/icons/flip.svg") + button( + @click="runAutoplay()" + :class="{'in-autoplay': autoplay}" + ) + img.inline(src="/images/icons/autoplay.svg") button(@click="play()") img.inline(src="/images/icons/play.svg") button(@click="gotoEnd()") @@ -83,6 +88,8 @@ export default { firstMoveNumber: 0, //for printing incheck: [], //for Board inMultimove: false, + autoplay: false, + autoplayLoop: null, inPlay: false, stackToPlay: [] }; @@ -135,6 +142,9 @@ export default { document.getElementById("eogDiv") .addEventListener("click", processModalClick); }, + beforeDestroy: function() { + if (!!this.autoplayLoop) clearInterval(this.autoplayLoop); + }, methods: { focusBg: function() { document.getElementById("baseGame").focus(); @@ -263,6 +273,29 @@ export default { this.endgameMessage = message; document.getElementById("modalEog").checked = true; }, + runAutoplay: function() { + const infinitePlay = () => { + if (this.cursor == this.moves.length - 1) { + clearInterval(this.autoplayLoop); + this.autoplayLoop = null; + this.autoplay = false; + return; + } + if (this.inPlay || this.inMultimove) + // Wait next tick + return; + this.play(); + }; + if (this.autoplay) { + this.autoplay = false; + clearInterval(this.autoplayLoop); + this.autoplayLoop = null; + } else { + this.autoplay = true; + infinitePlay(); + this.autoplayLoop = setInterval(infinitePlay, 1500); + } + }, // Animate an elementary move animateMove: function(move, callback) { let startSquare = document.getElementById(getSquareId(move.start)); @@ -325,12 +358,15 @@ export default { this.vr.play(smove); this.lastMove = smove; if (!this.inMultimove) { - if (this.cursor < this.moves.length - 1) - this.moves = this.moves.slice(0, this.cursor + 1); - this.moves.push(smove); + // Condition is "!navigate" but we mean "!this.autoplay" + if (!navigate) { + if (this.cursor < this.moves.length - 1) + this.moves = this.moves.slice(0, this.cursor + 1); + this.moves.push(smove); + } this.inMultimove = true; //potentially this.cursor++; - } else { + } else if (!navigate) { // Already in the middle of a multi-move const L = this.moves.length; if (!Array.isArray(this.moves[L-1])) @@ -340,7 +376,10 @@ export default { } }; const playMove = () => { - const animate = (V.ShowMoves == "all" && !!received); + const animate = ( + V.ShowMoves == "all" && + (this.autoplay || !!received) + ); if (!Array.isArray(move)) move = [move]; let moveIdx = 0; let self = this; @@ -387,7 +426,7 @@ export default { this.emitFenIfAnalyze(); this.inMultimove = false; this.score = computeScore(); - if (this.game.mode != "analyze") { + if (this.game.mode != "analyze" && !navigate) { if (!noemit) { // Post-processing (e.g. computer play). const L = this.moves.length; @@ -408,17 +447,19 @@ export default { // The move to navigate to is necessarily full: if (this.cursor == this.moves.length - 1) return; //no more moves move = this.moves[this.cursor + 1]; - // Just play the move: - if (!Array.isArray(move)) move = [move]; - for (let i=0; i < move.length; i++) this.vr.play(move[i]); - if (!light) { - this.lastMove = move[move.length-1]; - this.incheck = this.vr.getCheckSquares(this.vr.turn); - this.score = computeScore(); - this.emitFenIfAnalyze(); + if (!this.autoplay) { + // Just play the move: + if (!Array.isArray(move)) move = [move]; + for (let i=0; i < move.length; i++) this.vr.play(move[i]); + if (!light) { + this.lastMove = move[move.length-1]; + this.incheck = this.vr.getCheckSquares(this.vr.turn); + this.score = computeScore(); + this.emitFenIfAnalyze(); + } + this.cursor++; + return; } - this.cursor++; - return; } // Forbid playing outside analyze mode, except if move is received. // Sufficient condition because Board already knows which turn it is. @@ -541,8 +582,11 @@ export default { padding-top: 5px padding-bottom: 5px +.in-autoplay + background-color: #FACF8C + img.inline - height: 24px + height: 22px padding-top: 5px @media screen and (max-width: 767px) height: 18px diff --git a/client/src/components/MoveList.vue b/client/src/components/MoveList.vue index c4e19982..140b71cf 100644 --- a/client/src/components/MoveList.vue +++ b/client/src/components/MoveList.vue @@ -193,7 +193,7 @@ export default { padding: 5px img.inline - height: 24px + height: 22px @media screen and (max-width: 767px) height: 18px diff --git a/client/src/views/Game.vue b/client/src/views/Game.vue index 6339a3ce..ddbd3309 100644 --- a/client/src/views/Game.vue +++ b/client/src/views/Game.vue @@ -1409,7 +1409,7 @@ button margin: 0 display: inline-flex img - height: 24px + height: 22px display: flex @media screen and (max-width: 767px) height: 18px