Home
Relevant source files
The following files were used as context for generating this wiki page:
Farm Siege is an engaging browser game where players grow and defend crops under pressure to achieve the highest score possible. It is built from scratch in TypeScript using a custom canvas-based game engine. The game logic is contained within the /src directory, while the engine code is in /lib. High scores are persisted in an Upstash Redis store.
The application is a single-page game that loads into a <canvas> element. The initial entry point is index.html, which loads the main TypeScript module (/src/main.ts) and the game's stylesheet. The game features a start screen, a game screen, a game-over screen with high scores, and a help section.
Sources: README.md, index.html:1-40, src/Game.ts
Project Architecture
The project is built using Vite, as indicated by the scripts in package.json. The core of the application is the Game class, which acts as the root component, managing various screens, overlays, and data stores.
Sources: package.json:10-12, src/Game.ts:21
Initial Load Flow
The diagram below illustrates the sequence of events when a user first loads the game.
This diagram shows the initial loading process, from serving the main HTML file to displaying the start screen after the splash animation.
Sources: index.html:30, src/styles.css:2-5, src/Game.ts:161-171, src/overlays/SplashScreen.ts:15
Core Components & Stores
The game utilizes a component-based architecture with a central state management system composed of multiple "stores". The main Game class initializes and registers all necessary stores, which manage different parts of the game's state.
Key stores include:
CharacterStore: Manages the player character's state.GridStore: Manages the state of the game grid, including plants and other tile contents.MovablesStore: Manages moving entities like rabbits.StatsStore: Tracks the player's score and game duration.ScreensStore: Manages the currently active screen.MiscStore: Handles miscellaneous state like high scores and splash screen status.
Sources: src/Game.ts:174-187
Screens and Navigation
The game's UI is divided into several distinct screens, managed by the ScreensStore. The Game component conditionally renders the active screen based on the state of this store.
The primary screens are:
SplashScreen(Overlay)StartScreenGameScreenHelpScreenGameOverScreenCosmeticsScreenCreditsScreen
Sources: src/Game.ts:121-147
Screen State Transitions
The following diagram shows the possible navigation paths between the main screens of the game.
This diagram illustrates the user's journey through the different game states, from the initial splash screen to the game over screen and back.
Sources: src/screens/StartScreen.ts:25-72, src/Game.ts:92-105, src/screens/GameOverScreen.ts:130-137
Start Screen
The StartScreen is the main menu of the game. It presents the player with several options, each triggering a change in the ScreensStore to navigate to a different part of the application.
| Button | Action |
|---|---|
| Play | Resets game stores. If the player has not seen the help screen before (checked via a cookie), it navigates to HelpScreen first. Otherwise, it navigates directly to GameScreen. |
| Help | Navigates to the HelpScreen to show the "HOW TO PLAY" instructions. |
| Cosmetics | Navigates to the CosmeticsScreen. |
| Credits | Navigates to the CreditsScreen. |
Sources: src/screens/StartScreen.ts:22-104
Key Features
High Score Submission
When a game ends, the GameOverScreen is displayed. If the player's score is greater than zero, they can submit it to the high score leaderboard. This process involves both the client and a serverless API endpoint.
The submission flow is as follows:
- The user enters their name in the input field on the
GameOverScreen. - The client requests a reCAPTCHA token.
- A
POSTrequest is sent to/api/submitScorewith the name, score, and reCAPTCHA token. - The API endpoint validates the request data and the reCAPTCHA token.
- If valid, the score is added to the
highscoressorted set in Upstash Redis.
Sources: src/screens/GameOverScreen.ts:50-92, api/submitScore.ts
The sequence diagram below details the interaction between the client, Google reCAPTCHA, the API, and the Redis database.
The /api/submitScore endpoint is defined as a Vercel Edge Function. It validates the incoming payload against a zod schema.
Sources: api/submitScore.ts:4, api/submitScore.ts:23-27
Player Input
Player input is managed by the InputMap class within CharacterContainer. It maps keyboard keys and gamepad buttons to game actions like movement, using items, placing items, and firing the gun. The input map is enabled only when the GameScreen is active.
| Action | Keyboard Keys | Gamepad Buttons |
|---|---|---|
up | W, ArrowUp | LeftStickUp |
left | A, ArrowLeft | LeftStickLeft |
down | S, ArrowDown | LeftStickDown |
right | D, ArrowRight | LeftStickRight |
use | Space | ButtonB |
place | V | ButtonA |
fire | C | ButtonX (single press) |
Sources: src/components/CharacterContainer.ts:26-48, 54-62
Dependencies
The project relies on several third-party libraries for its functionality, defined in package.json.
Production Dependencies
| Package | Version | Description |
|---|---|---|
better-timer | ^2.0.4 | Used for timing-related game logic. |
clone-deep | ^4.0.1 | For deep cloning objects, likely for state management. |
eases | ^1.0.8 | Provides easing functions for animations. |
js-cookie | ^3.0.5 | Used to manage the helpShown cookie. |
load-script | ^2.0.0 | For dynamically loading external scripts like the reCAPTCHA API. |
zod | ^3.24.2 | Schema validation for the submitScore API endpoint. |
Development Dependencies
| Package | Version | Description |
|---|---|---|
vite | ^6.2.7 | The build tool and dev server for the project. |
typescript | ^5.8.2 | The language used for the entire codebase. |
eslint | ^8.28.0 | For code linting and quality checks. |
prettier | ^3.5.3 | For code formatting. |
Sources: package.json:13-25, 26-37