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를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
El juego sigue funcionando exactamente igual que antes. Lo único nuevo es una pestaña GLOBAL junto a la de LOCAL, y una pregunta al terminar una partida de invasión. Si no despliegas nada de esto, el juego funciona igual: la pestaña GLOBAL simplemente avisará de que no pudo conectar. index.html va en la raíz. La carpeta api/ es lo que Vercel convierte automáticamente en endpoints: api/scores.js se publica como /api/scores. 1. Crear la base de datos en NeonREADME 전문 보기 ↗
El juego sigue funcionando exactamente igual que antes. Lo único nuevo es una pestaña GLOBAL junto a la de LOCAL, y una pregunta al terminar una partida de invasión. Si no despliegas nada de esto, el juego funciona igual: la pestaña GLOBAL simplemente avisará de que no pudo conectar.
tu-repo/
├── index.html (el juego)
├── package.json
├── schema.sql (ranking global)
├── schema_salas.sql (salas del multijugador en línea)
└── api/
├── scores.js (función de servidor: ranking)
└── salas.js (función de servidor: salas)
index.html va en la raíz. La carpeta api/ es lo que Vercel convierte
automáticamente en endpoints: api/scores.js se publica como /api/scores.
schema.sql y pulsa Run.schema_salas.sql y pulsa Run (sin esto, el
multijugador en línea no funciona).postgresql://. Marca la opción Pooled connection si aparece.Guarda esa cadena: es la que usarás como DATABASE_URL.
Vuelve a pegar y ejecutar los dos archivos, schema.sql y
schema_salas.sql, en el SQL Editor de Neon. Están hechos para ejecutarse
sobre una base existente: no borran ni cambian ningún puntaje, solo añaden lo
que falte:
alien,
viltrum, dragon, maquina, mago y boros), tanto en el ranking como
en las salas;ranking_alien,
ranking_viltrum, ranking_dragon, ranking_maquina, ranking_mago y
ranking_boros.
Sirven para ver cada tabla de puntajes desde Neon
(SELECT * FROM ranking_mago;); el juego no las necesita.Después haz Redeploy en Vercel para que api/scores.js y api/salas.js
acepten a los personajes nuevos. Hasta entonces el servidor antiguo guardaba
lo suyo como si fuera la cría.
Cada personaje tiene su propio ranking: los cinco comparten la tabla scores
y se separan por la columna hero. En el navegador, los puntajes locales
también van por separado (invasion_scores, invasion_scores_vil,
invasion_scores_dra, invasion_scores_maq e invasion_scores_mag).
Cada mapa tiene además su propia tabla, global y local. Para activarlo en una
base que ya existía, vuelve a pegar y ejecutar schema.sql en el SQL Editor
de Neon y después haz Redeploy en Vercel. El script:
mapa (ciudad, alien o infierno); todos los puntajes
que ya tenías quedan como de la ciudad, sin perder ninguno;ranking_mapa_alien y ranking_mapa_infierno.Ejecuta schema.sql antes del Redeploy: el api/scores.js nuevo ya
consulta la columna mapa y, sin ella, el ranking global no cargaría.
En el navegador, los puntajes locales de los mapas nuevos añaden el nombre
del mapa a la clave (por ejemplo invasion_scores_alien o
invasion_scores_vil_infierno); los de la ciudad no cambian.
git init
git add index.html package.json schema.sql api/scores.js
git commit -m "Invasión Tentacular con ranking global"
git branch -M main
git remote add origin https://github.com/TU-USUARIO/TU-REPO.git
git push -u origin main
Entra en https://vercel.com y accede con tu cuenta de GitHub.
Add New → Project e importa el repositorio.
En Framework Preset deja Other. No hace falta build command.
Antes de desplegar, abre Environment Variables y añade:
| Name | Value | Environments |
|---|---|---|
DATABASE_URL | la cadena postgresql://… de Neon | Production, Preview, Development |
Pulsa Deploy.
Si añades la variable después del primer despliegue, entra en Settings → Environment Variables, guárdala y luego Deployments → ⋯ → Redeploy, porque las variables se leen al construir.
En tu proyecto de Vercel, Storage → Connect Database → Neon. Al vincularlo,
Vercel crea DATABASE_URL por ti y no tienes que copiar nada a mano.
https://tu-proyecto.vercel.app/api/scores?hero=dragon debe responder
{"ok":true,"hero":"dragon","scores":[…]} (vacío al principio).https://tu-proyecto.vercel.app/api/scores debe responder
{"ok":true,"scores":[]}.Si algo falla, Vercel → Deployments → Functions muestra los registros de
/api/scores.
| Variable | Obligatoria | Para qué |
|---|---|---|
DATABASE_URL | sí | Conexión a Neon. Solo la lee el servidor. |
La cadena nunca aparece en el HTML ni en el JavaScript del navegador: el
juego solo conoce la ruta /api/scores.
GET /api/scores?limit=25&hero=alienHay una tabla por personaje, igual que en el ranking local. hero acepta
alien, viltrum, dragon, maquina, mago o boros; si se omite, devuelve el
ranking conjunto.
{ "ok": true, "scores": [
{ "id": 1, "player_name": "ZORA", "score": 99000,
"hero": "alien", "device": "pc", "created_at": "2026-09-11T12:00:00.000Z" }
]}
limit admite de 1 a 100; por defecto 25. El campo hero de la respuesta
indica de qué tabla se trata, o null si vienen mezclados.
GET /api/scores?hero=alien&name=ZORAConsulta la posición de un jugador concreto, para poder decirle en qué puesto está cuando no entra en los 25 visibles.
{ "ok": true, "encontrado": true, "hero": "alien",
"score": 9000, "rank": 4, "total": 128 }
Si ese jugador nunca subió nada con ese personaje: { "ok": true, "encontrado": false }.
POST /api/scores{ "player_name": "ZORA", "score": 99000, "hero": "alien", "device": "pc" }
Cada jugador tiene un solo registro por personaje: el de su mejor partida.
{ "ok": true, "mejorado": true, "score": 99000, "rank": 3, "total": 128, "hero": "alien" }
201 y mejorado: true → era mejor que la marca anterior y se guardó.200 y mejorado: false → ya tenía una marca igual o mejor; la tabla no se
toca y score devuelve la que conserva.Quién decide es la base de datos, con ON CONFLICT ... WHERE scores.score < EXCLUDED.score, así que dos partidas terminadas a la vez no pueden pisarse.
El servidor no se fía del navegador y rechaza con 400:
Además recorta el nombre a 14 caracteres, le quita etiquetas y caracteres de
control, y normaliza hero y device a los valores conocidos.
SaveIO, localStorage, saveScore(), loadScores(),
renderScoreList(), commitName() y pendingScore siguen tal cual.