From 3df80ed59a0807f0676190c3bc33d6aad0ac5ad9 Mon Sep 17 00:00:00 2001 From: Jesse McDonald Date: Mon, 23 Mar 2020 01:53:53 -0500 Subject: [PATCH] add basic animations --- js/pacosako_ui.js | 85 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 20 deletions(-) diff --git a/js/pacosako_ui.js b/js/pacosako_ui.js index 21c2e2b..6268a6c 100644 --- a/js/pacosako_ui.js +++ b/js/pacosako_ui.js @@ -127,6 +127,7 @@ $(function (){ const code = pieceCode(side, type); const piece_id = 'cb_piece_' + code + '_' + suffix; const piece = $($('#' + piece_id)[0] || $('#cb_piece_' + code + ' img').clone()); + piece.stop(true); piece.attr('id', piece_id); piece.removeClass('cb-selected'); piece.removeAttr('style'); @@ -145,7 +146,8 @@ $(function (){ return piece; } - function renderBoard() { + function renderBoard(animate) { + $('#cb_board .cb-piece').stop(true); $('#cb_board .cb-piece').off('click.select'); $('#cb_board .cb-piece').off('click.unselect'); $('#cb_board .cb-square').off('click.destination'); @@ -184,30 +186,66 @@ $(function (){ if (lastMove.to) { cbSquare(lastMove.to).addClass('cb-end'); } + + if (lastMove.from && lastMove.to && animate) { + let pieces = cbSquare(lastMove.to).find('.cb-piece'); + if (!lastMove.alongside) { + pieces = pieces.filter(lastMove.side === PS.LIGHT ? '.cb-lt-piece' : '.cb-dk-piece'); + } + if (pieces.length > 0) { + const fromRect = cbSquare(lastMove.from)[0].getBoundingClientRect(); + const toRect = cbSquare(lastMove.to)[0].getBoundingClientRect(); + const movedDown = toRect.top - fromRect.top; + const movedRight = toRect.left - fromRect.left; + for (const domPiece of pieces) { + const piece = $(domPiece); + const originalTop = parseFloat(piece.css('top')); + const originalLeft = parseFloat(piece.css('left')); + const originalStyle = piece.attr('style') || null; + piece.css({ + 'z-index': 100, + 'top': originalTop - movedDown, + 'left': originalLeft - movedRight, + }).animate({ + 'top': originalTop, + 'left': originalLeft, + }, { + always: function() { + piece.attr('style', originalStyle); + }, + }); + } + } + } } const liveView = !game.canRedo; const playing = game.status === PS.PLAYING; - /* only enable selection / drag-and-drop in the live view */ - if (liveView && playing) { - const phantom = board.phantom; - if (phantom) { - const piece = placePiece(PS.PHANTOM, phantom.side, phantom.type, 'ph'); - cbSquare(PS.PHANTOM).appendTo(cbSquare(phantom.from)); + const phantom = board.phantom; + if (phantom) { + const piece = placePiece(PS.PHANTOM, phantom.side, phantom.type, 'ph'); + cbSquare(PS.PHANTOM).appendTo(cbSquare(phantom.from)); + + if (liveView && playing) { piece.draggable('enable'); piece.addClass('cb-selected'); pieceStartMove(piece, 'click'); - } else if (game.status === PS.PLAYING) { - const clss = game.player === PS.LIGHT ? '.cb-lt-piece' : '.cb-dk-piece'; - const pieces = $('#cb_board ' + clss) - pieces.on('click.select', pieceClickSelect); - pieces.draggable('enable'); } + } else if (liveView && playing) { + const clss = game.player === PS.LIGHT ? '.cb-lt-piece' : '.cb-dk-piece'; + const pieces = $('#cb_board ' + clss) + pieces.on('click.select', pieceClickSelect); + pieces.draggable('enable'); } let msg = ''; let winner = game.winner; + + if (!liveView) { + msg += '(Move ' + String(game.moves.length) + ' of ' + String(currentGame.moves.length) + ') '; + } + if (winner) { if (lastMove && lastMove.resign) { msg += (lastMove.side === PS.LIGHT ? 'Light' : 'Dark') + ' player resigned. '; @@ -240,13 +278,13 @@ $(function (){ } } - function setCurrentBoard(game) { + function setCurrentBoard(game, animate) { currentGame = game; /* navigation should not include the redo stack */ visibleGame = new PS.Game(game); visibleGame.clearRedo(); - renderBoard(); + renderBoard(animate); const moves = game.moves; @@ -361,6 +399,13 @@ $(function (){ if (d && d.board) { try { const moves = JSON.parse(d.board); + const oldState = { past: currentGame.moves, future: currentGame.redoMoves }; + + if (deepEqual(moves, oldState)) { + /* we already have this */ + return; + } + debug('got board', moves); const newGame = new PS.Game(); @@ -379,7 +424,7 @@ $(function (){ newGame.undo(); } - setCurrentBoard(newGame); + setCurrentBoard(newGame, moves.past.length > currentGame.moves.length); } catch (err) { debug('Error replaying board state', err); } @@ -579,7 +624,7 @@ $(function (){ if (currentGame.canRedo) { currentGame.redo(); $('#cb_board').data('last_state', currentGame.moves); - setCurrentBoard(currentGame); + setCurrentBoard(currentGame, true); putState(); } }); @@ -627,7 +672,7 @@ $(function (){ if (visibleGame.canRedo) { visibleGame.redo(); } - renderBoard(); + renderBoard(true); }); $('#cb_nav_next_turn').on('click', function(){ @@ -638,14 +683,14 @@ $(function (){ break; } } - renderBoard(); + renderBoard(true); }); $('#cb_nav_last').on('click', function(){ while (visibleGame.canRedo) { visibleGame.redo(); } - renderBoard(); + renderBoard(true); }); $('#cb_select_game').on('change', function(){ @@ -692,7 +737,7 @@ $(function (){ const lightName = shortenName(String(d.lightName || 'Light')); const darkName = shortenName(String(d.darkName || 'Dark')); const moves = !d.moves ? '' : - (', ' + d.moves + (d.moves === 1 ? ' move' : ' moves')); + (', ' + d.moves + (d.moves === 1 ? ' turn' : ' turns')); let opt = $('#cb_game_' + key);