Underground 2 Revived
Chrome과 Firefox에서 Need for Speed Underground 2를 WebGPU로 두고 팬 프로젝트입니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A 3D lightsaber dueling game. Two players each bring their own laptop + phone — the phone is the sword controller, the laptop renders a first-person view with head-coupled parallax.
Player 1's Phone ──┐ ┌── Player 1's Laptop (first-person view)
(gyro sword) ├── Server ────┤
Player 2's Phone ──┘ (authoritative)└── Player 2's Laptop (first-person view)
(gyro sword) game state
npm install
npm run dev
Player 1 opens http://localhost:3000/player/ on their laptop. Player 2 opens the same URL (or the tunnel URL if remote). Each player scans the QR code on their laptop with their phone.
iOS Safari requires HTTPS for DeviceOrientation/DeviceMotion.
# In a second terminal:
npm run tunnel
This runs cloudflared tunnel --url http://localhost:3000 and gives you a temporary HTTPS URL. Both players open that URL on their laptops — the QR codes will point phones to the tunnel.
Install cloudflared: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/
# In a second terminal:
npx ngrok http 3000
Gives you an HTTPS URL like https://xxxx.ngrok-free.app. Open that on your laptop instead of localhost — QR codes will point phones to the tunnel.
Note: ngrok free tier shows a "Visit Site" interstitial page. On your phone, you may need to open the base tunnel URL first, tap "Visit Site", then scan the QR code.
mkcert -install
mkcert localhost 192.168.x.x # your LAN IP
SSL_CERT=./localhost+1.pem SSL_KEY=./localhost+1-key.pem npm run dev
Safari can't do proper vibration on iPhone, so mobile/ is an Expo app version of the phone controller with layered Taptic haptics: a metallic clang on blade clashes, a thud that scales with swing power on hits, and a long rumble on smashes. It runs inside the free Expo Go app; no Xcode, Mac, or Apple developer account needed.
cd mobile
npm install
npx expo start # scan the QR it prints with your iPhone camera (opens Expo Go)
Then in the app, scan the QR code on your laptop. Phone and laptop must be on the same Wi-Fi as the game server (the app talks to it over plain ws:// on port 3000, so no certificate setup). Tunnel URLs work too.
Notes:
/player/ on their laptop| Class | Ability | Cooldown | Description |
|---|---|---|---|
| Guardian | Shockwave Push | 12s | Short-range blast that knocks opponent back |
| Striker | Overcharge | 15s | 4s of double knockback + longer blade |
| Mystic | Barrier | 18s | 3s bubble that auto-blocks everything |
| Phantom | Blink | 8s | Instant short dash in saber direction |
Add ?test to the player URL: http://localhost:3000/player/?test
Add ?debug to the player URL: http://localhost:3000/player/?debug
In src/shared/constants.ts:
export const FEATURES = {
HEAD_TRACKING: true, // Webcam head tracking for parallax
PARALLAX_CAMERA: true, // Off-axis head-coupled perspective
};
src/
├── server/
│ ├── index.ts # Express + Vite + WebSocket server (single port)
│ ├── session.ts # Game session: 2 slots, token-based phone linking
│ └── GameServer.ts # Authoritative game engine (physics, combat, rounds)
├── shared/
│ ├── protocol.ts # All message types (controller↔server↔player)
│ ├── math.ts # Vec3/Quat classes (no Three.js, used server-side)
│ ├── collision.ts # Segment/capsule collision (shared math)
│ ├── classes.ts # Class configs (stats, abilities)
│ └── constants.ts # Game constants + feature flags
└── client/
├── player/
│ ├── index.html # Player laptop page
│ ├── styles.css
│ ├── main.ts # Entry: lobby, QR, networking, game init
│ ├── network.ts # WebSocket client (role=player)
│ ├── FakeController.ts # Debug keyboard/mouse controller
│ ├── HeadTracker.ts # MediaPipe face tracking → parallax
│ └── game/
│ ├── GameRenderer.ts # First-person Three.js renderer
│ ├── Arena.ts # 3D arena: platform, water, sky, lighting
│ ├── Fighter.ts # Render-only character (snapshot interpolation)
│ ├── Saber.ts # Saber with glow, bloom, motion trail
│ ├── VFX.ts # Particles, sparks, hit flashes, screen shake
│ └── Audio.ts # Web Audio: sample SFX from public/sfx, synth hum + fallbacks
└── controller/
├── index.html # Phone controller page
├── styles.css
├── main.ts # Entry: permissions, token linking, UI, streaming
├── network.ts # WebSocket client (role=controller)
├── orientation.ts # DeviceOrientation → quaternion math
└── haptics.ts # Layered haptics (vibrate / iOS switch / flash)
ws WebSocket on a single portsrc/client/public/sfx/): CC0 packs from Kenney and OpenGameArt; per-file sources in src/client/public/sfx/CREDITS.txtsrc/client/public/models/golden-gate.glb; its built-in water slab is hidden at load)