Skip to content

Commit 834d915

Browse files
Update branding to Doom Simulation, show current level in title bar
- Rename all references from ViZDoom Web Player to Doom Simulation - Dynamically update page title and header with current map name while playing - Add current_map to server state dict for level-aware title updates - Rewrite README for the actual project Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 03fc291 commit 834d915

4 files changed

Lines changed: 85 additions & 182 deletions

File tree

README.md

Lines changed: 64 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -1,203 +1,88 @@
1-
# Bespoke Simulation Template
2-
3-
This directory contains a template for creating embedded applications that share a consistent design system and user experience.
4-
5-
## Components
6-
7-
### 1. Design System Integration
8-
This template uses the CodeSignal Design System located in `client/design-system/`:
9-
- **Foundations**: Colors, spacing, typography tokens
10-
- **Components**: Buttons, boxes, inputs, dropdowns, tags
11-
- Light and dark theme support (automatic)
12-
- See the [design system repository](https://github.com/CodeSignal/learn_bespoke-design-system) for full documentation
13-
14-
### 2. `client/bespoke-template.css`
15-
Template-specific CSS providing:
16-
- Layout components (header, sidebar, main-layout)
17-
- Utility classes (row, spacer)
18-
- Temporary components (modals, form elements) - will be replaced when design system adds them
19-
20-
### 3. `client/index.html`
21-
A base HTML template that includes:
22-
- Navigation header with app name and help button
23-
- Main layout structure (sidebar + content area)
24-
- Help modal integration
25-
- Proper CSS and JavaScript loading
26-
27-
### 4. `client/help-modal.js`
28-
A dependency-free JavaScript module for the help modal system:
29-
- Consistent modal behavior across all apps
30-
- Keyboard navigation (ESC to close)
31-
- Focus management
32-
- Custom event system
33-
34-
### 5. `client/help-content-template.html`
35-
A template for creating consistent help content:
36-
- Table of contents navigation
37-
- Standardized section structure
38-
- FAQ with collapsible details
39-
- Image integration guidelines
40-
41-
## Usage Instructions
42-
43-
### Setting Up a New Application
44-
45-
1. **Clone the repository**
46-
2. **Ensure the design-system submodule is initialized**:
47-
```bash
48-
git submodule update --init --recursive
49-
```
50-
51-
3. **Customize the HTML template** by replacing placeholders:
52-
- `<!-- APP_TITLE -->` - Your application title
53-
- `<!-- APP_NAME -->` - Your application name (appears in header)
54-
- `<!-- APP_SPECIFIC_HEADER_CONTENT -->` - Any additional header elements
55-
- `<!-- APP_SPECIFIC_MAIN_CONTENT -->` - Your main content area
56-
- `<!-- APP_SPECIFIC_CSS -->` - Links to your app-specific CSS files
57-
- `<!-- APP_SPECIFIC_SCRIPTS -->` - Links to your app-specific JavaScript files
58-
59-
3. **Use Design System Components**
60-
The template uses design system components directly. Use these classes:
61-
- Buttons: `button button-primary`, `button button-secondary`, `button button-danger`, `button button-text`
62-
- Boxes/Cards: `box card` for card containers
63-
- Inputs: Add `input` class to input elements: `<input type="text" class="input" />`
64-
65-
4. **Implement your application logic**. You can use Cursor or other agents for it. There is a file called `AGENTS.md` that contains context LLM can use.
66-
5. **Customise your help content** using the help content template
67-
3. **Use Design System Components**
68-
The template uses design system components directly. Use these classes:
69-
- Buttons: `button button-primary`, `button button-secondary`, `button button-danger`, `button button-text`
70-
- Boxes/Cards: `box card` for card containers
71-
- Inputs: Add `input` class to input elements: `<input type="text" class="input" />`
72-
73-
4. **Implement your application logic**. You can use Cursor or other agents for it. There is a file called `AGENTS.md` that contains context LLM can use.
74-
5. **Customise your help content** using the help content template
75-
76-
### Customizing Help Content
77-
78-
Use the `help-content-template.html` as a starting point:
79-
80-
1. **Replace placeholders** like `<!-- APP_NAME -->` with your actual content
81-
2. **Add sections** as needed for your application
82-
3. **Include images** by placing them in a `help/img/` directory
83-
4. **Use the provided structure** for consistency across applications
84-
85-
86-
### Help Modal API
87-
88-
The `HelpModal` class provides several methods:
89-
90-
```javascript
91-
// Initialize
92-
const modal = HelpModal.init({
93-
triggerSelector: '#btn-help',
94-
content: helpContent,
95-
theme: 'auto'
96-
});
97-
98-
// Update content dynamically
99-
modal.updateContent(newHelpContent);
100-
101-
// Destroy the modal
102-
modal.destroy();
103-
```
104-
105-
## Server
106-
107-
This template includes a local development server (`server.js`) that provides:
108-
- Static file serving for your application
109-
- WebSocket support for real-time messaging
110-
- A REST API for triggering client-side alerts
111-
112-
### Starting the Server
113-
114-
```bash
115-
# Local development
116-
npm run start:dev # Vite + API for local development
117-
# Production
118-
npm run build # Create production build in dist/
119-
npm run start:prod # Serve built assets from dist/
120-
```
121-
122-
123-
### Environment Variables
124-
125-
The server supports the following environment variables:
126-
127-
- **`PORT`** - Server port number
128-
- Development: Can be set to any port (e.g., `PORT=3001`), defaulting to `3000`
129-
- Production: Ignored (always `3000` when `IS_PRODUCTION=true`)
1+
# Doom Simulation
1302

131-
- **`IS_PRODUCTION`** - Enables production mode
132-
- Set to `'true'` to enable production mode
133-
- When enabled:
134-
- Server serves static files from `dist/` directory
135-
- Port is forced to `3000`
136-
- Requires `dist/` directory to exist (throws error if missing)
3+
Browser-playable Doom powered by [ViZDoom](https://vizdoom.cs.put.edu.pl/). Streams video and audio from a Python backend to a web client over WebSocket.
1374

5+
## Features
1386

139-
### Vite Build System
7+
- **Campaign mode** — Play Doom 1 (4 episodes) and Doom 2 with difficulty selection
8+
- **Test levels** — Run individual ViZDoom scenarios for experimentation
9+
- **Full audio/video streaming** — 1920x1080 JPEG video + stereo PCM audio over WebSocket
10+
- **Browser input** — WASD movement, mouse look, weapon selection, all in the browser
11+
- **Level progression** — Inventory carry-over between levels, kill/item/secret stats
12+
- **REST API** — Programmatic game control for AI agents
14013

141-
This project uses [Vite](https://vitejs.dev/) as the build tool for fast development and optimized production builds.
14+
## Prerequisites
14215

143-
#### Build Process
16+
- Python 3.11+
17+
- Node.js 22+
18+
- ViZDoom (`pip install vizdoom`)
19+
- `doom.wad` and `doom2.wad` in the project root
14420

145-
Running `npm run build` executes `vite build`, which:
146-
- Reads source files from the `client/` directory (configured in `vite.config.js`)
147-
- Processes and bundles JavaScript, CSS, and other assets
148-
- Outputs optimized production files to the `dist/` directory
149-
- Generates hashed filenames for cache busting
21+
## Quick Start
15022

151-
### WebSocket Messaging API
152-
153-
The server provides a `POST /message` endpoint that allows you to send real-time messages to connected clients. This can be used to signal changes in the client during events like "Run" or "Submit". When a message is sent, the preview window with the application open will display an alert with the message.
154-
155-
It uses the `ws` package, so if you want to use it, install the packages (but this is optional).
156-
157-
```
23+
```bash
24+
# Install dependencies
25+
git submodule update --init --recursive
26+
pip install -r requirements.txt
15827
npm install
28+
29+
# Start development servers (Vite on :3000, API on :3001)
30+
npm run start:dev
15931
```
16032

161-
#### Endpoint: `POST /message`
33+
Open http://localhost:3000 in your browser.
16234

163-
**Request Format:**
164-
```json
165-
{
166-
"message": "Your message here"
167-
}
168-
```
35+
## Production
16936

170-
**Example using curl:**
17137
```bash
172-
curl -X POST http://localhost:3000/message \
173-
-H "Content-Type: application/json" \
174-
-d '{"message": "Hello from the server!"}'
38+
npm run build
39+
IS_PRODUCTION=true python3 server.py
17540
```
17641

177-
## CI/CD and Automated Releases
42+
The production server serves the built frontend from `dist/` and runs on port 3000.
43+
44+
## Controls
17845

179-
This template includes a GitHub Actions workflow (`.github/workflows/build-release.yml`) that automatically builds and releases your application when you push to the `main` branch.
46+
| Key | Action |
47+
|-----|--------|
48+
| W/A/S/D | Move |
49+
| Mouse | Look |
50+
| Left Click | Attack |
51+
| E / Space | Use / Interact |
52+
| Shift | Run |
53+
| 1-7 | Select weapon |
54+
| Escape | Pause |
18055

181-
### How It Works
56+
## Architecture
18257

183-
When you push to `main`, the workflow will:
58+
```
59+
client/ → Browser frontend (vanilla JS, Vite)
60+
app.js → Game UI state machine, menu navigation
61+
doom-client.js → WebSocket client, input capture, frame rendering
62+
doom.css → Game-specific styles
63+
server.py → FastAPI/Uvicorn backend, WebSocket + REST API
64+
game_manager.py → ViZDoom wrapper, game sessions, input handling
65+
```
18466

185-
1. **Build the project** - Runs `npm run build` to create production assets in `dist/`
186-
2. **Create a release tarball** - Packages `dist/`, `package.json`, `server.js`, and production `node_modules/` into `release.tar.gz`
187-
3. **Create a GitHub Release** - Automatically creates a new release tagged as `v{run_number}` with the tarball attached
67+
### API Endpoints
18868

189-
### Release Contents
69+
| Method | Path | Description |
70+
|--------|------|-------------|
71+
| `GET` | `/api/game/scenarios` | List available scenarios |
72+
| `POST` | `/api/game/start` | Create a new game session |
73+
| `POST` | `/api/game/{id}/action` | Send action, get frame + state |
74+
| `GET` | `/api/game/{id}/state` | Get current game state |
75+
| `POST` | `/api/game/{id}/reset` | Reset episode |
76+
| `DELETE` | `/api/game/{id}` | Destroy session |
19077

191-
The release tarball (`release.tar.gz`) contains everything needed to deploy the application:
192-
- `dist/` - Built production assets
193-
- `package.json` - Project dependencies and scripts
194-
- `server.js` - Production server
195-
- `node_modules/` - Production dependencies only
78+
## CI/CD
19679

197-
### Using Releases
80+
Pushing to `main` triggers the GitHub Actions workflow which builds the client, packages a release tarball (`dist/`, `server.py`, `game_manager.py`, `requirements.txt`, `package.json`), and creates a GitHub Release.
19881

199-
To deploy a release:
82+
## Scripts
20083

201-
1. Download `release.tar.gz` from the latest GitHub Release (e.g. with `wget`)
202-
2. Extract (and remove) the tarball: `tar -xzf release.tar.gz && rm release.tar.gz`
203-
3. Start the production server: `npm run start:prod`
84+
| Command | Description |
85+
|---------|-------------|
86+
| `npm run start:dev` | Vite dev server + Python API (concurrent) |
87+
| `npm run build` | Production build to `dist/` |
88+
| `npm run start:prod` | Production mode (Python serves `dist/`) |

client/app.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ function hideAll() {
3333
}
3434
}
3535

36+
// --- Title management ---
37+
38+
const DEFAULT_TITLE = 'Doom Simulation';
39+
40+
function updateTitle(text) {
41+
document.title = text;
42+
const el = document.getElementById('page-title');
43+
if (el) el.textContent = text;
44+
}
45+
3646
// --- State transitions ---
3747

3848
function setHudVisible(visible) {
@@ -45,6 +55,7 @@ function goToMenu() {
4555
gameMode = null;
4656
pendingCampaign = null;
4757
setHudVisible(true);
58+
updateTitle(DEFAULT_TITLE);
4859
doomClient.lockVerticalMouse = false;
4960
if (document.pointerLockElement) document.exitPointerLock();
5061
doomClient.setPaused(true);
@@ -68,6 +79,7 @@ function startScenario(name) {
6879
uiState = 'playing';
6980
hideAll();
7081
setHudVisible(true);
82+
updateTitle(name.replace('.cfg', ''));
7183
doomClient.lockVerticalMouse = false;
7284
doomClient.enableAudio(); // activate on user gesture
7385
doomClient.setScenario(name);
@@ -113,6 +125,11 @@ function updateHud(state) {
113125
if (ammo) ammo.textContent = `Ammo: ${Math.round(state.ammo)}`;
114126
if (kills) kills.textContent = `Kills: ${Math.round(state.kill_count)}`;
115127

128+
// Update title with current map name
129+
if (state.current_map && uiState === 'playing') {
130+
updateTitle(state.current_map);
131+
}
132+
116133
// Only react to episode end while actively playing
117134
if (uiState !== 'playing') return;
118135

client/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="utf-8" />
5-
<title>ViZDoom Web Player</title>
5+
<title>Doom Simulation</title>
66
<meta name="viewport" content="width=device-width, initial-scale=1" />
77
<!-- Fonts (Work Sans) -->
88
<link rel="preconnect" href="https://fonts.googleapis.com">
@@ -29,7 +29,7 @@
2929
<body class="bespoke">
3030
<!-- Navigation Header -->
3131
<header class="header">
32-
<h1 class="heading-small">ViZDoom Web Player</h1>
32+
<h1 id="page-title" class="heading-small">Doom Simulation</h1>
3333
<div class="spacer"></div>
3434
<button id="btn-menu" class="button button-secondary">Menu</button>
3535
<button id="btn-help" class="button button-text">Help</button>
@@ -56,7 +56,7 @@ <h1 class="heading-small">ViZDoom Web Player</h1>
5656

5757
<!-- Main Menu -->
5858
<div id="overlay-menu" class="game-overlay game-overlay-menu" style="display:none;">
59-
<h2 class="menu-title">ViZDoom Web Player</h2>
59+
<h2 class="menu-title">Doom Simulation</h2>
6060

6161
<!-- Campaign buttons -->
6262
<div class="menu-campaigns">

game_manager.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ def _get_state_dict(self) -> dict:
405405
"episode_finished": finished,
406406
"dead": dead,
407407
"total_reward": self.game.get_total_reward(),
408+
"current_map": self._current_map,
408409
}
409410
if self._level_total_kills is not None:
410411
result["total_kills"] = self._level_total_kills

0 commit comments

Comments
 (0)