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분 만에 확인하기Military strategy board game
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A turn-based strategy card game on a 3D hexagonal battlefield, built with Next.js, React, TypeScript, Tailwind CSS and three.js (via React Three Fiber and drei).
src/lib/graphics.ts) - battle speed, vibration on phones that support it - castle hits, kills, a boss's strikes and the battle won or lost), quick battles (a one-off battle on a random map at easy, medium or hard) and the full guide to the rules.src/lib/campaign/daily.ts).src/app/manifest.ts): it then opens full screen from the home screen or app list, and Settings offers an Install button where the browser allows it (or explains Share, then Add to Home Screen, on iPhone and iPad). On phones it runs edge to edge, around notches and camera cutouts, with its buttons and panels kept clear of them (the --safe-* insets in globals.css).public/music/ to replace any of them (see its README).Every troop belongs to a class, and each class hits some others 50% harder (spears hit cavalry twice as hard), so no single army beats them all:
| Class | Strong against |
|---|---|
| Spear (Pikemen, lizardmen, scorpions) | Cavalry (x2), Brutes |
| Cavalry (Knights, wolves, wyverns) | Ranged, Casters |
| Ranged (Archers, Longbowmen) | Spears, Brutes |
| Infantry (Swordsmen, skeletons, orc grunts) | Spears, Skirmishers |
| Skirmisher (Rogues, spiders, imps, ghosts) | Ranged, Casters |
| Brute (Berserkers, bears, golems, ogres, giants) | Infantry |
| Caster (Mages, shamans, witches) | - but their spells ignore cover and line of sight |
Ranged troops caught in close combat fight at half strength. Every card and unit shows its class and what it is strong and weak against.
Every hex shows its height, a decimal number (water about 0.5, plains about 1.3, hills about 2.1, mountains about 2.7 - each hex varies a little). The height advantage comes from that number: every 1.0 of height the attacker stands above its target adds 30% damage, and every 1.0 below takes 30% away, rounded to a whole percent and capped at 50% either way - so even a small rise gives a small edge. Line of sight and ranged reach use height levels: water, swamp, ice and lava 0, most ground 1, hills and snow 2, mountains 3. Ranged troops on high ground reach one hex further. Shots at range are blocked by any hex in between that stands higher than both the shooter and the target: mountains block everything, ridges hide units from archers below, and forest canopies, ruined walls and village houses count one level higher. Spells arc over anything.
| Terrain | Height | Effect |
|---|---|---|
| Plains | 1 | No effect |
| Forest | 1 (trees 2) | Units take 40% less damage (except from spells); Pikemen attack 50% harder; blocks shots from below |
| Hills | 2 | High ground; costs 2 movement |
| Ruins | 1 (walls 2) | Units take 25% less damage (except from spells); blocks shots from below |
| Village | 1 (houses 2) | Units take 20% less damage (except from spells); the houses block shots from below |
| Desert | 1 | Costs 2 movement |
| Swamp | 0 | Low ground; costs 2 movement |
| Snow | 2 | High ground; costs 3 movement |
| Ice | 0 | Low ground; costs 2 movement |
| Spring | 1 | Heals 4 health at the end of each of your turns |
| Cursed Ground | 1 | Drains 2 health each turn - but heals the undead |
| Lava Field | 0 | Burns 4 health each turn (Fireborn troops are unharmed); costs 2 movement |
| Gold Mine | 1 | Pays its gold each turn while one of your units holds it |
| Mountains | 3 | Impassable (flyers pass over); blocks line of sight |
| Water | 0 | Impassable (flyers pass over) |
A unit can always step onto one neighbouring hex, however rough, even if that takes all of its movement.
Ranged, Long range, Spells (ignore cover and line of sight), Healer, Forest fighter, Sneak attack (no strike-back, except from other sneak attackers), Flying, Regenerates, Armored (2 less damage per fight), Siege (double castle damage), Berserk (+50% attack at half health), Undead, Pathfinder (rough ground costs 1) and Fireborn. Every card shows its abilities; hover them for details.
src/lib)game/troops.ts: Every troop - the Kingdom's 13 cards and the 50 monsters - with stats, abilities, rarity and lore; card levels and powergame/gameState.ts: Rules engine (pure functions): battle setup, the card hand, purchases, movement, combat (height, line of sight, counters, abilities), terrain, economy and upkeep, round limit and win conditionsgame/mapGenerator.ts: Seeded, themed map generation, including the campaign's region themesgame/hexUtils.ts: Hex grid mathsgame/signatures.ts: Each Kingdom card's signature ability, its condition and its numbers by rankgame/battlefield.ts: The battlefield's objects - great trees to fell and fires around lava - and their numbersgame/structures.ts: The buildings - watchtowers, houses, the catapult tower and the workshops - and their numbersgame/formations.ts: Fighting together: screens, pinning, shield walls and holding a crossinggame/bosses.ts: Each boss's power - strikes marked a turn ahead, minions, bites - and its ragegame/regionRules.ts: Faction traits, regional weather (fog banks, sandstorms, blizzards, ashfall) and moralegame/tutorialPlan.ts: The tutorial's plan for a turn, from the AI playing the player's side, with captionsai/aiPlayer.ts: The AI: scores every move on the fight it offers, the danger it walks into, the ground and its goal; recruits counters from whatever roster it has; plays either side, with selectable doctrines for simulationscampaign/levels.ts: The 15 regions and 150 levels: enemy rosters and scaling, bosses, star goals and rewardscampaign/battleSetup.ts: Builds a battle from a campaign level (or a quick battle) and the player's deckcampaign/challenges.ts: Each level's optional challenge and its bonuscampaign/daily.ts: The daily challenge: the day's battle from the date, its reward and the streakcloudSave.ts: Cloud save: syncing the profile with the cloud_saves table, choosing between two changed copies, and linking an emailgraphics.ts: The graphics setting and what each quality changes in the 3D sceneslegal.ts: The contact address and date shown on the privacy policy and termsmeta/economy.ts: Rewards, card prices, upgrade costs and the progression model behind recommended powerhaptics.ts: Vibration on phones, and its settingsrc/app)page.tsx: Main menu (components/game/intro/IntroScreen, with a 3D island of troops and monsters)campaign: The campaign map (each region an island of map tiles, laid out in lib/campaign/mapArt.ts and drawn by components/menu/RegionMap); tapping a level opens a callout from its spot (the enemy, your power against the recommended, weather, the challenge, the reward) with the button to fight it, and any empty deck slots are filled for the battle (components/menu/CampaignScreen, LevelPopup, battleDeck in lib/campaign/battleSetup.ts; suggestions in lib/meta/loadout.ts)army: Your cards, the card shop and upgrades (components/menu/ArmyScreen)bestiary: The bestiary and its 3D model viewer (components/menu/BestiaryScreen, TroopModelViewer)stats: Stats and save files (components/menu/StatsScreen); the main menu's settings and guide are in components/menu/SettingsPanelplay: A battle (/play?level=7, /play?mode=quick&difficulty=hard, or the daily challenge, /play?mode=quick&daily=2026-10-10)privacy, terms: The privacy policy and terms of service (components/menu/LegalPage), linked from the main menu and Settings; robots.ts and sitemap.ts list the public pages for search enginespvp: Battle Friends: the rooms page, a room's lobby (/pvp?room=ABC234) and its battle, and practice against the AI (components/arena/: PvpScreen, ArenaSettingsForm, ArenaBattle - the battle screen with the standings - and OnlineBattle)src/components/game)GameController: Runs a battle and lays out its HUD, records the result and shows the results screenGameBoard: The 3D board and camera (each turn it frames your troops and the enemies near them, just above the hand; drag or one finger to pan, right-drag or Shift-drag to turn and tilt, a two-finger twist to turn and two fingers slid up or down to tilt, scroll or pinch to zoom - but not while it flies somewhere on its own; selecting something far away swings it round to the nearest of four sides, picking a card brings your castle into the frame, and when battles break out it rises to look down on them at a slight tilt, then settles on the nearest side once they're over), routes, battle markers, deaths and damage numbersUnitMesh: An animated troop - KayKit character or procedural creature - walking, fighting blow by blow (see utils/battleTiming) and fallingCastle, Camp, HexTile, BoardDecorations, MovePath: The rest of the boardcards/TroopCard: A troop as a playing card, used everywherehud/: TopBar (round, castles, gold, speed and menu buttons), CardHand, SelectionCard, EventFeed, HelpPanel, TurnBannershared/: ResultsScreen, TutorialCoach, BossIntroreplay/: Recording the battle as the board showed it, and watching it again (BattleReplay, ReplayBar)effects/: Callouts, screen shake, slow motion, flying coins and confetti, and useBattleMoments, which spots the big momentsutils/UnitModelSystem: How every troop looks: character, weapons, colour palette and animations, or creature bodyutils/unitModelCache: Loads models once, repaints their colour atlas per faction and clones them per unitutils/creatures: Procedural low-poly monsters (wolves, spiders, slimes, golems, wisps, dragons...)storage/GameStorage: Save and resume the battle in progressOn the dev server (npm run dev), or any copy of the game served from localhost, a pink DEV button (bottom left of the menus) opens shortcuts: coins (+10,000, max, zero, or infinite - topped back up after every purchase), unlock or lock every campaign level, own every card, set them all to one level, reset them to the starter set, or reset all progress. Each card in the Army also gets − and + buttons to set its level for free. None of it appears on the live site (src/lib/meta/devTools.ts, src/components/shared/DevPanel.tsx).
Every card shows a picture of its troop's own 3D model - no ground, no shadow - over the faction's colour and the card frame's pattern, so the frames from the Style shop show behind the troop (src/components/game/cards/cardArt.ts). The pictures in public/cards/ are transparent WebP images rendered from the dev page /dev/card-art?type=<troop>: with the dev server running, node scripts/render-card-art.mjs [troop ...] photographs them (it needs Playwright: npm i --no-save playwright && npx playwright install chromium). Re-run it after changing a troop's model.
npm run simulate plays AI-vs-AI battles in which one side uses the deck the progression model expects at each level, and reports win rates and battle lengths. npm run simulate -- --tune 20 1 2 3 searches for the enemy strength at which that deck wins its level's target share of battles: 90% on level 1, easing to 65% from level 16 on (targetWinRate in levels.ts). The constants in src/lib/campaign/levels.ts were tuned with it.
The game can send anonymous gameplay events to PostHog - battles started, won, lost and abandoned (with level, deck and duration), cards bought and upgraded, cosmetics bought, tutorial completion and save exports - to show where players get stuck in the campaign. Nothing is sent unless NEXT_PUBLIC_POSTHOG_KEY is set at build time (and optionally NEXT_PUBLIC_POSTHOG_HOST, default https://us.i.posthog.com). Session recording and autocapture are off, Do Not Track is respected, and players can switch it off in Settings. Events are defined in src/lib/analytics.ts.
The same events, plus page views, can also go to Google Analytics 4: set NEXT_PUBLIC_GA_MEASUREMENT_ID (the G-... ID of a GA4 web stream) at build time. Google signals and ad personalisation are off for it, and the Settings switch turns it off too.
The web version can show ads through Google H5 Games Ads (AdSense's Ad Placement API), in src/lib/ads.ts:
AD_BONUS_FRACTION in src/lib/meta/economy.ts). Players who skip it progress at the normal pace.Nothing loads unless NEXT_PUBLIC_ADSENSE_CLIENT (your ca-pub-... publisher ID) is set at build time, so a build without it (such as a paid desktop version) has no ads. /ads.txt is generated from the same ID. Set NEXT_PUBLIC_ADS_TEST=1 as well to get Google's test ads while trying it out. Ads only serve once the site is approved in AdSense and enrolled in H5 Games Ads, and players in the EEA, UK and Switzerland must be shown a Google-certified consent message, which AdSense's Privacy & messaging page can set up without code changes.
public/models/kaykit/ (the castle styles are KayKit buildings too)Rooms live in a Supabase project. Its tables, access rules and functions are in supabase/migrations (applied to the project when they reach main, through Supabase's GitHub integration). Players are anonymous Supabase users, made on their device the first time they go online. The project's URL and publishable key are in src/lib/pvp/supabase.ts; set NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY to use another project.
The host's game runs the battle - the same rules engine as everywhere else, the AI's sides included - and sends every step of it, gzipped, to the others over the room's private Realtime channel (room:<code>, open only to the room's members). Everyone else plans their own turn on their copy and sends their orders to the host with a secret only the host can read, so nobody can give orders for someone else's side. A player who drops out has their turns end when the timer runs out; the host keeps the battle on their device, so reloading the page carries on. Saves can be edited, so a player's cards are only as honest as their device: fair mode makes that moot.
Saves are kept in the same Supabase project as the online rooms, in the cloud_saves table (supabase/migrations/20261010150000_cloud_saves.sql): one row per account, readable and deletable only by its owner, and written through put_cloud_save. Every copy sent gets a random revision id, and the function only replaces the revision the device last agreed with, so two devices (or tabs) can't overwrite each other's progress unasked: when both changed, the player chooses. It also clears away saves untouched for two years. An emailed sign-in link only works in the browser that asked for it (src/lib/emailLink.ts), so nobody can send a link that signs a player into another account; on any other device the player types the code from the email. The account is the anonymous one the device already uses for rooms; linking an email turns it into a permanent account that can sign in elsewhere.
Before email linking works for players, the Supabase project needs:
https://hexhordes.com/stats (and any preview domains) in the allow list, as the emailed links return to /stats?cloud=....{{ .Token }} to the Magic Link and Change Email Address templates, so players of the installed app (where links open in the browser instead) can type the code./privacy and /terms describe what the game stores and sends (saves on the device, online rooms and cloud saves in Supabase, PostHog and Google Analytics, AdSense) and the rules for playing. Players are asked to write to [email protected] (CONTACT_EMAIL in src/lib/legal.ts); update LEGAL_UPDATED in src/lib/legal.ts whenever either page changes.
npm installnpm run devThis project uses next/font to load DynaPuff for titles and buttons; and Fredoka for body text (both under the SIL Open Font License).
meta/profile.ts: The player's saved progress, the shop, battle results, stats, and save export and importgame/sides.ts: The sides of a battle: turn order, teams and allies, enemies, sides knocked out, and how the log names them (the campaign is fought between player and ai; a bigger battle has sides s1...s8, and its AI sides ai1...)pvp/arena.ts: Builds a free-for-all or team battle: the map's size, mirrored maps, weather, fair mode and the AI's kingdomspvp/room.ts, pvp/supabase.ts: Online rooms (see Online battles below)audio/: The music engine: instruments, a lookahead scheduler, the score notation and the tracks