Frontend Components - Nokia Snake Game
UI components
Frontend Components - Nokia Snake Game
Overview
Architecture: Component-based with Redux-like state management
Granularity: Moderate (logical grouping per game entity/feature)
Rendering: WebGL 2D context with modern minimalist design
State Management: Centralized store with unidirectional data flow
Component Hierarchy
graph TB
App[App Component] --> GameContainer[GameContainer]
App --> MainMenu[MainMenu]
App --> GameOverScreen[GameOverScreen]
GameContainer --> GameCanvas[GameCanvas]
GameContainer --> GameHUD[GameHUD]
GameContainer --> PauseMenu[PauseMenu]
GameCanvas --> SnakeRenderer[SnakeRenderer]
GameCanvas --> FoodRenderer[FoodRenderer]
GameCanvas --> PowerUpRenderer[PowerUpRenderer]
GameCanvas --> GridRenderer[GridRenderer]
GameHUD --> ScoreDisplay[ScoreDisplay]
GameHUD --> HighScoreDisplay[HighScoreDisplay]
GameHUD --> TimerDisplay[TimerDisplay]
GameHUD --> LevelDisplay[LevelDisplay]
MainMenu --> StartButton[StartButton]
MainMenu --> SettingsButton[SettingsButton]
MainMenu --> HighScoresButton[HighScoresButton]
GameOverScreen --> RestartButton[RestartButton]
GameOverScreen --> MenuButton[MenuButton]
GameOverScreen --> FinalScoreDisplay[FinalScoreDisplay]
Core Components
1. App Component
Purpose: Root component, application entry point
Responsibilities:
- Application initialization and setup
- Routing between main screens
- Global error boundary
- Theme provider
Props: None (root component)
State:
currentScreen: 'MAIN_MENU' | 'GAME' | 'GAME_OVER' | 'SETTINGS'theme: Current visual themeerror: Global error state
Methods:
initializeApp(): Set up applicationhandleScreenChange(screen): Navigate between screenshandleGlobalError(error): Global error handlerapplyTheme(theme): Change visual theme
Lifecycle:
- Mount: Initialize app, set up event listeners
- Update: Handle screen changes, theme updates
- Unmount: Clean up resources, save state
2. GameContainer Component
Purpose: Main game screen container
Responsibilities:
- Game state management
- Component coordination
- Input handling delegation
- Game loop management
Props:
initialState: Initial game state (optional)onGameOver: Callback when game endsonPause: Callback when game paused
State:
gameState: Current game state objectisPaused: Boolean indicating pause stateinputState: Current keyboard input staterenderStats: Performance statistics
Methods:
startGame(): Initialize and start gamepauseGame(): Pause game loopresumeGame(): Resume game looprestartGame(): Reset and restart gamehandleInput(event): Process keyboard inputupdateGameState(deltaTime): Update game logic
Lifecycle:
- Mount: Initialize game engine, set up input handlers
- Game Loop: Continuous state updates and rendering
- Pause/Resume: Manage game loop suspension
- Unmount: Stop game loop, clean up resources
3. GameCanvas Component
Purpose: WebGL rendering canvas
Responsibilities:
- WebGL context management
- Game element rendering
- Canvas sizing and scaling
- Performance optimization
Props:
gameState: Current game state to renderwidth: Canvas widthheight: Canvas heighttheme: Visual theme configuration
State:
glContext: WebGL rendering contextrenderQueue: Queue of rendering operationslastRenderTime: Timestamp of last renderfps: Current frames per second
Methods:
initializeWebGL(): Set up WebGL contextrenderFrame(): Render single frameresizeCanvas(width, height): Handle canvas resizeclearCanvas(): Clear rendering canvasrenderGameObject(object, style): Render game object
Lifecycle:
- Mount: Create canvas, initialize WebGL
- Render Loop: Continuous rendering at target FPS
- Resize: Handle window resize events
- Unmount: Clean up WebGL resources
4. SnakeRenderer Component
Purpose: Render snake entity
Responsibilities:
- Snake segment rendering
- Movement animations
- Color and style application
- Special effects (power-ups, etc.)
Props:
snake: Snake entity objectgridSize: Game grid dimensionscellSize: Size of each grid cell in pixelsstyle: Visual style configuration
State:
animationState: Current animation statesegmentCache: Cached segment positionscolorGradient: Color gradient for snake
Methods:
renderSnake(): Render complete snakeanimateMovement(oldPositions, newPositions): Animate movementapplyPowerUpEffects(powerUpType): Apply visual effectsupdateSegmentCache(positions): Update position cache
Rendering Details:
- Head: Distinct shape/color
- Body: Segments with gradient
- Tail: Special rendering
- Movement: Smooth animation between positions
- Effects: Visual feedback for power-ups
5. FoodRenderer Component
Purpose: Render food items
Responsibilities:
- Food item rendering
- Collection animations
- Type-specific visuals
- Spawn/despawn effects
Props:
foodItems: Array of food objectsgridSize: Game grid dimensionscellSize: Size of each grid cell in pixelsstyle: Visual style configuration
State:
animationState: Food animation stateparticleEffects: Collection animation particlespulseState: Pulsing animation state
Methods:
renderFood(): Render all food itemsanimateCollection(food): Animate food collectionapplyTypeStyle(foodType): Apply type-specific stylingupdatePulseAnimation(): Update pulsing animation
Rendering Details:
- Regular Food: Simple circle with color
- Power-up Food: Special shape with glow effect
- Animation: Pulsing, rotating, or other effects
- Collection: Particle explosion effect
6. GameHUD Component
Purpose: Heads-Up Display overlay
Responsibilities:
- Game information display
- Score and statistics
- Control hints
- Performance metrics
Props:
gameState: Current game stateposition: HUD position on screentheme: Visual theme configurationshowPerformance: Whether to show performance stats
State:
hudElements: Array of HUD elements to displayupdateQueue: Queue of HUD updatesanimationState: HUD animation state
Methods:
updateHUD(gameState): Update HUD with current stateanimateScoreChange(oldScore, newScore): Animate score changesshowNotification(message, type): Show temporary notificationtogglePerformanceStats(): Toggle performance display
HUD Elements:
- Score Display: Current score with animation
- High Score: Best score achieved
- Timer: Game duration
- Level: Current difficulty level
- Snake Length: Current snake size
- Consecutive Foods: Streak counter
- Power-up Timer: Active power-up duration
7. MainMenu Component
Purpose: Main menu screen
Responsibilities:
- Game start initiation
- Navigation to other screens
- Settings access
- High scores display
Props:
onStartGame: Callback to start gameonShowSettings: Callback to show settingsonShowHighScores: Callback to show high scoreshighScores: Array of high scores
State:
menuState: Current menu stateselectedOption: Currently selected menu optionanimationState: Menu animation state
Methods:
handleStartGame(): Trigger game starthandleSettings(): Open settings screenhandleHighScores(): Show high scoreshandleKeyNavigation(event): Handle keyboard navigation
Menu Options:
- Start Game: Begin new game session
- Continue: Resume saved game (if available)
- Settings: Game configuration
- High Scores: View best scores
- Help: Game instructions
- Exit: Close application (web: reload)
8. GameOverScreen Component
Purpose: Game over screen
Responsibilities:
- Final score display
- Restart option
- High score celebration
- Statistics summary
Props:
finalScore: Game ending scorehighScore: Current high scoregameStats: Game statisticsonRestart: Callback to restart gameonMenu: Callback to return to menu
State:
screenState: Screen animation statescoreAnimation: Score display animationparticleEffects: Celebration effects
Methods:
animateScoreReveal(): Animate score displaycheckHighScore(): Check if high score beatenshowCelebration(): Show celebration effectshandleRestart(): Trigger game restart
Screen Elements:
- Game Over Title: Large text display
- Final Score: Animated score reveal
- High Score Indicator: If new record achieved
- Statistics: Game duration, snake length, etc.
- Restart Button: Immediate restart
- Menu Button: Return to main menu
Component Props and State
Common Props Interface
interface GameComponentProps {
// Required props
gameState?: GameState;
theme?: ThemeConfig;
// Optional props
width?: number;
height?: number;
className?: string;
style?: React.CSSProperties;
// Callbacks
onStateChange?: (newState: Partial<GameState>) => void;
onError?: (error: Error) => void;
onRenderComplete?: () => void;
}
interface GameState {
status: 'MAIN_MENU' | 'PLAYING' | 'PAUSED' | 'GAME_OVER';
score: number;
highScore: number;
snake: Snake;
food: Food[];
gameTime: number;
// ... other state properties
}
Component State Management
// Centralized state store
class GameStore {
private state: GameState;
private subscribers: Array<(state: GameState) => void>;
getState(): GameState;
dispatch(action: GameAction): void;
subscribe(callback: (state: GameState) => void): Unsubscribe;
}
// Component local state
interface ComponentLocalState {
// UI-specific state
isAnimating: boolean;
localValues: Record<string, any>;
errorState: Error | null;
// Performance state
renderCount: number;
lastRenderTime: number;
performanceMetrics: PerformanceMetrics;
}
Component Interactions
1. Input Flow
Keyboard Event → InputHandler → GameContainer → GameState Update → Component Re-render
2. Rendering Flow
GameState Change → GameContainer → GameCanvas → Individual Renderers → WebGL Draw Calls
3. State Update Flow
User Action → Component Handler → Store Dispatch → State Update → Subscriber Notification → Component Update
4. Error Handling Flow
Component Error → Error Boundary → Error Handler → Fallback UI → Error Logging
User Interaction Flows
Game Start Flow
sequenceDiagram
User->>MainMenu: Click "Start Game"
MainMenu->>App: navigateTo('GAME')
App->>GameContainer: mount with initialState
GameContainer->>GameContainer: initializeGame()
GameContainer->>GameCanvas: render with gameState
GameContainer->>InputHandler: start listening
GameContainer->>GameLoop: start()
Game Pause/Resume Flow
sequenceDiagram
User->>GameContainer: Press "P" key
GameContainer->>GameContainer: togglePause()
GameContainer->>GameLoop: pause() / resume()
GameContainer->>GameHUD: update with isPaused
GameContainer->>PauseMenu: show() / hide()
Game Over Flow
sequenceDiagram
GameEngine->>GameContainer: collision detected
GameContainer->>GameContainer: handleGameOver()
GameContainer->>GameLoop: stop()
GameContainer->>App: onGameOver(finalScore)
App->>GameOverScreen: mount with finalScore
GameOverScreen->>GameOverScreen: animateScoreReveal()
GameOverScreen->>HighScoreManager: checkHighScore()
Settings Change Flow
sequenceDiagram
User->>SettingsScreen: Change control mapping
SettingsScreen->>GameStore: dispatch(SETTINGS_UPDATE)
GameStore->>InputHandler: updateControlMapping()
GameStore->>All Components: notify state change
SettingsScreen->>LocalStorage: saveSettings()
Form Validation Rules
Settings Form Validation
const settingsValidationRules = {
// Control mapping validation
controls: {
up: { required: true, type: 'string', maxLength: 20 },
down: { required: true, type: 'string', maxLength: 20 },
left: { required: true, type: 'string', maxLength: 20 },
right: { required: true, type: 'string', maxLength: 20 },
pause: { required: true, type: 'string', maxLength: 20 }
},
// Game settings validation
gameSettings: {
gridWidth: { required: true, type: 'number', min: 10, max: 50 },
gridHeight: { required: true, type: 'number', min: 10, max: 50 },
initialSpeed: { required: true, type: 'number', min: 1, max: 20 },
powerUpChance: { required: true, type: 'number', min: 0, max: 1 }
},
// Visual settings validation
visualSettings: {
theme: { required: true, type: 'string', enum: ['MINIMAL', 'CLASSIC', 'MODERN'] },
animationSpeed: { required: true, type: 'number', min: 0.5, max: 2.0 }
}
};
Input Validation Rules (SECURITY-05 Compliance)
const inputValidationRules = {
// Keyboard input validation
keyboardInput: {
key: { required: true, type: 'string', pattern: /^[A-Za-z0-9ArrowUpArrowDownArrowLeftArrowRightEscapeSpace]$/ },
type: { required: true, type: 'string', enum: ['keydown', 'keyup'] },
timestamp: { required: true, type: 'number', min: 0 }
},
// Game state validation
gameState: {
score: { required: true, type: 'number', min: 0 },
snakeLength: { required: true, type: 'number', min: 1, max: 1000 },
gameTime: { required: true, type: 'number', min: 0 }
},
// Component props validation
componentProps: {
gameState: { required: false, type: 'object' },
theme: { required: false, type: 'object' },
callbacks: { required: false, type: 'object' }
}
};
Component Lifecycle
Mounting Phase
- Constructor: Initialize state, bind methods
- ComponentDidMount: DOM setup, event listeners, resource loading
- Initial Render: First render with initial state
Updating Phase
- ShouldComponentUpdate: Performance optimization check
- ComponentDidUpdate: Handle prop/state changes, side effects
- Render: Re-render with updated state
Unmounting Phase
- ComponentWillUnmount: Clean up resources, event listeners
- State Persistence: Save component state if needed
- Resource Cleanup: Release WebGL resources, timers, etc.
Error Handling
- Error Boundary: Catch component errors
- Fallback UI: Show error state component
- Error Recovery: Attempt automatic recovery
- Error Logging: Log errors for debugging
Performance Optimization
Rendering Optimization
- ShouldComponentUpdate: Prevent unnecessary re-renders
- Memoization: Cache expensive computations
- Virtualization: Only render visible elements
- Batching: Batch state updates and renders
Memory Optimization
- Object Pooling: Reuse component instances
- Event Delegation: Use event delegation instead of individual listeners
- Resource Management: Proper cleanup of WebGL resources
- Garbage Collection: Minimize object creation in render methods
WebGL Optimization
- Texture Atlases: Combine textures into atlases
- Batch Rendering: Batch similar draw calls
- Shader Optimization: Use efficient shaders
- Buffer Management: Proper buffer usage and cleanup
Security Considerations
Input Validation (SECURITY-05 Compliance)
- Prop Validation: Validate all component props
- Event Validation: Validate event data before processing
- State Validation: Validate component state changes
- DOM Sanitization: Sanitize any dynamic content
Error Handling (SECURITY-15 Compliance)
- Error Boundaries: Isolate component errors
- Graceful Degradation: Fallback when features unavailable
- Safe Defaults: Default to safe states on error
- Error Logging: Log errors without exposing sensitive data
XSS Prevention
- Content Sanitization: Sanitize dynamic content
- Event Handler Security: Secure event handler binding
- DOM Manipulation Safety: Safe DOM manipulation practices
- CSP Compliance: Content Security Policy adherence
Testing Strategy
Unit Tests
- Component Rendering: Test component renders correctly
- Props Validation: Test prop validation logic
- State Management: Test component state changes
- Event Handling: Test event handlers
Integration Tests
- Component Interaction: Test component communication
- User Flows: Test complete user interaction flows
- State Management: Test Redux store integration
- Rendering Pipeline: Test complete rendering pipeline
Performance Tests
- Render Performance: Test component render speed
- Memory Usage: Test component memory footprint
- Animation Performance: Test animation smoothness
- Load Time: Test component initialization time
Accessibility Tests
- Keyboard Navigation: Test keyboard accessibility
- Screen Reader: Test screen reader compatibility
- Color Contrast: Test visual accessibility
- Focus Management: Test focus handling
Compliance Summary
SECURITY Baseline Compliance
- SECURITY-05 (Input Validation): Component props validation, event validation, form validation
- SECURITY-15 (Exception Handling): Error boundaries, graceful degradation, safe defaults
Frontend Best Practices
- Component Design: Single responsibility, loose coupling, high cohesion
- Performance: Optimized rendering, memory management, WebGL best practices
- Accessibility: Keyboard navigation, screen reader support, color contrast
- Maintainability: Clean code, documentation, test coverage