Nokia Snake Game - Service Layer Design

Service layer design

Nokia Snake Game - Service Layer Design

Service Overview

The service layer provides orchestration and coordination between components, implementing business logic and managing cross-cutting concerns. Services follow a centralized pattern with clear responsibilities and interfaces.

Core Services

1. Game Orchestration Service

Purpose: Coordinate game components and manage the overall game flow

Responsibilities:

  • Orchestrate game loop execution
  • Coordinate component interactions
  • Manage game state transitions
  • Handle game events and routing
  • Ensure component synchronization

Service Interface:

/**
 * Game Orchestration Service
 * Manages overall game flow and component coordination
 */
class GameOrchestrationService {
  /**
   * Initialize service with component dependencies
   * @param {Object} dependencies - Component dependencies
   */
  constructor(dependencies) {
    this.gameEngine = dependencies.gameEngine;
    this.rendering = dependencies.rendering;
    this.inputHandler = dependencies.inputHandler;
    this.stateManager = dependencies.stateManager;
    this.ui = dependencies.ui;
    this.scoreService = dependencies.scoreService;
  }

  /**
   * Start the game with initial configuration
   * @param {Object} config - Game configuration
   * @returns {Promise<void>}
   */
  async startGame(config) {
    // 1. Initialize all components
    // 2. Set up game state
    // 3. Start game loop
    // 4. Begin rendering
  }

  /**
   * Pause the game
   * @returns {void}
   */
  pauseGame() {
    // 1. Stop game loop
    // 2. Update game state
    // 3. Show pause UI
  }

  /**
   * Resume paused game
   * @returns {void}
   */
  resumeGame() {
    // 1. Restart game loop
    // 2. Update game state
    // 3. Hide pause UI
  }

  /**
   * Handle game over condition
   * @param {Object} gameOverData - Game over information
   * @returns {void}
   */
  handleGameOver(gameOverData) {
    // 1. Stop game loop
    // 2. Update scores
    // 3. Show game over UI
    // 4. Save game state
  }

  /**
   * Restart the game
   * @returns {void}
   */
  restartGame() {
    // 1. Reset game state
    // 2. Reinitialize components
    // 3. Start new game
  }

  /**
   * Process game frame
   * @param {number} deltaTime - Time since last frame
   * @returns {void}
   */
  processFrame(deltaTime) {
    // 1. Process input
    // 2. Update game state
    // 3. Check collisions
    // 4. Apply game rules
    // 5. Update rendering
  }
}

Orchestration Patterns:

  1. Command Pattern: Input events translated to game commands
  2. Observer Pattern: State changes propagate to observers
  3. Mediator Pattern: Service mediates component interactions
  4. Strategy Pattern: Different game modes as strategies

2. Score Service

Purpose: Manage scoring, high scores, and game progress tracking

Responsibilities:

  • Calculate and track scores
  • Manage high score persistence
  • Track game progress and achievements
  • Provide score-related analytics
  • Handle score validation

Service Interface:

/**
 * Score Service
 * Manages scoring, high scores, and game progress
 */
class ScoreService {
  /**
   * Initialize score service
   * @param {Object} storage - Storage adapter (localStorage, IndexedDB, etc.)
   */
  constructor(storage) {
    this.storage = storage;
    this.currentScore = 0;
    this.highScores = [];
  }

  /**
   * Calculate score for game event
   * @param {string} eventType - Type of game event
   * @param {Object} eventData - Event data
   * @returns {number} Score points
   */
  calculateEventScore(eventType, eventData) {
    // Scoring rules:
    // - Food collection: 10 points
    // - Power-up collection: 25 points
    // - Special food: 50 points
    // - Combo multiplier: based on consecutive collections
  }

  /**
   * Update current score
   * @param {number} delta - Score change
   * @returns {number} New score
   */
  updateScore(delta) {
    this.currentScore += delta;
    return this.currentScore;
  }

  /**
   * Check and update high score
   * @param {number} score - Current score
   * @returns {boolean} True if high score beaten
   */
  updateHighScore(score) {
    if (score > this.getHighestScore()) {
      this.highScores.unshift({
        score: score,
        date: new Date().toISOString(),
        level: this.getCurrentLevel()
      });
      
      // Keep only top 10 scores
      this.highScores = this.highScores.slice(0, 10);
      
      // Persist to storage
      this.saveHighScores();
      return true;
    }
    return false;
  }

  /**
   * Get highest score
   * @returns {number} Highest score
   */
  getHighestScore() {
    return this.highScores.length > 0 ? this.highScores[0].score : 0;
  }

  /**
   * Load high scores from storage
   * @returns {Promise<Array>} High scores
   */
  async loadHighScores() {
    const scores = await this.storage.get('highScores');
    this.highScores = scores || [];
    return this.highScores;
  }

  /**
   * Save high scores to storage
   * @returns {Promise<void>}
   */
  async saveHighScores() {
    await this.storage.set('highScores', this.highScores);
  }

  /**
   * Reset current score
   * @returns {void}
   */
  resetCurrentScore() {
    this.currentScore = 0;
  }

  /**
   * Get game statistics
   * @returns {Object} Game statistics
   */
  getGameStatistics() {
    return {
      totalGamesPlayed: this.getTotalGamesPlayed(),
      totalScore: this.getTotalScore(),
      averageScore: this.getAverageScore(),
      bestCombo: this.getBestCombo(),
      achievements: this.getAchievements()
    };
  }
}

Scoring Rules:

  1. Base Scoring:

    • Regular food: 10 points
    • Special food: 50 points
    • Power-ups: 25 points
  2. Combo System:

    • Consecutive food collection without dying: 1.5x multiplier
    • Max combo: 5x multiplier
    • Combo resets on death or missed food
  3. Difficulty Multipliers:

    • Easy: 1x
    • Medium: 1.5x
    • Hard: 2x
    • Expert: 3x

3. Event Bus Service (Implicit)

Purpose: Decoupled event communication between components

Responsibilities:

  • Publish/subscribe event system
  • Event routing and filtering
  • Event validation and transformation
  • Error handling for events

Event Types:

const GameEvents = {
  // Input Events
  INPUT_KEY_DOWN: 'input:keydown',
  INPUT_KEY_UP: 'input:keyup',
  
  // Game State Events
  GAME_STARTED: 'game:started',
  GAME_PAUSED: 'game:paused',
  GAME_RESUMED: 'game:resumed',
  GAME_OVER: 'game:over',
  GAME_RESTARTED: 'game:restarted',
  
  // Gameplay Events
  FOOD_COLLECTED: 'gameplay:food:collected',
  POWERUP_COLLECTED: 'gameplay:powerup:collected',
  COLLISION_DETECTED: 'gameplay:collision:detected',
  SCORE_UPDATED: 'gameplay:score:updated',
  
  // UI Events
  UI_MENU_OPENED: 'ui:menu:opened',
  UI_MENU_CLOSED: 'ui:menu:closed',
  UI_BUTTON_CLICKED: 'ui:button:clicked',
  
  // System Events
  SYSTEM_INITIALIZED: 'system:initialized',
  SYSTEM_ERROR: 'system:error',
  SYSTEM_WARNING: 'system:warning'
};

4. Plugin Manager Service

Purpose: Manage extensible plugin system

Responsibilities:

  • Plugin registration and discovery
  • Plugin lifecycle management
  • Plugin dependency resolution
  • Plugin configuration management

Plugin Types:

  1. Power-up Plugins: Additional power-up types
  2. Visual Theme Plugins: Alternative visual styles
  3. Game Mode Plugins: Additional game modes
  4. Analytics Plugins: Game analytics and telemetry
  5. Social Plugins: Social features and sharing

Service Interaction Patterns

1. Request-Response Pattern

Component → Service → Component
Example: UI requests score → Score Service → Returns score

2. Publish-Subscribe Pattern

Component → Event Bus → Multiple Components
Example: Food collected → Score updates, UI updates, Analytics tracks

3. Orchestration Pattern

Orchestration Service → Multiple Components
Example: Game start → Initialize all components, start game loop

4. Choreography Pattern

Component → Event → Component → Event → Component
Example: Input → Game Engine → Rendering → UI

Service Dependencies

Game Orchestration Service
  ├── depends on: All core components
  └── provides: Game flow coordination

Score Service
  ├── depends on: Storage adapter, State Manager
  └── provides: Scoring and progress tracking

Event Bus Service
  ├── depends on: None (standalone)
  └── provides: Decoupled communication

Plugin Manager Service
  ├── depends on: Configuration, Event Bus
  └── provides: Plugin lifecycle management

Service Configuration

const serviceConfig = {
  gameOrchestration: {
    frameRate: 60, // FPS
    fixedTimeStep: 16.67, // ms (60 FPS)
    maxFrameSkip: 5
  },
  
  scoreService: {
    storageType: 'localStorage',
    maxHighScores: 10,
    scoreDecay: false, // Whether scores decay over time
    comboEnabled: true,
    comboMultiplier: {
      base: 1.0,
      max: 5.0,
      increment: 0.5
    }
  },
  
  eventBus: {
    maxListeners: 50,
    enableLogging: false,
    errorHandling: 'strict' // 'strict' | 'lenient' | 'silent'
  },
  
  pluginManager: {
    pluginDirectory: '/plugins/',
    autoLoad: true,
    sandboxed: true, // Run plugins in sandboxed environment
    versionCheck: true
  }
};

Security Considerations for Services

  1. Input Validation: All service methods validate inputs
  2. Error Handling: Services handle errors gracefully
  3. Data Sanitization: Output data is sanitized
  4. Access Control: Service methods have appropriate access levels
  5. Audit Logging: Service actions are logged for security auditing