TINY SHOP — cozy 3D shop-management game (Three.js vertical slice)

- Procedural 3D world: dollhouse shop, town, day/night, weather, seasons
- Customer AI with personalities (story NPCs, thieves, weekly regulars)
- Economy: suppliers, negotiation, pricing psychology, daily accounting
- Staff with traits/loyalty, 8 expansion levels, furniture & decoration
- Events with choices, quests, achievements, 4 difficulties, rival shop
- Animated daily report, analytics, save/load (3 slots + autosave)
- Procedural music & SFX (WebAudio), zero external assets
- Test harnesses: simtest (node), verify/check/e2e (headless browser)
This commit is contained in:
2026-08-23 06:58:24 +00:00
commit 0e7c07533e
40 changed files with 10130 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<title>TINY SHOP 🏪</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏪</text></svg>" />
</head>
<body>
<div id="game"></div>
<!-- soft cinematic vignette -->
<div id="vignette"></div>
<!-- ============ GAME UI ============ -->
<div id="ui" class="hidden">
<!-- top status bar -->
<div id="topbar">
<div class="tb-left panel-chip">
<span class="tb-day" id="tb-day">Day 1</span>
<span class="tb-sep">·</span>
<span id="tb-season" title="Season">🌸 Spring</span>
<span class="tb-sep">·</span>
<span id="tb-weather" title="Weather">☀️ Sunny</span>
<span class="tb-sep">·</span>
<span id="tb-clock" class="mono">8:00</span>
<span id="tb-phase" class="phase-pill closed">CLOSED</span>
</div>
<div class="tb-right">
<div class="panel-chip stat-chip" title="Gold"><span class="ic">💰</span><span id="tb-gold" class="mono">100</span><span class="unit">g</span></div>
<div class="panel-chip stat-chip" title="Reputation — grow it to attract richer customers and unlock rare goods"><span class="ic"></span><span id="tb-rep" class="mono">0</span><span id="tb-rep-tier" class="rep-tier">Unknown</span></div>
<button class="icon-btn" id="btn-help" title="Help & controls"></button>
<button class="icon-btn" id="btn-settings" title="Settings">⚙️</button>
</div>
</div>
<!-- right side time controls -->
<div id="timebar">
<button class="tbtn" id="spd-pause" title="Pause (Space)"></button>
<button class="tbtn active" id="spd-1" title="Normal speed (1)"></button>
<button class="tbtn" id="spd-2" title="Fast (2)">▶▶</button>
<button class="tbtn" id="spd-3" title="Very fast (3)">▶▶▶</button>
<button class="open-btn" id="btn-open-close">OPEN SHOP</button>
</div>
<!-- bottom navigation -->
<nav id="bottomnav">
<button class="nav-btn" data-panel="shop"><span class="ni">🏠</span><span class="nl">Shop</span></button>
<button class="nav-btn" data-panel="inventory"><span class="ni">📦</span><span class="nl">Stock</span></button>
<button class="nav-btn" data-panel="suppliers"><span class="ni">🚚</span><span class="nl">Suppliers</span></button>
<button class="nav-btn" data-panel="staff"><span class="ni">🧑‍🍳</span><span class="nl">Staff</span></button>
<button class="nav-btn" data-panel="town"><span class="ni">🏘️</span><span class="nl">Town</span></button>
<button class="nav-btn" data-panel="quests"><span class="ni">📜</span><span class="nl">Quests<span id="quest-dot" class="dot hidden"></span></span></button>
<button class="nav-btn" data-panel="analytics"><span class="ni">📈</span><span class="nl">Ledger</span></button>
<button class="nav-btn" data-panel="goals"><span class="ni">🏆</span><span class="nl">Goals</span></button>
</nav>
<!-- decorate mode toolbar -->
<div id="decorate-bar" class="hidden">
<span class="dec-title">🪄 Decorating</span>
<div id="dec-catalog"></div>
<div class="dec-hint">Left-click place · <b>R</b> rotate · Right-click / Esc cancel · Click placed item to pick up</div>
<button class="small-btn" id="btn-dec-done">✓ Done</button>
</div>
<!-- selection card (floating) -->
<div id="selcard" class="hidden"></div>
<!-- toasts -->
<div id="toasts"></div>
<!-- event banner -->
<div id="event-banner" class="hidden">
<div class="eb-emoji" id="eb-emoji"></div>
<div>
<div class="eb-title" id="eb-title">Event</div>
<div class="eb-text" id="eb-text"></div>
</div>
</div>
<!-- generic modal host -->
<div id="modal-root" class="hidden"></div>
<!-- tooltip -->
<div id="tooltip" class="hidden"></div>
</div>
<!-- ============ TITLE MENU ============ -->
<div id="menu">
<canvas id="menu-bg"></canvas>
<div class="menu-inner">
<div class="logo">
<div class="logo-shop">TINY&nbsp;SHOP</div>
<div class="logo-sub">— a very small shop with very big dreams —</div>
</div>
<div class="menu-buttons">
<button class="menu-btn primary" id="m-new">🆕 New Game</button>
<button class="menu-btn" id="m-continue">📖 Continue</button>
<button class="menu-btn" id="m-load">💾 Load Game</button>
<button class="menu-btn" id="m-achievements">🏆 Achievements</button>
<button class="menu-btn" id="m-settings">⚙️ Settings</button>
</div>
<div class="menu-foot">WASD/QE orbit camera · Scroll zoom · Click to inspect · Made with 🧡 and Three.js</div>
</div>
<div id="newgame-wizard" class="hidden"></div>
<div id="load-slots" class="hidden"></div>
</div>
<script type="module" src="/src/main.js"></script>
</body>
</html>