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