Skip to content

feat: looping last-move replay animation on opponent's turn#170

Open
Copilot wants to merge 11 commits intomainfrom
copilot/add-move-animation-feature
Open

feat: looping last-move replay animation on opponent's turn#170
Copilot wants to merge 11 commits intomainfrom
copilot/add-move-animation-feature

Conversation

Copy link
Contributor

Copilot AI commented Mar 2, 2026

  • Add parseMovePairs to Utils.ts
  • Create src/Board/MoveAnimation.tsx with overlay component
  • Create src/Board/MoveAnimation.css with slide animation
  • Add position: relative to #board in Board.css
  • Update index.tsx with boardRef, movePairs memo, and <MoveAnimation>
  • Add pauses at source and destination, ease-in-out slide
  • Fix edge alignment: use .piece.ghost screen position for animation start and .piece.moved screen position for animation end — eliminates all geometric slot math and correctly handles any orientation, stacking, and CSS transforms automatically

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: ProLoser <67395+ProLoser@users.noreply.github.com>
Copilot AI changed the title [WIP] Add looping animation for friend's last move feat: looping last-move replay animation on opponent's turn Mar 2, 2026
@ProLoser ProLoser marked this pull request as ready for review March 2, 2026 17:28
@github-actions
Copy link

github-actions bot commented Mar 2, 2026

PR Preview Action v1.8.1

🚀 View preview at
https://ProLoser.github.io/PeaceInTheMiddleEast/preview/pr-170/

Built to branch gh-pages at 2026-03-14 20:14 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@ProLoser
Copy link
Owner

ProLoser commented Mar 8, 2026

@copilot add a small pause at the beginning and end of the animation as well as make the move speed up and slow down. The animation position is starting at the center of one point and ending after passing the center of the end point. Instead I want the piece to animate with the chip aligned correctly with the point and not offset 50%

…destination

Co-authored-by: ProLoser <67395+ProLoser@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot add a small pause at the beginning and end of the animation as well as make the move speed up and slow down. The animation position is starting at the center of one point and ending after pas...

Done in afe0e5c.

Pauses — keyframe now has a visible hold at both ends: fade-in (0→5%), pause at source (5→12%), ease-in-out slide (12→38%), pause at destination (38→45%), fade-out (45→50%).

Ease-in-outanimation-timing-function: ease-in-out is set on the 12% keyframe so the slide segment (12→38%) accelerates away from the source and decelerates into the destination.

Alignment — replaced the center-offset calculation (width/2 - pieceSize/2) with a getPiecePos helper that places the piece at the correct edge of the point:

  • Landscape: top-half points (0–11) → top edge of point; bottom-half points (12–23) → bottom edge
  • Portrait (writing-mode: tb): top-half → left edge; bottom-half → right edge

Bar pieces still use center positioning since bar pieces stack centrally.

@ProLoser
Copy link
Owner

ProLoser commented Mar 8, 2026

@copilot the animation is not going far enough across the bar and I want the animation direction to start half the width of the piece earlier and end half the width of the piece earlier than it's currently doing

…avel direction

Co-authored-by: ProLoser <67395+ProLoser@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot the animation is not going far enough across the bar and I want the animation direction to start half the width of the piece earlier and end half the width of the piece earlier than it's curr...

Fixed in 983fe8d. Both the source and destination positions are now shifted by pieceSize / 2 in the travel axis, so the piece is centered on the tip of the triangle rather than having its leading corner sit on the edge. In landscape this means:

  • Top-half points: y = rect.top − pieceSize/2 (piece straddles the tip, starting earlier)
  • Bottom-half points: y = rect.bottom − pieceSize/2 (same offset from the bottom tip)

The equal shift on both ends increases the total travel distance by one full piece width (half from the source, half from the destination), which gets the piece fully across the bar.

@ProLoser
Copy link
Owner

ProLoser commented Mar 8, 2026

@copilot the animation should always use the 7th spot on the point regardless of the number of pieces on it

Co-authored-by: ProLoser <67395+ProLoser@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot the animation should always use the 7th spot on the point regardless of the number of pieces on it

Done in f334b3f. The animation now always targets the 7th slot (index 6) on a point, independent of actual piece count:

  • Landscape top-half: y = rect.top + 6 × pieceSize
  • Landscape bottom-half: y = rect.bottom − 7 × pieceSize
  • Portrait mirrors the same on the x-axis

Bar pieces keep their center positioning since they stack centrally.

@ProLoser
Copy link
Owner

ProLoser commented Mar 8, 2026

@copilot I don't see animated pieces anymore

…s to match actual stacking direction

Co-authored-by: ProLoser <67395+ProLoser@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot I don't see animated pieces anymore

Fixed in 14ed7a8. The bug was in the portrait branch of getPiecePos: the isTopHalf x-formulas were swapped. In portrait (writing-mode: tb), top-half points (indices 0–11) sit on the right side of the board and their pieces stack right→left (base = rect.right), while bottom-half points sit on the left and stack left→right (base = rect.left). The previous code used rect.left + SLOT*pieceSize for top-half, which produced x=387 on a 390px-wide board with overlayWidth=352 — outside the overflow:hidden overlay and therefore invisible. Both portrait positions are now within bounds (x=147 and x=211 for a 390×844 viewport).

@ProLoser
Copy link
Owner

ProLoser commented Mar 8, 2026

Try to use the screen relative position of the ghost and highlight to calculate where the animation should start and end

@ProLoser
Copy link
Owner

ProLoser commented Mar 8, 2026

@copilot use the screen relative position of the ghost and highlight to calculate where the animation should start and end

Co-authored-by: ProLoser <67395+ProLoser@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot use the screen relative position of the ghost and highlight to calculate where the animation should start and end

Done in d530e29. computeSegments now queries .piece.ghost elements for the source position and .piece.moved elements for the destination — getBoundingClientRect() gives the exact rendered screen position, handling all orientations, stacking, and CSS transforms automatically. Multiple moves from/to the same point are tracked with a counter so the correct nth ghost/moved piece is used. The old geometric slot calculation is removed entirely.

Animation aligned on ghost/moved pieces

Red circle = animation start on the ghost piece; blue circle = animation end on the moved/highlighted piece — both are pixel-perfect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants