Skip to content

Commit 5190ecc

Browse files
feat: add 3D Tic-Tac-Toe board and toggle functionality
- Introduced TicTacToeBoard3D component for a 3D game experience. - Updated TicTacToePage to include a toggle for 3D mode, saving preference in localStorage. - Enhanced GameControls to support toggling between 2D and 3D views. - Updated package.json dependencies for React Three Fiber and related libraries. - Improved UI feedback for AI turns in the 3D board.
1 parent 18accee commit 5190ecc

File tree

7 files changed

+1242
-11
lines changed

7 files changed

+1242
-11
lines changed
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
# 3D Tic Tac Toe Implementation Plan
2+
3+
## Overview
4+
This plan introduces a 3D visualization for Tic Tac Toe using `react-three-fiber`. Users can toggle between the classic 2D grid and an interactive 3D scene where they can rotate the board, see hover effects, and enjoy celebratory effects when winning.
5+
6+
## Implementation Steps
7+
8+
### 1. Install 3D Dependencies
9+
Install the latest versions of required 3D libraries in the `web` workspace:
10+
11+
```bash
12+
cd web
13+
npm install three@^0.170.0 @react-three/fiber@^9.0.0 @react-three/drei@^10.0.0 @react-three/cannon@^6.6.0
14+
```
15+
16+
**Dependencies:**
17+
- `three` - Core Three.js library for 3D rendering
18+
- `@react-three/fiber` - React renderer for Three.js
19+
- `@react-three/drei` - Helper components and abstractions for react-three-fiber
20+
- `@react-three/cannon` - Physics and effects for celebratory animations
21+
22+
---
23+
24+
### 2. Create 3D Board Component
25+
**File:** `web/src/components/games/TicTacToeBoard3D.tsx`
26+
27+
**Requirements:**
28+
- Implement the `TicTacToeBoardProps` interface from `TicTacToeBoard.tsx`
29+
- Accept the same props: `gameState`, `onMove`, `disabled`
30+
- Maintain functional parity with the 2D board component
31+
32+
**Component Structure:**
33+
```typescript
34+
interface TicTacToeBoardProps {
35+
gameState: TicTacToeGameState
36+
onMove: (move: TicTacToeMove) => void
37+
disabled?: boolean
38+
}
39+
40+
export function TicTacToeBoard3D({ gameState, onMove, disabled }: TicTacToeBoardProps) {
41+
// Implementation
42+
}
43+
```
44+
45+
---
46+
47+
### 3. Implement 3D Scene
48+
**Canvas Setup:**
49+
- Use `<Canvas>` component from `@react-three/fiber`
50+
- Configure `OrbitControls` from `@react-three/drei` for rotation and zoom
51+
- Set isometric camera position: `position={[5, 5, 5]}` with `lookAt={[0, 0, 0]}`
52+
- Allow user to rotate and zoom but maintain clear view of the board
53+
54+
**3x3 Grid Implementation:**
55+
- Create 9 interactive mesh cells positioned in a 3x3 grid
56+
- Each cell should be a clickable 3D object
57+
- Use raycasting for click detection via `onClick` handlers
58+
- Implement hover effects via `onPointerOver` and `onPointerOut`
59+
60+
**Interaction Model:**
61+
- Raycasting automatically handled by react-three-fiber's event system
62+
- Each valid cell should respond to:
63+
- `onClick` - trigger `onMove({ row, col })`
64+
- `onPointerOver` - show hover highlight
65+
- `onPointerOut` - remove hover highlight
66+
- Disable interactions when `disabled={true}` or cell is occupied
67+
68+
---
69+
70+
### 4. Add Visual Feedback
71+
72+
**Hover States:**
73+
- Highlight valid cells on hover (e.g., subtle glow or color change)
74+
- Only show hover effect on empty cells when it's the player's turn
75+
- No hover effect during AI turns or on occupied cells
76+
77+
**Disabled State During AI Turns:**
78+
- Show overlay or dim the board when `disabled={true}`
79+
- Display "AI's Turn" indicator
80+
- Prevent all click interactions
81+
82+
**Turn Indicator:**
83+
- Display current turn above the board
84+
- Options:
85+
- Use `<Html>` component from `@react-three/drei` for HTML overlay
86+
- OR use 3D text mesh
87+
- Show "Your turn (X)" or "AI thinking... (O)"
88+
89+
**Win Celebration Effect:**
90+
- Trigger confetti/particle effect when game is won
91+
- Use `<Sparkles>` from `@react-three/drei` or similar
92+
- Consider using `@react-three/cannon` for more dynamic effects
93+
- Effect should be visible but not obstruct the final board state
94+
95+
---
96+
97+
### 5. Update GameControls Component
98+
**File:** `web/src/components/ui/GameControls.tsx`
99+
100+
**Changes:**
101+
- Add new optional prop: `onViewToggle?: () => void`
102+
- Add new optional prop: `is3DMode?: boolean`
103+
- Render toggle button when `onViewToggle` is provided
104+
- Button text should indicate current mode: "Switch to 3D View" or "Switch to 2D Grid"
105+
106+
**Example Button:**
107+
```tsx
108+
{onViewToggle && (
109+
<button onClick={onViewToggle}>
110+
{is3DMode ? '2D Grid' : '3D View'}
111+
</button>
112+
)}
113+
```
114+
115+
**Placement:**
116+
- Add button to the controls panel alongside "New Game" and "Delete" buttons
117+
- Maintain consistent styling with existing buttons
118+
119+
---
120+
121+
### 6. Update Tic Tac Toe Page
122+
**File:** `web/src/app/games/tic-tac-toe/page.tsx`
123+
124+
**State Management:**
125+
- Add new state: `const [is3DMode, setIs3DMode] = useState<boolean>(false)`
126+
- Initialize from localStorage on mount
127+
- Persist to localStorage on toggle
128+
129+
**localStorage Integration:**
130+
```typescript
131+
// On mount
132+
useEffect(() => {
133+
const saved = localStorage.getItem('ticTacToe_view3D')
134+
if (saved !== null) {
135+
setIs3DMode(saved === 'true')
136+
}
137+
}, [])
138+
139+
// On toggle
140+
const handleViewToggle = () => {
141+
setIs3DMode(prev => {
142+
const newValue = !prev
143+
localStorage.setItem('ticTacToe_view3D', String(newValue))
144+
return newValue
145+
})
146+
}
147+
```
148+
149+
**Conditional Rendering:**
150+
```tsx
151+
const gameBoard = is3DMode ? (
152+
<TicTacToeBoard3D
153+
gameState={gameSession.gameState}
154+
onMove={makeMove}
155+
disabled={isLoading || gameSession.gameState.currentPlayerId === 'ai'}
156+
/>
157+
) : (
158+
<TicTacToeBoard
159+
gameState={gameSession.gameState}
160+
onMove={makeMove}
161+
disabled={isLoading || gameSession.gameState.currentPlayerId === 'ai'}
162+
/>
163+
)
164+
```
165+
166+
**Pass Props to GameControls:**
167+
```tsx
168+
<GameControls
169+
isLoading={isLoading}
170+
onNewGame={() => startNewGame()}
171+
onDelete={() => handleDeleteGame(gameSession.gameState.id)}
172+
onViewToggle={handleViewToggle}
173+
is3DMode={is3DMode}
174+
showDelete={true}
175+
/>
176+
```
177+
178+
**Memory Leak Prevention:**
179+
- Ensure proper cleanup when toggling views
180+
- Canvas should unmount cleanly
181+
- Three.js resources should be disposed properly
182+
- react-three-fiber handles most cleanup automatically, but verify no lingering references
183+
184+
---
185+
186+
## Technical Specifications
187+
188+
### Geometries for Game Symbols
189+
190+
**Cell Base:**
191+
- `BoxGeometry` for the clickable cell surface
192+
- Material: Semi-transparent when empty, solid when occupied
193+
- Dimensions: Appropriate spacing for 3x3 grid
194+
195+
**X Symbol:**
196+
- Two `CylinderGeometry` meshes arranged in an X pattern
197+
- Rotate cylinders 45° and -45° to form cross
198+
- Color: Blue (matching 2D version)
199+
200+
**O Symbol:**
201+
- `TorusGeometry` for circular ring
202+
- Color: Red (matching 2D version)
203+
204+
### Camera Configuration
205+
- **Position:** `[5, 5, 5]` (isometric view)
206+
- **LookAt:** `[0, 0, 0]` (center of board)
207+
- **Controls:** `OrbitControls` with:
208+
- Enable rotate: `true`
209+
- Enable zoom: `true`
210+
- Enable pan: `false` (optional)
211+
- Min/max distance limits to prevent extreme zoom
212+
213+
### Performance Considerations
214+
- Desktop-first optimization (no mobile-specific handling in MVP)
215+
- Keep geometry complexity low for smooth 60fps
216+
- Use instanced meshes if performance issues arise
217+
- Proper disposal of Three.js resources on unmount
218+
219+
### Accessibility Notes
220+
- 3D mode is optional; 2D mode remains fully functional
221+
- Toggle is clearly labeled in sidebar
222+
- Preference persists across page refreshes
223+
- No keyboard navigation in 3D mode for MVP (future enhancement)
224+
225+
---
226+
227+
## Testing Strategy (Post-MVP)
228+
- Manual testing for MVP
229+
- Future considerations:
230+
- Mock Three.js for unit tests
231+
- Visual regression testing for 3D rendering
232+
- Performance benchmarks
233+
- Test localStorage persistence
234+
235+
---
236+
237+
## localStorage Schema
238+
**Key:** `ticTacToe_view3D`
239+
**Value:** `"true"` or `"false"` (string representation of boolean)
240+
**Scope:** Per-browser, persists across page refreshes for the same game type
241+
242+
---
243+
244+
## File Structure Summary
245+
```
246+
web/
247+
├── src/
248+
│ ├── components/
249+
│ │ ├── games/
250+
│ │ │ ├── TicTacToeBoard.tsx (existing)
251+
│ │ │ └── TicTacToeBoard3D.tsx (NEW)
252+
│ │ └── ui/
253+
│ │ └── GameControls.tsx (MODIFY)
254+
│ └── app/
255+
│ └── games/
256+
│ └── tic-tac-toe/
257+
│ └── page.tsx (MODIFY)
258+
└── package.json (MODIFY - add dependencies)
259+
```
260+
261+
---
262+
263+
## Dependencies Impact
264+
**New packages added to `web/package.json`:**
265+
- `three@^0.170.0`
266+
- `@react-three/fiber@^9.0.0`
267+
- `@react-three/drei@^10.0.0`
268+
- `@react-three/cannon@^6.6.0`
269+
270+
**Bundle size impact:** ~500KB (Three.js core + react-three libraries)
271+
272+
---
273+
274+
## Success Criteria
275+
- [x] User can toggle between 2D and 3D views via sidebar button
276+
- [x] 3D view renders a rotatable 3x3 Tic Tac Toe board
277+
- [x] Clicking cells in 3D works identically to 2D
278+
- [x] Hover effects show which cells are clickable
279+
- [x] AI turn disables the board with visual feedback
280+
- [x] Turn indicator shows current player above board
281+
- [x] Win condition triggers celebratory effect in 3D
282+
- [x] View preference persists across page refreshes
283+
- [x] No memory leaks when toggling between views
284+
- [x] Existing 2D functionality remains unchanged
285+
286+
---
287+
288+
## Future Enhancements (Out of Scope for MVP)
289+
- Mobile/touch optimization
290+
- Keyboard navigation in 3D mode
291+
- Custom camera presets (top-down, side view, etc.)
292+
- Animation transitions when placing symbols
293+
- Sound effects
294+
- Multiple 3D themes/skins
295+
- Unit and integration tests for 3D components

0 commit comments

Comments
 (0)