尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Dust & Iron: a top-down western shooter built with Three.js and Rapier.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗A western with one life: two towns, a desert and a pine forest, outlaw camps, a gang boss, hunting, saloons and dice, in one shared online world for up to 20 people. Pick a name and spawn in; next time, continue as that rider. Built with Three.js, Rapier, and plain JavaScript modules.
Play at dustiron.vercel.app.
Fastest (no install): open dist-single/dustiron.html through any local static server, for example:
npx serve dist-single # then open the URL it prints
# or
python3 -m http.server -d dist-single 8080
Three.js and Rapier load from the jsDelivr CDN, so you need an internet connection.
Development (hot reload):
npm install
npm run dev
After editing anything in src/, rebuild the single-file version with npm run single.
The game server is plain Node (22 or newer) with no extra packages. It serves the game and runs the shared world: outlaws, camps, health, duels and money moved between riders.
Try it on your own machine:
npm install # three and rapier, which the server also uses
npm run server # http://localhost:8080
Open http://localhost:8080 in two browser windows (one private window works), type a name in each under Ride online, and you will see each other in Mercy Crossing. The world is saved in data/world.json.
?server=wss://example.com on the page URL points a statically hosted copy (Vercel, dist-single) at a server elsewhere.
Online rules
/y yell, /g world, /w Name whisper, /r reply; click a name to whisper. The rider list and ping are under the money.Deploy to Cloudflare (one shared world, sleeps when nobody plays, about $5–7 a month):
Needs the Workers Paid plan ($5/month), which includes Containers. The Worker serves the game page from Cloudflare's edge, and starts the game server container only when someone rides online; the server shuts itself down after 15 minutes with nobody online. The world is saved in the Worker's Durable Object storage, so it survives sleep and redeploys.
From GitHub (no Docker needed on your machine): in the Cloudflare dashboard, Workers & Pages → Create → Import a repository, pick this repo and branch, then set
npm run build:webnpx wrangler deployFrom your own machine (needs Docker Desktop running):
npx wrangler login
npm run deploy
The game is then at https://dustiron.<your-subdomain>.workers.dev. The first rider after a quiet spell waits a few seconds while the server wakes. instance_type in wrangler.jsonc sets the server size (basic is 1/4 CPU and 1 GiB; standard-1 doubles the CPU if the world lags).
Deploy to Fly.io (sleeps when nobody plays, about $3–5 a month):
fly launch --no-deploy --copy-config # pick an app name; keep fly.toml
fly volumes create dustiron_data --size 1
fly deploy
The machine stops when nobody is connected and starts again on the next visit (a few seconds). The world file lives on the volume, so it survives restarts and deploys.
| Action | Key |
|---|---|
| Move | W A S D |
| Aim | Mouse or trackpad |
| Shoot | Left click (hold for repeat fire) |
| Dodge roll | Space (brief invulnerability) |
| Reload | R |
| Dead Eye | Hold Shift (slow motion, needs meter) |
| Switch weapon | 1 2 3 or Q |
| Camera zoom | Mouse wheel |
| Talk or use a shop | E or Enter |
| Use a bandage | H |
| Smoke a cigarette or cigar | B |
| Chat (online) | Enter or T; /s say, /y yell, /g world, /w Name whisper, /r reply |
| Duel or dice with a rider (online) | G, then Y / X to answer |
| Map | M or Tab (pauses the fight) |
| Pause | Esc |
| Mute | N |
| Frame rate readout | I |
| Tuning panel | ` (backquote) |
Horses belong to their rider: others see them standing or ridden but cannot mount them. A browser tab in the background stops sending its rider's position (browsers pause hidden pages), so that rider stands still for everyone else until the tab comes back.
npm test
npm run build
npm run single
Tests cover life resets, map discovery, transactions, single bounty payments, saved combat state, finite reloads, and camp navigation. Use Chrome to check movement, aiming, menus, and visual changes.
src/
main.js boot and the fixed 60 Hz loop (time scale, interpolation)
game.js life loop, saving, Dead Eye, hit-stop, explosions
life.js seeded world data, inventory, jobs, map discovery, purchases
storage.js versioned browser saves, death records, old-save migration
frontier.js town buildings, walking civilians, roads, and desert
encounters.js camp placement, local path grids, and combat snapshots
town-actions.js talks, shops, and bounty menus
tuning.js every feel number in one place
input.js keyboard and mouse state
camera.js angled follow camera, look-ahead, trauma shake
render.js renderer, lights, shadow box that follows the player
physics.js Rapier world, collision groups, ray casts, interpolation
player.js movement, dodge roll, shooting, health and regen
weapons.js weapon data and the shared gun state machine
enemy.js bandit types, perception and the AI state machine
cover.js cover-point scoring
nav.js 0.5 m grid A* with path smoothing
props.js crates, barrels, explosive barrels, fences, debris
projectiles.js visible enemy bullets
level.js seeded camp layouts and scenery
models.js code-built low-poly models
character.js procedural animation and corpses
fx.js pooled particles, tracers, light flashes
audio.js synthesized sound effects (no audio files)
ui.js HUD, reticle, cards
map.js world map (M): explored land, roads, landmarks, and jobs
wilds.js desert and forest scenery, merged per chunk
town-pine.js Pine Hollow
wildlife.js animal simulation (browser offline, server online)
hunting.js animal models, skinning, online puppets
vices.js drink and tobacco effects
sky.js day, night and rain
net.js browser side of the server connection
net-world.js server-run outlaws, props and events in the browser
net-ui.js joining, chat, duels and dice
remote-players.js other riders
protocol.js message shapes shared with the server
server/
index.js HTTP + WebSocket server, game loop, saving
hub.js accounts, sessions, authority over health and money
sim.js the shared world: camps and outlaws, headless
duels.js dice.js rider-versus-rider games
store.js world.json on disk
ws.js dependency-free WebSocket
tools/bundle.mjs builds dist-single/ without npm