Commit ae9d5065 authored by Mahmoud Aglan's avatar Mahmoud Aglan

feat(juice): chess capture explosions, ludo dice slam + star burst on 6

Chess juice:
- Capture: particle burst at capture square + board shake + haptic
- Check: board shake + haptic medium
- Checkmate: heavy shake + screen flash + haptic heavy

Ludo juice:
- Dice roll: slam-in with 1.6x overshoot + board shake + haptic
- Roll 6: golden star burst around dice
- Capture: confetti + heavy shake + haptic heavy
- Piece finish: star burst + haptic success
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent ee14c2cd
......@@ -7,6 +7,7 @@ import { t } from '../../../core/i18n.js';
import { ChessBoard } from '../canvas/board.js';
import * as engine from '../logic/engine.js';
import { ChessClock, parseTimeControl } from '../logic/clock.js';
import * as juice from '../../../core/juice.js';
let board, clock, gameState;
......@@ -193,17 +194,34 @@ function executeMove(el, from, to, promotion) {
board.setPosition(engine.fen());
board.setLastMove(from, to);
// Sound
if (m.san.includes('#')) audio.play('gameOver', 'game');
else if (m.san.includes('+')) audio.play('check', 'game');
else if (m.captured) audio.play('capture', 'game');
else if (m.san === 'O-O' || m.san === 'O-O-O') audio.play('castle', 'game');
else audio.play('move', 'game');
// Sound + Juice
if (m.san.includes('#')) {
audio.play('gameOver', 'game');
juice.shake(el, 6, 400);
juice.flash('#fff', 200);
juice.hapticHeavy();
} else if (m.san.includes('+')) {
audio.play('check', 'game');
juice.shake(el, 3, 200);
juice.hapticMedium();
} else if (m.captured) {
audio.play('capture', 'game');
juice.shake(el, 2, 150);
juice.hapticLight();
// Particle burst at capture square
const captureXY = board.squareToXY(to);
const boardRect = board.canvas.getBoundingClientRect();
juice.burst(boardRect.left + captureXY.x + board.squareSize/2, boardRect.top + captureXY.y + board.squareSize/2,
{ count: 8, colors: ['#EF4444', '#F97316', '#FBBF24'], size: 6, spread: 60, duration: 500 });
} else if (m.san === 'O-O' || m.san === 'O-O-O') {
audio.play('castle', 'game');
juice.hapticLight();
} else {
audio.play('move', 'game');
}
// Captured pieces
if (m.captured) {
const capturedPiece = m.color === gameState.playerColor
? m.captured : m.captured.toUpperCase ? m.captured : m.captured;
if (m.color === gameState.playerColor) {
gameState.capturedByPlayer.push(m.captured);
} else {
......
......@@ -5,6 +5,7 @@ import * as store from '../../../core/store.js';
import { t } from '../../../core/i18n.js';
import { createCanvas, clear } from '../../../core/canvas.js';
import * as rules from '../logic/rules.js';
import * as juice from '../../../core/juice.js';
let game, validMoves, canvasCtx, canvasEl, boardSize;
......@@ -57,10 +58,16 @@ function handleRoll(el) {
game.diceValue = dice;
game.rolled = true;
audio.play('dice', 'game');
juice.hapticMedium();
const diceEl = el.querySelector('#dice-display');
diceEl.textContent = dice;
diceEl.style.color = '#E4AC38';
juice.slamIn(diceEl, { scale: 1.6, duration: 350 });
juice.shake(el.querySelector('#ludo-board'), 2, 150);
if (dice === 6) {
juice.starBurst(diceEl.getBoundingClientRect().left + 28, diceEl.getBoundingClientRect().top + 28, 5);
}
validMoves = rules.getValidMoves(game, 0, dice);
......@@ -93,7 +100,18 @@ function handleRoll(el) {
function applyPlayerMove(el, move) {
rules.applyMove(game, 0, move);
game.rolled = false;
audio.play(move.type === 'capture' ? 'capture' : 'move', 'game');
if (move.type === 'capture') {
audio.play('capture', 'game');
juice.shake(el, 4, 250);
juice.hapticHeavy();
juice.confetti(window.innerWidth / 2, window.innerHeight / 2, 15);
} else if (move.type === 'finish') {
audio.play('win', 'reward');
juice.starBurst(window.innerWidth / 2, window.innerHeight / 2, 8);
juice.hapticSuccess();
} else {
audio.play('move', 'game');
}
if (game.gameOver || game.players[0].finished) { endGame(el); return; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment