Project Structure
Relevant source files
The following files were used as context for generating this wiki page:
Farm Siege is a browser-based game built with TypeScript. The project has a well-defined structure that separates the custom game engine, the game-specific logic, and the backend API services. The frontend is powered by a custom canvas-based rendering engine and a component-based architecture, while the backend consists of serverless functions for features like highscores.
The project uses Vite for its development server and build process. State management is handled through a series of dedicated "Store" classes, which provide a centralized way to manage and subscribe to changes in the game's state.
Sources: README.md:5-7, package.json:10-12
Overall Architecture
The project is logically divided into three main parts: the game engine (lib), the game application logic (src), and the serverless backend (api).
This diagram illustrates the high-level organization of the codebase.
Sources: README.md:7, src/main.ts, api/highscores.ts, api/submitScore.ts
Key Directories
| Directory | Purpose |
|---|---|
src/ | Contains all the game-specific logic, including components, screens, stores, and assets. |
lib/ | Houses the custom, reusable game engine code, including the main Canvas class and base Component. |
api/ | Contains serverless functions that act as the backend for the game (e.g., highscore handling). |
Sources: README.md:7
Frontend Application
The frontend is a single-page application responsible for all rendering and gameplay logic.
Application Entry Point
The application starts with index.html, which is the main HTML document. It contains a <canvas> element and loads the main TypeScript module, src/main.ts.
The src/main.ts file initializes the game by creating a new Canvas instance, linking it to the HTML canvas element, and setting Game as the root component.
Sources: index.html:32, 37, src/main.ts:6-13
Game Engine (lib/)
The lib/ directory contains a custom game engine. Its core is the Canvas class.
Canvas Class
The Canvas class is the heart of the rendering engine. Its responsibilities include:
- Initializing the 2D rendering context from an HTML
<canvas>element. - Managing the main render loop using
window.requestAnimationFrame. - Calculating the time difference between frames (
timeDifference) for smooth animations. - Handling screen resizing and scaling to maintain aspect ratio.
- Propagating user input events (click, keypress, etc.) to the root component.
- Rendering the root component (
Game) and its children on every frame.
Sources: lib/Canvas.ts:25-30, 40-55, 80-104
Game Logic (src/)
The src/ directory contains all the logic and assets specific to Farm Siege.
Root Component (Game.ts)
Game.ts is the top-level component for the entire application. It orchestrates the main parts of the game:
- Store Initialization: It creates instances of all state stores (e.g.,
CharacterStore,GridStore,ScreensStore) and registers them. - Screen Management: It renders the active screen (
StartScreen,GameScreen,GameOverScreen, etc.) based on the state fromScreensStore. - Global Game Loop (
onTick): It contains the primary game loop logic that runs on every frame. This includes updating timers, checking for game-over conditions, and updating game speed. - Asset Loading: It handles loading external scripts like Google reCAPTCHA and manages background music.
Sources: src/Game.ts:20, 92-120, 180-194
State Management (Stores)
The game uses a "Store" pattern for state management. Each store is a class that extends Store and manages a specific slice of the application's state.
This diagram shows how components interact with stores to get data and trigger updates.
Key stores include:
ScreensStore: Manages which screen is currently active.StatsStore: Tracks the player's score and game duration.GridStore: Manages the state of the 8x8 game grid.CharacterStore: Manages the player character's position, state, and held items.MiscStore: Handles miscellaneous state like highscores, splash screen visibility, and reCAPTCHA status.
Sources: src/Game.ts:180-194, src/components/ScoreCounter.ts:26-28, src/store/MiscStore.ts
Screen and Component Architecture
The UI is built using a tree of components, starting from the root Game component.
- Screens: High-level components like
StartScreen,GameScreen, andGameOverScreenrepresent different states of the application. Only one is active at a time, controlled by theScreensStore. - Components: Smaller, reusable pieces of UI or logic, such as
CharacterContainer,GridTile, orScoreCounter. - Templates: Each component defines a
templatearray, which declares its child components, their positions, and their properties. This creates a declarative, hierarchical structure.
Sources: src/Game.ts:122-178, src/screens/StartScreen.ts:104-187, src/components/grid/GridTile.ts:32-137
Backend API (api/)
The backend is composed of serverless functions located in the api/ directory. These functions handle operations that require a server, such as managing highscores.
Highscore System
The highscore system consists of two main endpoints.
This diagram shows the flow of submitting a new highscore.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/highscores | Fetches the list of highscores from the Upstash Redis database. |
POST | /api/submitScore | Submits a new score. It validates the input with Zod, verifies a reCAPTCHA token, and saves to Redis. |
Sources: src/store/MiscStore.ts:58-60, api/submitScore.ts:25, 30-38
Data Validation
The /api/submitScore endpoint uses zod to validate the incoming request body. The expected schema is:
| Field | Type | Constraints |
|---|---|---|
name | string | min(1), max(20) |
score | number | int(), min(0) |
recaptcha | string | - |
Sources: api/submitScore.ts:25-29
Build and Dependencies
The project's build process and dependencies are defined in package.json.
Scripts
| Script | Command | Description |
|---|---|---|
dev | vite | Starts the Vite development server. |
build | vite build | Creates a production build of the project. |
lint | eslint **/*.ts | Lints all TypeScript files. |
format | prettier --write . | Formats the codebase with Prettier. |
Sources: package.json:9-13
Key Dependencies
vite: The build tool and development server.typescript: The language used for the entire project.zod: Used for schema validation in the backend API.better-timer: A dependency used for timing-related logic.eases: A library for easing functions, likely used in animations.
Sources: package.json:16-24