A modern remake of the classic turn-based artillery game Scorched Earth, built as a single-page web application using React and TypeScript.
Scorched Earth Tanks is a two-player turn-based strategy game where players control tanks positioned on opposite sides of a randomly generated terrain. Players take turns adjusting their tank's cannon angle and power settings to fire projectiles at their opponent. The first player to destroy the enemy tank wins.
- Loading Screen: The game starts with delightful animations that play for a few seconds before revealing a Start button
- Terrain Generation: Random procedural terrain is generated at the start of each match
- Tank Placement: Two tanks are placed on opposite sides (left/right) of the terrain, each with a distinct color
- Turn-Based Combat: Players alternate turns to fire at each other
- Aiming System: Players select:
- Angle: 0-90 degrees for cannon direction
- Power: 0-100% for shot velocity
- Physics Simulation: Projectiles follow realistic ballistic trajectories using gravity (10 m/s²)
- Projectile Tracing: A dotted line shows the path of the projectile as it flies
- Collision Detection:
- Projectile impacts create small explosion animations
- If explosion overlaps any part of enemy tank, that tank is destroyed
- Player who made the hit wins
- Win Condition: Game ends when one tank is destroyed
- Gravitational constant: 10 m/s²
- Screen calibration: Full power (100%) at 70° angle sends projectile from far left to far right of screen
- Physics scale dynamically to canvas dimensions
- Runtime: Node.js
- Framework: React 18.3.1
- Language: TypeScript 5.7.2
- Build Tool: Vite 6.0.3
- Package Manager: npm
- Linting: ESLint 9.15.0 with TypeScript and React plugins
- TypeScript Config: Strict mode enabled, ES2020 target
- Issue Tracking: Beads (bd CLI)
{
"react": "^18.3.1",
"react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.4"
}tanks/
├── src/
│ ├── components/ # React UI components
│ ├── engine/ # Game logic and physics
│ ├── utils/ # Helper functions and utilities
│ ├── App.tsx # Main application component
│ ├── App.css # Application styles
│ ├── main.tsx # React entry point
│ └── index.css # Global styles
├── index.html # HTML entry point
├── package.json # Project dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── vite.config.ts # Vite build configuration
├── .beads/ # Issue tracking database (beads)
├── AGENTS.md # Agent workflow instructions
└── README.md # This file
src/components/: React components for UI elements (buttons, controls, canvas, screens)src/engine/: Core game logic, physics calculations, collision detection, game statesrc/utils/: Shared utilities, constants, helper functions, type definitions
- Node.js (v18 or higher recommended)
- npm (comes with Node.js)
- Git
# Clone the repository
git clone git@github.com:LupusDei/tanks.git
cd tanks
# Install dependencies
npm install
# Start development server
npm run devThe application will be available at http://localhost:5173/
npm run dev # Start development server with hot reload
npm run build # Build for production (TypeScript compile + Vite build)
npm run preview # Preview production build locally
npm run lint # Run ESLint to check code quality
npm test # Run test suite
npm test -- --watch # Run tests in watch mode
npm test -- --coverage # Run tests with coverage reportTests are MANDATORY - Every feature must have corresponding tests.
- Vitest: Fast unit testing framework (Vite-native)
- React Testing Library: Component testing
- Coverage Target: >80% for critical code paths
# Run all tests
npm test
# Watch mode (auto-rerun on changes)
npm test -- --watch
# Coverage report
npm test -- --coverage
# Run specific test file
npm test physics.test.tsTests live alongside the code they test:
src/
├── engine/
│ ├── physics.ts
│ ├── physics.test.ts # Unit tests for physics
│ ├── collision.ts
│ └── collision.test.ts
├── components/
│ ├── Canvas.tsx
│ └── Canvas.test.tsx # Component tests
└── utils/
├── math.ts
└── math.test.ts
- ✅ Write tests BEFORE or ALONGSIDE implementation
- ✅ Test edge cases and error conditions
- ✅ Keep tests fast and independent
- ✅ Use descriptive test names
- ✅ Mock external dependencies
- ❌ Never commit code without tests
- ❌ Never skip failing tests
// physics.test.ts
import { describe, it, expect } from 'vitest'
import { calculateTrajectory } from './physics'
describe('calculateTrajectory', () => {
it('should calculate correct position at t=0', () => {
const result = calculateTrajectory(45, 100, 0)
expect(result).toEqual({ x: 0, y: 0 })
})
it('should account for gravity over time', () => {
const result = calculateTrajectory(45, 100, 1)
expect(result.y).toBeLessThan(0) // Falling due to gravity
})
})This project is designed for parallel development. Multiple agents must be able to work simultaneously without conflicts.
Key Principles:
- ✅ One responsibility per module: Each file has a single, clear purpose
- ✅ Clear interfaces: Modules communicate through well-defined APIs
- ✅ Minimal coupling: Changes in one module shouldn't break others
- ✅ Independent testing: Each module can be tested in isolation
- ✅ No circular dependencies: Keep dependency graph acyclic
src/engine/ → Pure game logic (no React dependencies)
src/components/ → React UI (no direct game logic)
src/utils/ → Shared utilities (no dependencies on engine or components)
Example of Good Modularity:
// ✅ GOOD: Clear interface, no coupling
// engine/physics.ts
export function calculateTrajectory(angle: number, power: number, time: number): Position {
// Pure calculation, no side effects
}
// components/Canvas.tsx
import { calculateTrajectory } from '../engine/physics'
// Uses physics as a dependency, but physics doesn't know about CanvasExample of Poor Modularity:
// ❌ BAD: Tight coupling
// engine/physics.ts
import { Canvas } from '../components/Canvas' // Engine shouldn't import components!- TypeScript Strict Mode: No
anytypes, proper type definitions - Descriptive Names:
calculateProjectileVelocity()notcalc() - Small Functions: <50 lines, single responsibility
- DRY Principle: Extract common logic into utilities
- Error Handling: Handle edge cases gracefully
- Comments: Only when necessary - prefer self-documenting code
Before committing, ALL of these must pass:
npm run build # TypeScript compilation
npm run lint # Code style and quality
npm test # Test suiteIf any fail, fix them before committing.
This project uses beads (bd CLI) for issue tracking. All work items are tracked as issues with dependencies.
bd ready # Show issues ready to work (no blockers)
bd list # List all issues
bd show <id> # View detailed issue information
bd update <id> --status=in_progress # Claim a task
bd close <id> # Mark task complete
bd stats # Project statistics🚨 STOP - READ BEFORE CODING 🚨
ALL work MUST be done on feature branches. Each issue gets its own branch named after the issue ID.
- NEVER work directly on master - Always create a feature branch first
- Every change needs a bead - Create issue first using
bd create - Write tests - No code without tests
- Run quality gates - Build + lint + test must ALL pass
# 1. Find and claim work (or create new issue if needed)
bd ready
bd update <issue-id> --status=in_progress
# 2. Create feature branch from master
git checkout master && git pull
git checkout -b <issue-id>
# 3. Implement the feature
# ... make changes, write tests ...
# 4. Verify ALL quality gates pass
npm run build && npm run lint && npm test
# 5. Commit to feature branch
git add <files>
git commit -m "Description
Closes <issue-id>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
# 6. Push feature branch to remote
git push -u origin <issue-id>
# 7. Merge to master
git checkout master
git pull
git merge <issue-id>
git push
# 8. Clean up (keep remote branch for history)
git branch -d <issue-id>
# Do NOT delete remote branch - keep for reference
bd close <issue-id>
bd syncNote: Remote feature branches are preserved for historical reference and traceability.
Traceability: Every commit must reference its beads issue ID (e.g., "Closes tanks-xyz") to maintain complete project history and enable proper tracking.
See AGENTS.md for complete detailed workflow instructions with examples.
- ✅ Project initialization (Node.js/React/TypeScript)
- ✅ Vite build tooling setup
- ✅ Basic project structure
- ✅ TypeScript strict mode configuration
- ✅ Development environment verified
- Set up organized folder structure (components, engine, utils)
- Establish canvas rendering infrastructure
- Implement terrain generation algorithm
- Create tank entity system
- Set up game state management
- Loading screen with animations
- Start button and game initialization
- Physics engine for projectile motion
- UI controls for angle and power selection
- Turn management system
- Projectile animation and rendering
- Collision detection (terrain and tank)
- Explosion animations
- Win conditions and game over state
- Physics calibration and tuning
View all tracked issues: bd list --status=open
The game will use React state management (Context API or similar) to track:
- Current game phase (loading, menu, playing, game over)
- Active player turn
- Tank states (position, health, angle, power)
- Terrain data
- Projectile state during flight
- HTML5 Canvas for all game rendering
- React component wrapper for canvas management
- Requestanimationframe for smooth 60fps animation
- Responsive canvas sizing based on viewport
- Custom physics calculations for projectile motion
- Frame-independent physics using delta time
- Realistic ballistic trajectories with gravity
- Collision detection with pixel-perfect accuracy for explosions
App
├── LoadingScreen (with animations)
├── MenuScreen (with Start button)
└── GameScreen
├── Canvas (terrain, tanks, projectiles)
├── ControlPanel
│ ├── AngleSelector
│ ├── PowerSelector
│ └── FireButton
└── GameOverScreen (winner announcement)
The initial version focuses on core gameplay. Future enhancements may include:
- Multiple terrain generation algorithms
- Wind effects on projectile trajectory
- Destructible terrain (explosions create craters)
- Multiple weapon types
- Power-up items
- Sound effects and music
- Multiplayer networking
- AI opponents
- Campaign mode
- Custom tank skins and colors
When working on this project:
- Check
bd readyfor available tasks - Read task descriptions carefully in
bd show <id> - Follow the established project structure
- Write TypeScript with strict typing
- Test changes before committing
- Follow the workflow in
AGENTS.md - Update this README when adding major features or changing architecture
This is a personal project - license TBD.
Repository: https://github.com/LupusDei/tanks