Vanilla JS + Canvas 2D, zero dependencies. Gameplay: campaign waves vs 12 dino species + 3 bosses, arena mode, 7 weapons, hero talents, pets, ult/bombs, card roguelite picks. World: day/night cycle, weather fronts (rain+lightning), Blood Moon weekends, 3 act biomes (jungle -> swamp -> ashlands with lava veins). Meta: gems economy, upgrade tree, quests, bestiary, achievements, shop (weapons/heroes/skins incl. premium), revive, ad-cap system, endless scaling past wave 25, live-painted shop/bestiary icons, pro main menu, auto-aim toggle (F). Headless smoke suite included.
257 lines
11 KiB
HTML
257 lines
11 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
|
<meta name="theme-color" content="#191207" />
|
|
<title>Primal Rampage — Stone Age Survival</title>
|
|
<link rel="stylesheet" href="./style.css" />
|
|
</head>
|
|
<body>
|
|
<canvas id="game"></canvas>
|
|
|
|
<!-- ===================== DOM UI ===================== -->
|
|
<div id="ui-root">
|
|
|
|
<!-- MENU -->
|
|
<section id="screen-menu" class="screen">
|
|
<div class="menu-wrap">
|
|
<div class="logo">
|
|
<h1>PRIMAL<span>RAMPAGE</span></h1>
|
|
<p data-i18n="menu.subtitle"></p>
|
|
</div>
|
|
<div id="menu-best" class="bestline"></div>
|
|
|
|
<nav class="menu-nav pro">
|
|
<button id="btn-campaign" class="btn-menu primary" data-i18n="menu.campaign"></button>
|
|
<button id="btn-arena" class="btn-menu" data-i18n="menu.arena"></button>
|
|
<div class="menu-sep"></div>
|
|
<button id="btn-upgrades" class="btn-menu">💪 <span id="lbl-upgrades"></span><span class="badge-dot hidden" id="dot-upgrades"></span><span class="chev">▸</span></button>
|
|
<button id="btn-quests" class="btn-menu">📜 <span id="lbl-quests"></span><span class="badge-dot hidden" id="dot-quests"></span><span class="chev">▸</span></button>
|
|
<button id="btn-bestiary" class="btn-menu">📖 <span id="lbl-bestiary"></span><span class="chev">▸</span></button>
|
|
<button id="btn-shop" class="btn-menu" data-i18n="menu.shop"></button>
|
|
<div class="menu-sep"></div>
|
|
<button id="btn-rank" class="btn-menu sm" data-i18n="menu.rank"></button>
|
|
<button id="btn-settings" class="btn-menu sm" data-i18n="menu.settings"></button>
|
|
<button id="btn-howto" class="btn-menu sm" data-i18n="menu.howto"></button>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="menu-bottombar">
|
|
<span class="ver">PRIMAL RAMPAGE · v0.9 · Stone Age Survival</span>
|
|
<span class="wallet">
|
|
<span id="menu-coins" class="coins"></span>
|
|
<span id="menu-gems" class="gems"></span>
|
|
</span>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SHOP -->
|
|
<section id="screen-shop" class="screen">
|
|
<h2 data-i18n="menu.shop"></h2>
|
|
<div class="screen-topline">
|
|
<span id="shop-coins" class="coins"></span>
|
|
<span id="shop-gems" class="gems"></span>
|
|
<button class="btn" data-back data-i18n="how.close"></button>
|
|
</div>
|
|
<div class="tabs">
|
|
<button id="tab-weapons" class="btn tab active" data-i18n="shop.tabWeapons"></button>
|
|
<button id="tab-heroes" class="btn tab" data-i18n="shop.tabHeroes"></button>
|
|
<button id="tab-skins" class="btn tab" data-i18n="shop.tabSkins"></button>
|
|
<button id="tab-upgrades" class="btn tab">💪 <span id="lbl-tabup"></span></button>
|
|
</div>
|
|
<div id="shop-grid" class="grid"></div>
|
|
<div id="shop-bombs" class="bomb-row"></div>
|
|
</section>
|
|
|
|
<!-- QUESTS -->
|
|
<section id="screen-quests" class="screen narrow">
|
|
<h2 id="h2-quests">📜</h2>
|
|
<div class="screen-topline">
|
|
<span id="quest-streak" class="gems"></span>
|
|
<button class="btn" data-back data-i18n="how.close"></button>
|
|
</div>
|
|
<div id="quest-list" class="col"></div>
|
|
<h3 id="h3-ach" style="margin-top:18px"></h3>
|
|
<div id="ach-list" class="col"></div>
|
|
</section>
|
|
|
|
<!-- BESTIARY -->
|
|
<section id="screen-bestiary" class="screen">
|
|
<h2 id="h2-best">📖</h2>
|
|
<div class="screen-topline">
|
|
<span id="best-progress" class="gems"></span>
|
|
<button class="btn" data-back data-i18n="how.close"></button>
|
|
</div>
|
|
<div id="bestiary-grid" class="grid"></div>
|
|
</section>
|
|
|
|
<!-- SETTINGS -->
|
|
<section id="screen-settings" class="screen narrow">
|
|
<h2 data-i18n="set.title"></h2>
|
|
<div class="form-row"><label data-i18n="set.language"></label>
|
|
<select id="set-lang">
|
|
<option value="en">English</option>
|
|
<option value="vi">Tiếng Việt</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-row"><label data-i18n="set.sfx"></label><input type="range" id="set-sfx" min="0" max="100" /></div>
|
|
<div class="form-row"><label data-i18n="set.music"></label><input type="range" id="set-music" min="0" max="100" /></div>
|
|
<div class="form-row"><label data-i18n="set.autofire"></label><input type="checkbox" id="set-autofire" /></div>
|
|
<div class="form-row"><label data-i18n="set.autoaim"></label><input type="checkbox" id="set-autoaim" /></div>
|
|
<div class="form-row"><label data-i18n="set.onehit"></label><input type="checkbox" id="set-onehit" /></div>
|
|
<div class="form-row"><label data-i18n="set.shake"></label><input type="checkbox" id="set-shake" /></div>
|
|
<div class="form-row"><label data-i18n="set.name"></label><input type="text" id="set-name" maxlength="16" /></div>
|
|
<div class="row" style="display:flex;gap:10px;align-items:center;margin-top:8px">
|
|
<label for="set-shakeamt" style="min-width:130px" id="lbl-shakeamt"></label>
|
|
<input id="set-shakeamt" type="range" min="0" max="100" value="100" />
|
|
<span id="val-shakeamt" style="width:40px"></span>
|
|
</div>
|
|
<div class="row" style="display:flex;gap:10px;align-items:center;margin-top:8px">
|
|
<label for="set-quality" style="min-width:130px" id="lbl-quality"></label>
|
|
<select id="set-quality">
|
|
<option value="high">High</option>
|
|
<option value="low">Low</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-actions">
|
|
<button id="set-reset" class="btn danger" data-i18n="set.reset"></button>
|
|
<button class="btn primary" data-back data-i18n="set.done"></button>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- LEADERBOARD -->
|
|
<section id="screen-rank" class="screen narrow">
|
|
<h2 data-i18n="rank.title"></h2>
|
|
<div class="rank-head rank-row">
|
|
<span>#</span><span data-i18n="rank.colPlayer"></span><span data-i18n="rank.colScore"></span><span data-i18n="rank.colWave"></span>
|
|
</div>
|
|
<div id="rank-body"></div>
|
|
<div class="form-actions"><button class="btn primary" data-back data-i18n="how.close"></button></div>
|
|
</section>
|
|
|
|
<!-- HOW TO PLAY -->
|
|
<section id="screen-howto" class="screen narrow">
|
|
<h2 data-i18n="how.title"></h2>
|
|
<ul class="how-list">
|
|
<li data-i18n="how.move"></li>
|
|
<li data-i18n="how.aim"></li>
|
|
<li data-i18n="how.ult"></li>
|
|
<li data-i18n="how.bomb"></li>
|
|
<li data-i18n="how.pause"></li>
|
|
<li data-i18n="how.onfire"></li>
|
|
<li data-i18n="how.cards"></li>
|
|
</ul>
|
|
<div class="form-actions"><button class="btn primary" data-back data-i18n="how.close"></button></div>
|
|
</section>
|
|
|
|
<!-- ARENA SETUP -->
|
|
<section id="screen-arena-setup" class="screen narrow">
|
|
<h2 data-i18n="arena.setup"></h2>
|
|
<div class="form-row"><label data-i18n="arena.bots"></label>
|
|
<select id="arena-bots">
|
|
<option value="1">1</option>
|
|
<option value="2" selected>2</option>
|
|
<option value="3">3</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-row"><label data-i18n="arena.target"></label>
|
|
<select id="arena-target">
|
|
<option value="5">5</option>
|
|
<option value="10" selected>10</option>
|
|
<option value="15">15</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-actions">
|
|
<button class="btn" data-back data-i18n="arena.back"></button>
|
|
<button id="arena-start" class="btn primary" data-i18n="arena.start"></button>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- IN-GAME HUD (DOM parts) -->
|
|
<div id="hud-root" class="hidden-ui">
|
|
<button id="btn-pause" class="icon-btn">⏸</button>
|
|
</div>
|
|
|
|
<!-- TOUCH CONTROLS -->
|
|
<div id="touch-ui" class="hidden">
|
|
<div id="stick-move" class="stick"><div class="stick-knob"></div></div>
|
|
<div id="stick-aim" class="stick"><div class="stick-knob"></div></div>
|
|
<div id="touch-buttons">
|
|
<button id="tc-fire" class="tc-btn">🔥</button>
|
|
<button id="tc-ult" class="tc-btn small">★</button>
|
|
<button id="tc-bomb" class="tc-btn small">💣</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- CARD PICK -->
|
|
<div id="overlay-cards" class="overlay hidden">
|
|
<h2 data-i18n="card.pickTitle"></h2>
|
|
<p id="card-hint" class="hint"></p>
|
|
<div id="card-row"></div>
|
|
</div>
|
|
|
|
<!-- PAUSE -->
|
|
<div id="overlay-pause" class="overlay hidden">
|
|
<h2 data-i18n="hud.paused"></h2>
|
|
<div class="col">
|
|
<button id="btn-resume" class="btn big primary" data-i18n="hud.resume"></button>
|
|
<button id="btn-quit" class="btn big danger" data-i18n="hud.quit"></button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- REVIVE -->
|
|
<div id="overlay-revive" class="overlay hidden">
|
|
<h2 id="revive-count">6</h2>
|
|
<div class="col">
|
|
<button id="btn-revive" class="btn big primary"><span data-i18n="over.revive"></span> <span id="revive-cost"></span></button>
|
|
<button id="btn-nodecline" class="btn big" data-i18n="over.menu"></button>
|
|
</div>
|
|
<p class="hint" data-i18n="over.reviveHint"></p>
|
|
</div>
|
|
|
|
<!-- GAME OVER -->
|
|
<div id="overlay-over" class="overlay hidden">
|
|
<span id="over-record" class="record hidden" data-i18n="over.newRecord"></span>
|
|
<h2 id="over-title"></h2>
|
|
<div class="stats-grid">
|
|
<div><label data-i18n="over.score"></label><b id="ov-score"></b></div>
|
|
<div><label data-i18n="over.wave"></label><b id="ov-wave"></b></div>
|
|
<div><label data-i18n="over.kills"></label><b id="ov-kills"></b></div>
|
|
<div><label data-i18n="over.combo"></label><b id="ov-combo"></b></div>
|
|
<div><label data-i18n="over.coinsEarned"></label><b id="ov-coins"></b></div>
|
|
</div>
|
|
<div class="col">
|
|
<button id="btn-retry" class="btn big primary" data-i18n="over.retry"></button>
|
|
<button id="btn-tomenu" class="btn big" data-i18n="over.menu"></button>
|
|
<button id="btn-adx2" class="btn big gem-btn hidden"></button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="toast" class="hidden"></div>
|
|
</div>
|
|
|
|
<div id="overlay-tutorial" class="overlay hidden">
|
|
<div class="panel" style="text-align:center;max-width:420px">
|
|
<h2 id="tut-title" style="margin-bottom:8px"></h2>
|
|
<p id="tut-step" style="font-size:16px;line-height:1.5;margin-bottom:16px"></p>
|
|
<div style="display:flex;gap:10px;justify-content:center">
|
|
<button id="btn-tut-next" class="btn primary"></button>
|
|
<button id="btn-tut-skip" class="btn"></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script src="./js/i18n.js"></script>
|
|
<script src="./js/save.js?v=13"></script>
|
|
<script src="./js/util.js?v=13"></script>
|
|
<script src="./js/audio.js?v=13"></script>
|
|
<script src="./js/art.js?v=13"></script>
|
|
<script src="./js/data.js?v=13"></script>
|
|
<script src="./js/entities.js?v=13"></script>
|
|
<script src="./js/game.js?v=13"></script>
|
|
<script src="./js/ui.js?v=13"></script>
|
|
<script src="./js/main.js?v=13"></script>
|
|
</body>
|
|
</html>
|