scarytom/tta

Times Tables Attack Game

★ 0Forks 0HTMLGitHub ↗Compare

README

Math Multiplication Shooter

A lightweight, dependency-free educational game built in pure modern JavaScript using the HTML5 Canvas API.

🚀 Project Overview

This is a multiplication practice game where the player controls a cannon at the bottom of the screen, firing numbered bullets at enemies displaying maths problems. Players must shoot the correct answer to destroy each enemy.

The goal was to build a robust "Game Engine" from scratch without external libraries, focusing on clean architecture, frame-rate independence, and state management.

🛠 Architecture & Design Decisions

The codebase currently resides in a single file (index.html) for portability, but is structured to be easily modularized.

1. The "State Container" Pattern

We utilize a functional-inspired architecture where the game logic is separated from the game state.

  • State is Isolated: All changing data (player position, score, enemy arrays) is contained in a single gameState object.
  • Update is Logic-Only: The update() function takes the current state, input, and time, and returns the modified state.
  • Draw is Pure: The draw() function takes the state and renders it. It never modifies data.

2. Lazy Initialization

We do not manually initialize the game before the loop starts. Instead, the update() function handles self-healing:

  • If gameState is undefined, it creates it.
  • If isGameOver is true and a restart is requested, it replaces the state with a fresh one. This removes the need for duplicate "reset" logic.

3. Frame-Rate Independence (Delta Time)

  • Logic: Movement is calculated in Pixels Per Second, not Pixels Per Frame.
  • Implementation: The update function accepts a raw timestamp from requestAnimationFrame, calculates the deltaTime internally (comparing it to lastFrameTime stored in the state), and applies strictly time-based movement.

4. Configuration Separation

  • CONFIG Object: All "magic numbers" (colors, dimensions, base speeds) are extracted into a constant object at the top of the file.
  • Naming Convention: We strictly use verbose, explicit variable names (e.g., lastFrameTime instead of lastTime, deltaTime instead of dt) to maximize readability.

5. Data Structures

Game State Object

{
    score: Number,
    highScore: Number,          // Persisted via localStorage
    isGameOver: Boolean,
    lastFrameTime: Number,      // Timestamp of the previous frame
    secsSinceLastSpawn: Number, // Accumulator for enemy spawning
    spawnIntervalSecs: Number,  // Difficulty scaling
    columns: Array[],           // 5 columns of enemies
    player: { x, y, width, height, targetX, sprite },
    bullets: [ { x, y, width, height, value, sprite } ],
    explosions: [ { x, y, age, type } ]
}

Input State Object

Input is handled via a persistent object updated by Event Listeners, decoupled from the game loop.

{
    moveLeftRequest: Boolean,
    moveRightRequest: Boolean,
    fireValue: String,       // Number keys 0-12 (`, 1-9, 0, -, =)
    restartRequest: Boolean  // Enter key on Game Over
}

🎮 Current Gameplay Features

Core Mechanics:

  • Column-based movement: Player snaps between 5 columns using arrow keys
  • Math problems: Enemies display multiplication equations with missing operands
  • Numbered bullets: Keys 0-12 fire bullets with corresponding values
  • Answer validation: Correct answers destroy enemies, wrong answers show red X effect

Visual Polish:

  • Procedurally generated sprites: 3 enemy types, player cannon, bullets
  • Explosion animations: Orange particles for successful hits, red X for misses
  • Smooth interpolation: Player and enemies glide to target positions

Progression:

  • Difficulty scaling: Spawn rate increases with score
  • High score tracking: Persisted via localStorage, displayed in UI bar
  • Game over: Triggered when enemies reach the player's row

Collision Detection: Standard AABB (Axis-Aligned Bounding Box)

🗺️ Future Roadmap (To-Do)

If picking up this project, the following features are the next logical steps:

Phase 1: Polish

  • Power-ups: Special bullets that clear entire columns or slow enemy descent
  • Combo system: Reward consecutive correct answers with score multipliers

Phase 2: Customization

  • Difficulty settings: Adjustable number ranges and operation types (+, -, ×, ÷)
  • Practice mode: Focus on specific multiplication tables
  • Statistics: Track accuracy, response time, and problem types

Phase 3: Infrastructure

  • Module split: Separate CONFIG, update, draw, and sprite generation into .js files
  • Responsive canvas: Dynamically resize while maintaining aspect ratio

▶️ How to Run

Simply open index.html in any modern web browser. No build steps or servers are required. Or browse to https://scarytom.github.io/tta

Controls

  • Arrow Left/Right: Move between columns
  • Number keys: Fire bullets with values 0-12
    • ` = 0
    • 1-9 = 1-9
    • 0 = 10
    • - = 11
    • = = 12
  • Enter: Restart after game over

Contributors

scarytom

Issues