Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
A 2D side-scrolling platformer. See BOCHUR_BROS_DESIGN.md for the design doc.
Current state: Milestone 1 — the jump. One character, one greybox test
level, a camera that follows. Nothing else, on purpose.
The quickest way is a hosted build — no install, just a link. `npm run
build:playtestproduces a flattened, self-contained page inplaytest/` that
can be published anywhere static. It is keyboard-only until Milestone 7 adds
touch controls, so play it on a computer.檢視完整 README ↗A 2D side-scrolling platformer. See BOCHUR_BROS_DESIGN.md for the design doc.
Current state: Milestone 1 — the jump. One character, one greybox test level, a camera that follows. Nothing else, on purpose.
The quickest way is a hosted build — no install, just a link. npm run build:playtest produces a flattened, self-contained page in playtest/ that
can be published anywhere static. It is keyboard-only until Milestone 7 adds
touch controls, so play it on a computer.
To run it locally instead:
npm install
npm run dev # then open http://localhost:5173
Other scripts: npm run build (typechecks, then bundles to dist/),
npm run build:playtest, npm run build:maps, npm run preview,
npm run typecheck.
Click the game once before using the keyboard — a page does not receive key presses until something inside it has been clicked. The start card says so.
| Arrows, Space | On the map: choose a level, play it |
| G | On the map: the greybox test levels |
| Backspace | On the map: wipe saved progress |
| Esc | In a level: back to the map |
| Tab or C | Swap brothers |
| Arrows / WASD | Move; hold Down to crouch |
| Space or Z | Jump — hold for height |
| Shift or X | Run |
| Down, airborne | Berel's ground pound |
| R | Respawn at the last checkpoint |
| F1 | Toggle the debug readout |
| F2 | Toggle collision boxes |
| F3 | Cycle levels |
Esc (pause) is bound but does nothing yet.
Measured, not guessed:
| Mendy | Berel | |
|---|---|---|
| Widest gap, running | 6 tiles | 5 |
| Tallest ledge, walking | 4 tiles | 3 |
| Reinforced blocks | never, in any form | breaks them |
| Crates | cannot budge one | shoves them |
| Weak floors | — | pounds through |
| Wind | blown back | ignores it |
Mendy moves on Super Mario Bros.' own figures: 90 px/s walking, 150 running, a four-tile standing jump and a five-tile running one. Holding the jump button does not add force, it lowers gravity — which is why a tap gives you one tile and a held button gives you four.
Both are in src/config/Tuning.ts:
riseSeconds in each jumpArc(...) line — how long the jump takes to
reach the top. Lower it and jumping feels faster without changing how high
it goes. Raise it and the jump floats.VIEW_WIDTH / VIEW_HEIGHT — how much of the world fits on screen.
320x180 shows 20 tiles across. A wider view makes everything read as slower,
because the same walking speed has more screen to cross.Everything that affects how the character moves lives in one file:
src/config/Tuning.ts. Vite hot-reloads it, so edit, save, and the page
picks it up. Values taken from the design doc are marked [SPEC]; values added
to make it playable are marked [ADDED] and explained.
The test level is a calibration range, not a level. Each lettered station measures one property of the jump:
| A | Flat ground — acceleration, top speed, stopping, pivoting |
| B | Pillars rising one tile at a time — how high you get |
| C | Gaps widening one tile at a time — how far you get |
| D | A ledge to run off and jump from late — coyote time |
| E | A staircase and a long drop — jump buffering |
| F | A two-tile-high tunnel — head collisions |
| G | A one-tile tunnel — crouching, and what Cholent cannot fit through |
There are no bottomless pits. Every gap has a floor a short hop below it, so missing a jump costs a walk back and nothing else.
Turn on F1 and the readout gives you the apex and the distance of your last jump in pixels and tiles, which is faster than arguing about it.
Levels are Tiled maps. src/levels/maps/*.tmj is the whole catalogue —
dropping a new .tmj in that folder adds it to the game, and no code changes.
Open any of them in Tiled to edit visually.
Each map uses two object layers:
| Layer | What it holds |
|---|---|
solids | Rectangles. Optional kind property: ground, platform, wall. |
entities | Objects tagged with Tiled's Class field (see below). |
Entity classes: spawn, goal, checkpoint, coin, crate, label
(property text), block (properties block = mystery/brick/reinforced/weak,
contents = coin/cholent), enemy (property enemy), wind (property
direction, −1 or 1; drawn as a rectangle).
Maps in tools/levels/ are generated by npm run build:maps — that exists
because levels with repetition (a staircase, a ladder of widening gaps) are
clearer as a loop than as a hundred hand-placed objects. Once you start editing
a map in Tiled, stop regenerating it.
Which levels exist, and in what order, is src/levels/catalog.ts.
src/
config/Tuning.ts every tunable number, and only tunable numbers
entities/ player, enemies, blocks, crates, pickups, hazards
input/ abstract actions; keyboard today, touch in Milestone 7
levels/maps/ the levels themselves, as Tiled .tmj files
levels/tiled/ the .tmj reader
levels/catalog.ts which levels exist and in what order
scenes/ boot, world map, level, HUD, debug overlay
systems/ power-up state machine, save game
util/ runtime placeholder-texture generation
tools/ level authoring scripts -> .tmj