diff --git a/src/game.css b/src/game.css index f8425dc..49ac1d0 100755 --- a/src/game.css +++ b/src/game.css @@ -37,13 +37,28 @@ ========================================================= */ .snake-cell.snake-head { background-color: var(--accent, #ffc777); - border-radius: 6px 6px 2px 2px; box-shadow: 0 0 8px color-mix(in srgb, var(--accent, #ffc777) 70%, transparent), inset 0 0 4px color-mix(in srgb, var(--accent, #ffc777) 90%, transparent); position: relative; } +.snake-cell.snake-head.dir-up { + border-radius: 6px 6px 2px 2px; +} + +.snake-cell.snake-head.dir-down { + border-radius: 2px 2px 6px 6px; +} + +.snake-cell.snake-head.dir-left { + border-radius: 6px 2px 2px 6px; +} + +.snake-cell.snake-head.dir-right { + border-radius: 2px 6px 6px 2px; +} + .snake-cell.snake-head::after { content: ""; position: absolute; @@ -65,7 +80,22 @@ .snake-cell.snake-tail { background-color: var(--accent, #ffc777); opacity: 0.5; - border-radius: 2px 2px 6px 6px; box-shadow: 0 0 4px color-mix(in srgb, var(--accent, #ffc777) 40%, transparent); } +.snake-cell.snake-tail.dir-up { + border-radius: 6px 6px 2px 2px; +} + +.snake-cell.snake-tail.dir-down { + border-radius: 2px 2px 6px 6px; +} + +.snake-cell.snake-tail.dir-left { + border-radius: 6px 2px 2px 6px; +} + +.snake-cell.snake-tail.dir-right { + border-radius: 2px 6px 6px 2px; +} + diff --git a/src/useGame/useSnake.ts b/src/useGame/useSnake.ts index 8cbd92d..f0554c5 100755 --- a/src/useGame/useSnake.ts +++ b/src/useGame/useSnake.ts @@ -44,24 +44,55 @@ export function useSnake( const container = containerRef.current; if (!container) return; - container.querySelectorAll(".snake-head, .snake-body, .snake-tail").forEach((el) => { - el.classList.remove("snake-head", "snake-body", "snake-tail"); - }); - + const dir = directionRef.current; + const newPositions = new Set(); + + // First, apply new positions and track them body.forEach((segment, idx) => { + const posKey = `${segment.r},${segment.c}`; + newPositions.add(posKey); + const cell = container.querySelector( `.snake-cell[data-r="${segment.r}"][data-c="${segment.c}"]` ); if (cell) { + cell.className = "snake-cell"; if (idx === 0) { - cell.classList.add("snake-head"); + cell.classList.add("snake-head", `dir-${dir}`); } else if (idx === body.length - 1) { - cell.classList.add("snake-tail"); + const tailDir = getTailDirection(body); + cell.classList.add("snake-tail", `dir-${tailDir}`); } else { cell.classList.add("snake-body"); } } }); + + // Then clear old positions not in the new body + const allSnakeCells = container.querySelectorAll(".snake-head, .snake-body, .snake-tail"); + allSnakeCells.forEach((el) => { + const r = el.getAttribute("data-r"); + const c = el.getAttribute("data-c"); + const posKey = `${r},${c}`; + if (!newPositions.has(posKey)) { + el.className = "snake-cell"; + } + }); + }; + + const getTailDirection = (body: SnakeBody): Direction => { + if (body.length < 2) return directionRef.current; + + const tail = body[body.length - 1]; + const beforeTail = body[body.length - 2]; + + // Tail points away from beforeTail + if (tail.r < beforeTail.r) return "up"; + if (tail.r > beforeTail.r) return "down"; + if (tail.c < beforeTail.c) return "left"; + if (tail.c > beforeTail.c) return "right"; + + return directionRef.current; }; const changeDirection = (newDirection: Direction) => {