192 lines
8.2 KiB
HTML
192 lines
8.2 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, maximum-scale=1" />
|
|
<title>Newbury Nights — AR Ghost Hunt</title>
|
|
<link rel="stylesheet" href="/css/app.css" />
|
|
<link rel="stylesheet" href="/css/game.css" />
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"three": "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js"
|
|
}
|
|
}
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<!-- ============ TITLE SCREEN ============ -->
|
|
<section id="screen-title" class="screen">
|
|
<div class="title-wrap">
|
|
<div class="eyebrow">Newbury · After Dark</div>
|
|
<h1 class="game-title">Newbury<span>Nights</span></h1>
|
|
<p class="tagline">The town is glooming over. Raise your detector, find the cold spots, and clear them before your battery dies.</p>
|
|
|
|
<div class="title-actions">
|
|
<button class="primary" id="btn-scan-set">Scan a Set</button>
|
|
<button id="btn-freehunt">Free Hunt</button>
|
|
<button id="btn-roster">Ghost Index</button>
|
|
<button id="btn-about">About This Tribute</button>
|
|
</div>
|
|
|
|
<div class="battery-hint mono">DETECTOR ONLINE · v0.1</div>
|
|
</div>
|
|
<div class="disclaimer">
|
|
Fan-made tribute. Not affiliated with, sponsored by, or endorsed by the LEGO Group.
|
|
LEGO® and Hidden Side™ are trademarks of the LEGO Group.
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ============ SCAN SCREEN ============ -->
|
|
<section id="screen-scan" class="screen hidden">
|
|
<button class="back" data-back>← Back</button>
|
|
<div class="scan-wrap">
|
|
<h2>Scan a Set</h2>
|
|
<p class="muted">Point your camera at the set's code, or type it in.</p>
|
|
<div id="scan-video-wrap" class="scan-video">
|
|
<video id="scan-video" playsinline muted></video>
|
|
<div class="scan-reticle"></div>
|
|
<div id="scan-status" class="scan-status mono">Starting camera…</div>
|
|
</div>
|
|
<div class="manual-entry">
|
|
<label for="manual-code">Set code</label>
|
|
<div class="row">
|
|
<input id="manual-code" placeholder="e.g. NN-70419" autocomplete="off" />
|
|
<button class="primary" id="btn-manual-go">Go</button>
|
|
</div>
|
|
<div id="scan-error" class="scan-error hidden"></div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ============ HUNT (AR) SCREEN ============ -->
|
|
<section id="screen-hunt" class="screen hidden">
|
|
<video id="ar-video" playsinline muted></video>
|
|
<canvas id="ar-canvas"></canvas>
|
|
|
|
<!-- HUD overlay -->
|
|
<div class="hud">
|
|
<div class="hud-top">
|
|
<button class="back small" data-back>✕</button>
|
|
<div class="battery">
|
|
<div class="battery-label mono">BATTERY</div>
|
|
<div class="battery-bar"><div id="battery-fill" class="battery-fill"></div></div>
|
|
<div id="battery-pct" class="mono">100%</div>
|
|
</div>
|
|
<div class="gloom-count mono"><span class="dot" style="background:var(--gloom);box-shadow:0 0 8px var(--gloom)"></span> <span id="gloom-count">0</span></div>
|
|
</div>
|
|
|
|
<!-- color wheel scanner -->
|
|
<div class="wheel" id="color-wheel" aria-label="Gloom detector color wheel">
|
|
<button class="wheel-seg seg-red" data-type="red" aria-label="Scan red gloom"></button>
|
|
<button class="wheel-seg seg-yellow" data-type="yellow" aria-label="Scan yellow gloom"></button>
|
|
<button class="wheel-seg seg-blue" data-type="blue" aria-label="Scan blue gloom"></button>
|
|
<div class="wheel-core mono" id="wheel-core">SCAN</div>
|
|
</div>
|
|
|
|
<!-- lock-on label -->
|
|
<div id="lockon" class="lockon hidden">
|
|
<div class="lockon-name display" id="lockon-name">—</div>
|
|
<div class="lockon-sub mono"><span id="lockon-type">—</span> · <span id="lockon-rarity">—</span> · <span id="lockon-ability">—</span></div>
|
|
<div class="ghost-hp"><div id="ghost-hp-fill" class="ghost-hp-fill"></div></div>
|
|
</div>
|
|
|
|
<!-- blaster -->
|
|
<div class="hud-bottom">
|
|
<div class="overheat" id="overheat-wrap"><div id="overheat-fill" class="overheat-fill"></div></div>
|
|
<button id="btn-blast" class="blaster">HOLD TO BLAST</button>
|
|
</div>
|
|
|
|
<!-- jumpscare / toast -->
|
|
<div id="toast" class="toast hidden"></div>
|
|
|
|
<!-- iOS motion permission gate -->
|
|
<div id="motion-gate" class="motion-gate hidden">
|
|
<div class="motion-card">
|
|
<div class="motion-title display">Enable Motion</div>
|
|
<p class="motion-body">Newbury Nights uses your phone's motion sensor to look around. Tap below and allow access when prompted.</p>
|
|
<button class="primary" id="motion-enable">Enable Motion</button>
|
|
</div>
|
|
</div>
|
|
<div id="result" class="result hidden">
|
|
<div class="result-card">
|
|
<div id="result-title" class="display">Set Cleared</div>
|
|
<div id="result-body" class="muted"></div>
|
|
<button class="primary" data-back>Return to Newbury</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ============ ABOUT / TRIBUTE ============ -->
|
|
<section id="screen-about" class="screen hidden">
|
|
<button class="back" data-back>← Back</button>
|
|
<div class="about-wrap">
|
|
<h2>About This Tribute</h2>
|
|
|
|
<p class="about-lead">Newbury Nights is a fan-made, non-commercial homage to the
|
|
augmented-reality ghost-hunting mechanics of the LEGO® Hidden Side™ app, which the
|
|
LEGO Group discontinued. It exists because some of us loved how that game worked and
|
|
didn't want the idea to disappear.</p>
|
|
|
|
<h3>What this is</h3>
|
|
<p>An independent reimplementation of the <em>way the game played</em> — raising your
|
|
phone as a detector, uncovering coloured gloom, locking on, and clearing ghosts. The
|
|
ghost names, types, and stats are referenced from community documentation of the
|
|
original so the tribute feels true to what fans remember.</p>
|
|
|
|
<h3>What this is not</h3>
|
|
<p>This project is not made by, affiliated with, sponsored by, or endorsed by the
|
|
LEGO Group. It uses none of the LEGO Group's logos, brand artwork, minifigure designs,
|
|
or other protected imagery. Where the original game's name appears, it is only to
|
|
describe what this project pays tribute to.</p>
|
|
|
|
<h3>Names & trademarks</h3>
|
|
<p>"LEGO" and "Hidden Side" are trademarks of the LEGO Group. They are referenced here
|
|
solely to identify the original work being honoured. If you're looking for the official
|
|
product, visit the LEGO Group's own website rather than this fan project.</p>
|
|
|
|
<h3>Credit & takedown</h3>
|
|
<p>All credit for the original concept belongs to the LEGO Group and the team behind
|
|
Hidden Side. This is a labour of love, offered freely. If a rights holder would prefer
|
|
any element changed or removed, that request will be respected.</p>
|
|
</div>
|
|
<div class="disclaimer">
|
|
Fan-made tribute. Not affiliated with, sponsored by, or endorsed by the LEGO Group.
|
|
LEGO® and Hidden Side™ are trademarks of the LEGO Group.
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ============ ROSTER / INDEX ============ -->
|
|
<section id="screen-roster" class="screen hidden">
|
|
<button class="back" data-back>← Back</button>
|
|
<div class="roster-wrap">
|
|
<h2>Ghost Index</h2>
|
|
<div class="roster-filters">
|
|
<select id="filter-type">
|
|
<option value="">All types</option>
|
|
<option value="red">Red</option>
|
|
<option value="yellow">Yellow</option>
|
|
<option value="blue">Blue</option>
|
|
</select>
|
|
<select id="filter-rarity">
|
|
<option value="">All rarities</option>
|
|
<option value="1">★</option>
|
|
<option value="2">★★</option>
|
|
<option value="3">★★★</option>
|
|
<option value="4">★★★★</option>
|
|
</select>
|
|
<label class="boss-toggle"><input type="checkbox" id="filter-boss" /> Bosses only</label>
|
|
</div>
|
|
<div id="roster-grid" class="roster-grid"></div>
|
|
</div>
|
|
<div class="disclaimer">
|
|
Fan-made tribute. Not affiliated with, sponsored by, or endorsed by the LEGO Group.
|
|
LEGO® and Hidden Side™ are trademarks of the LEGO Group.
|
|
</div>
|
|
</section>
|
|
|
|
<script type="module" src="/js/game.js"></script>
|
|
</body>
|
|
</html>
|