Add landscape layout with D-pad left panel and A/B right panel flanking the screen

This commit is contained in:
justin committed 2026-05-20 22:44:04 -07:00
1 parent 26dbe3f8a9
commit ffe6b9a522
3 files changed
+67 -13

No files matched your search

+6 -6
View File
@@ -288,8 +288,6 @@ class Game {
CONTROLLER OVERLAY — wires D-pad, A, B, SELECT, START CONTROLLER OVERLAY — wires D-pad, A, B, SELECT, START
══════════════════════════════════════════════════════════ */ ══════════════════════════════════════════════════════════ */
_bindController() { _bindController() {
const ctrl = document.getElementById('gba-controller');
const dpadMap = { 'dp-up':'up', 'dp-down':'down', 'dp-left':'left', 'dp-right':'right' }; const dpadMap = { 'dp-up':'up', 'dp-down':'down', 'dp-left':'left', 'dp-right':'right' };
Object.entries(dpadMap).forEach(([id, dir]) => { Object.entries(dpadMap).forEach(([id, dir]) => {
@@ -844,10 +842,12 @@ class Game {
} }
} }
_showController(visible) { _showController(visible) {
const ctrl = document.getElementById('gba-controller'); ['gba-left', 'gba-right'].forEach(id => {
if (!ctrl) return; const el = document.getElementById(id);
if (visible) ctrl.classList.remove('hidden'); if (!el) return;
else ctrl.classList.add('hidden'); if (visible) el.classList.remove('hidden');
else el.classList.add('hidden');
});
} }
/* ══════════════════════════════════════════════════════════ /* ══════════════════════════════════════════════════════════
+3 -7
View File
@@ -202,9 +202,7 @@
<!-- ═══ GBA CONTROLLER OVERLAY ═══════════════════════════════ <!-- ═══ GBA CONTROLLER OVERLAY ═══════════════════════════════
Shown over map + battle screens. Hidden on all others. --> Shown over map + battle screens. Hidden on all others. -->
<div id="gba-controller" class="gba-controller hidden"> <div id="gba-left" class="gba-controller hidden">
<!-- D-PAD (left) -->
<div class="dpad" id="dpad"> <div class="dpad" id="dpad">
<button class="dpad-btn dpad-up" id="dp-up" aria-label="Up">▲</button> <button class="dpad-btn dpad-up" id="dp-up" aria-label="Up">▲</button>
<button class="dpad-btn dpad-left" id="dp-left" aria-label="Left">◀</button> <button class="dpad-btn dpad-left" id="dp-left" aria-label="Left">◀</button>
@@ -212,19 +210,17 @@
<button class="dpad-btn dpad-right" id="dp-right" aria-label="Right">▶</button> <button class="dpad-btn dpad-right" id="dp-right" aria-label="Right">▶</button>
<button class="dpad-btn dpad-down" id="dp-down" aria-label="Down">▼</button> <button class="dpad-btn dpad-down" id="dp-down" aria-label="Down">▼</button>
</div> </div>
<!-- SELECT / START (center) -->
<div class="gba-mid-btns"> <div class="gba-mid-btns">
<button class="gba-mid-btn" id="btn-select">SELECT</button> <button class="gba-mid-btn" id="btn-select">SELECT</button>
<button class="gba-mid-btn" id="btn-start">START</button> <button class="gba-mid-btn" id="btn-start">START</button>
</div> </div>
</div>
<!-- A / B BUTTONS (right) --> <div id="gba-right" class="gba-controller hidden">
<div class="ab-cluster"> <div class="ab-cluster">
<button class="ab-btn ab-b" id="btn-b">B</button> <button class="ab-btn ab-b" id="btn-b">B</button>
<button class="ab-btn ab-a" id="btn-a">A</button> <button class="ab-btn ab-a" id="btn-a">A</button>
</div> </div>
</div> </div>
<div id="toast" class="toast hidden"></div> <div id="toast" class="toast hidden"></div>
+58
View File
@@ -272,6 +272,7 @@ html, body {
-webkit-tap-highlight-color: transparent; -webkit-tap-highlight-color: transparent;
transition: background .08s; transition: background .08s;
min-width: 52px; min-width: 52px;
width: 52px;
text-align: center; text-align: center;
} }
.gba-mid-btn:active { background: #3d2f99; } .gba-mid-btn:active { background: #3d2f99; }
@@ -674,3 +675,60 @@ html, body {
/* ─── TOAST ──────────────────────────────────────────────── */ /* ─── TOAST ──────────────────────────────────────────────── */
.toast { position:absolute; bottom:max(20px,var(--safe-bottom)); left:50%; transform:translateX(-50%); background:var(--dark-bg); border:3px solid var(--yellow); color:var(--yellow); font-family:var(--font); font-size:clamp(6.5px,1.8vw,8px); padding:10px 18px; z-index:950; animation:slideUp .3s ease; white-space:nowrap; max-width:90%; overflow:hidden; text-overflow:ellipsis; } .toast { position:absolute; bottom:max(20px,var(--safe-bottom)); left:50%; transform:translateX(-50%); background:var(--dark-bg); border:3px solid var(--yellow); color:var(--yellow); font-family:var(--font); font-size:clamp(6.5px,1.8vw,8px); padding:10px 18px; z-index:950; animation:slideUp .3s ease; white-space:nowrap; max-width:90%; overflow:hidden; text-overflow:ellipsis; }
.hidden { display:none !important; } .hidden { display:none !important; }
/* ─── PORTRAIT: left panel has dpad+mid, right panel has ab ─ */
@media (orientation: portrait) {
#gba-left, #gba-right {
position: fixed; bottom: 0; height: clamp(110px, 22vw, 148px);
flex-direction: row; align-items: center;
border-top: 2px solid rgba(120,80,255,.35); border-left: none; border-right: none;
background: linear-gradient(180deg, rgba(26,10,62,.82) 0%, rgba(14,6,36,.95) 100%);
backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
#gba-left { left: 0; width: 60%; justify-content: flex-start; padding: 0 8px 0 clamp(8px,3vw,20px); gap: 8px; }
#gba-right { right: 0; width: 40%; justify-content: flex-end; padding: 0 clamp(8px,3vw,20px) 0 8px; }
#gba-left .gba-mid-btns { flex-direction: row; }
}
/* ─── LANDSCAPE CONTROLLER LAYOUT ───────────────────────── */
@media (orientation: landscape) and (max-height: 500px) {
html, body { align-items: flex-start; justify-content: flex-start; }
#app {
width: 100vw; height: 100dvh;
border: none; border-radius: 0; box-shadow: none;
display: flex; flex-direction: row; align-items: stretch;
}
.screen { position: relative; flex: 1; inset: auto; height: 100dvh; overflow: hidden; min-width: 0; }
.gba-controller {
position: relative;
height: 100dvh; width: clamp(100px, 20vw, 140px);
bottom: auto; left: auto; right: auto;
flex-direction: column;
justify-content: center;
align-items: center;
border-top: none;
padding: 8px max(6px, env(safe-area-inset-left, 0px)) 8px 6px;
gap: 8px;
flex-shrink: 0;
}
.gba-controller.hidden { display: none; }
.dpad {
width: clamp(72px, 16vh, 100px);
height: clamp(72px, 16vh, 100px);
}
.ab-cluster {
width: clamp(72px, 16vh, 100px);
height: clamp(72px, 16vh, 100px);
}
.gba-mid-btns { flex-direction: column; gap: 5px; }
.gba-mid-btn { min-width: 44px; width: 44px; font-size: 5px; padding: 6px 4px; }
#gba-right { border-left: 2px solid rgba(120,80,255,.35); border-right: none; padding: 8px 6px 8px max(6px, env(safe-area-inset-right, 0px)); }
#gba-left { border-right: 2px solid rgba(120,80,255,.35); border-left: none; }
}