dkforest

A forum and chat platform (onion)
git clone https://git.dasho.dev/n0tr1v/dkforest.git
Log | Files | Refs | LICENSE

commit 2b1b68247750ac863c92c555c40509441115addc
parent 7540b41528ce994d14f004c44678cecc59854853
Author: n0tr1v <n0tr1v@protonmail.com>
Date:   Thu, 15 Jun 2023 11:31:05 -0700

animation

Diffstat:
Mpkg/web/handlers/chess.go | 44+++++++++++++++++++++++++++++++++++++-------
Mpkg/web/handlers/interceptors/chess.go | 42++++++++++++++++++++++++++++++++++--------
2 files changed, 71 insertions(+), 15 deletions(-)

diff --git a/pkg/web/handlers/chess.go b/pkg/web/handlers/chess.go @@ -720,6 +720,7 @@ Loop: moves := game.Moves()[:moveIdx] lastMove := moves[len(moves)-1] piecesCache := interceptors.InitPiecesCache(moves) + piecesCache1 := g.PiecesCache1 squareMap := pos.Board().SquareMap() var bestMove *chess.Move @@ -753,7 +754,7 @@ Loop: renderChecks(&styles, checkIDStr) renderLastMove(&styles, *lastMove) renderBestMove(&styles, bestMove, isFlipped) - renderShowVisiblePieceInPosition(&styles, visiblePieces, squareMap, piecesCache, isFlipped) + renderShowVisiblePieceInPosition(&styles, &animationIdx, visiblePieces, squareMap, piecesCache, piecesCache1, isFlipped) send(styles.Build()) c.Response().Flush() @@ -841,15 +842,44 @@ Loop: return nil } -func renderShowVisiblePieceInPosition(styles *StylesBuilder, visiblePieces map[chess.Square]struct{}, squareMap map[chess.Square]chess.Piece, piecesCache map[chess.Square]string, isFlipped bool) { +var strToSquareMap = map[string]chess.Square{ + "a1": chess.A1, "a2": chess.A2, "a3": chess.A3, "a4": chess.A4, "a5": chess.A5, "a6": chess.A6, "a7": chess.A7, "a8": chess.A8, + "b1": chess.B1, "b2": chess.B2, "b3": chess.B3, "b4": chess.B4, "b5": chess.B5, "b6": chess.B6, "b7": chess.B7, "b8": chess.B8, + "c1": chess.C1, "c2": chess.C2, "c3": chess.C3, "c4": chess.C4, "c5": chess.C5, "c6": chess.C6, "c7": chess.C7, "c8": chess.C8, + "d1": chess.D1, "d2": chess.D2, "d3": chess.D3, "d4": chess.D4, "d5": chess.D5, "d6": chess.D6, "d7": chess.D7, "d8": chess.D8, + "e1": chess.E1, "e2": chess.E2, "e3": chess.E3, "e4": chess.E4, "e5": chess.E5, "e6": chess.E6, "e7": chess.E7, "e8": chess.E8, + "f1": chess.F1, "f2": chess.F2, "f3": chess.F3, "f4": chess.F4, "f5": chess.F5, "f6": chess.F6, "f7": chess.F7, "f8": chess.F8, + "g1": chess.G1, "g2": chess.G2, "g3": chess.G3, "g4": chess.G4, "g5": chess.G5, "g6": chess.G6, "g7": chess.G7, "g8": chess.G8, + "h1": chess.H1, "h2": chess.H2, "h3": chess.H3, "h4": chess.H4, "h5": chess.H5, "h6": chess.H6, "h7": chess.H7, "h8": chess.H8, +} + +func parseSq(s string) chess.Square { + return strToSquareMap[s] +} + +func renderShowVisiblePieceInPosition(styles *StylesBuilder, animationIdx *int, visiblePieces map[chess.Square]struct{}, squareMap map[chess.Square]chess.Piece, piecesCache map[chess.Square]string, piecesCache1 map[chess.Square]chess.Square, isFlipped bool) { + animate := func(s1, s2 chess.Square, id string, p chess.Piece) { + x1, y1 := squareCoord(s1, isFlipped) + x2, y2 := squareCoord(s2, isFlipped) + *animationIdx++ + styles.Appendf("#%s { display: block !important; "+ + "background-image: url(/public/img/chess/"+p.Color().String()+strings.ToUpper(p.Type().String())+".png) !important; }", id) + animationName := fmt.Sprintf("move_anim_%d", *animationIdx) + keyframes := "@keyframes %s {" + + "from { left: calc(%d*12.5%%); top: calc(%d*12.5%%); }" + + " to { left: calc(%d*12.5%%); top: calc(%d*12.5%%); } }" + styles.Appendf(keyframes, animationName, x1, y1, x2, y2) + styles.Appendf(`#%s { animation: %s %dms forwards; }`, id, animationName, 400) + } + for sq := range visiblePieces { sqID := piecesCache[sq] - x1, y1 := squareCoord(sq, isFlipped) + sqStr := strings.TrimPrefix(sqID, "piece_") + s2 := parseSq(sqStr) + pc1 := piecesCache1[s2] p := squareMap[sq] - styles.Appendf("#%s { display: block !important; "+ - "left: calc(%d*12.5%%) !important; top: calc(%d*12.5%%) !important; "+ - "background-image: url(/public/img/chess/"+p.Color().String()+strings.ToUpper(p.Type().String())+".png) !important; }", - sqID, x1, y1) + animate(pc1, sq, sqID, p) + piecesCache1[s2] = sq } } diff --git a/pkg/web/handlers/interceptors/chess.go b/pkg/web/handlers/interceptors/chess.go @@ -49,14 +49,15 @@ type ChessPlayer struct { } type ChessGame struct { - DbChessGame *database.ChessGame - Key string - Game *chess.Game - lastUpdated time.Time - Player1 *ChessPlayer - Player2 *ChessPlayer - CreatedAt time.Time - piecesCache map[chess.Square]string + DbChessGame *database.ChessGame + Key string + Game *chess.Game + lastUpdated time.Time + Player1 *ChessPlayer + Player2 *ChessPlayer + CreatedAt time.Time + piecesCache map[chess.Square]string + PiecesCache1 map[chess.Square]chess.Square } func newChessPlayer(player database.User) *ChessPlayer { @@ -82,6 +83,7 @@ func newChessGame(gameKey string, player1, player2 database.User, dbChessGame *d g.Player1 = newChessPlayer(player1) g.Player2 = newChessPlayer(player2) g.piecesCache = InitPiecesCache(g.Game.Moves()) + g.PiecesCache1 = InitPiecesCache1(g.Game.Moves()) return g } @@ -646,6 +648,7 @@ func (b *Chess) SendMove(gameKey string, userID database.UserID, g *ChessGame, c } piecesCache := g.piecesCache + piecesCache1 := g.PiecesCache1 currentPlayer := player1 opponentPlayer := player2 @@ -713,6 +716,7 @@ func (b *Chess) SendMove(gameKey string, userID database.UserID, g *ChessGame, c } updatePiecesCache(piecesCache, mov) + updatePiecesCache1(piecesCache1, mov) var checkIDStr string if mov.HasTag(chess.Check) { @@ -763,6 +767,7 @@ func (g *ChessGame) MakeMoves(movesStr string, db *database.DkfDB) { func (g *ChessGame) MoveStr(m string) { game := g.Game piecesCache := g.piecesCache + piecesCache1 := g.PiecesCache1 validMoves := game.Position().ValidMoves() var mov chess.Move for _, move := range validMoves { @@ -774,6 +779,7 @@ func (g *ChessGame) MoveStr(m string) { } updatePiecesCache(piecesCache, mov) + updatePiecesCache1(piecesCache1, mov) _ = game.MoveStr(m) } @@ -803,6 +809,22 @@ func InitPiecesCache(moves []*chess.Move) map[chess.Square]string { return piecesCache } +func InitPiecesCache1(moves []*chess.Move) map[chess.Square]chess.Square { + piecesCache1 := make(map[chess.Square]chess.Square) + game := chess.NewGame() + pos := game.Position() + for i := 0; i < 64; i++ { + sq := chess.Square(i) + if pos.Board().Piece(sq) != chess.NoPiece { + piecesCache1[sq] = sq + } + } + for _, m := range moves { + updatePiecesCache1(piecesCache1, *m) + } + return piecesCache1 +} + func updatePiecesCache(piecesCache map[chess.Square]string, mov chess.Move) { idStr1 := piecesCache[mov.S1()] delete(piecesCache, mov.S1()) @@ -828,6 +850,10 @@ func updatePiecesCache(piecesCache map[chess.Square]string, mov chess.Move) { } } +func updatePiecesCache1(piecesCache1 map[chess.Square]chess.Square, mov chess.Move) { + piecesCache1[mov.S1()] = mov.S2() +} + // Creates a map of pieces on the board and their count func pieceMap(board *chess.Board) map[chess.Piece]int { m := board.SquareMap()