muse-engine-29 / engine /ui /start-screen.js
axonis22's picture
Muse Engine 29 - Look Picker (Phase 29 engine, Look A + Look B by Muse Glimmer, lamp fix)
8fb1496 verified
Raw History Blame Contribute Delete
3.79 kB
// [e29 coach] Start screen: choose Look A / Look B before playing. Remembers the choice (via MuseLooks,
// localStorage 'muse-engine-29.look'). Skip with ?start=0 (used by tests).
(function () {
var E = window.MuseEngine29, M = window.MuseLooks;
var stage = document.getElementById('stage') || document.body;
if (!E || !M) return;
if (/[?&](start=0|skipstart=1)/.test(location.search)) return;
function rgb(c) { return c ? 'rgb(' + c.map(function (v) { return Math.round(Math.max(0, Math.min(1, v)) * 255); }).join(',') + ')' : 'transparent'; }
function swatches(p) {
var env = p.env || {}, n = p.nodes || {}, ch = p.characters || {};
function partCol(c) { return c && c.parts && c.parts[0] ? c.parts[0].color : (c && c.color); }
return [env.dayClear, n.ground && n.ground.color, n.crate0 && n.crate0.color, n.pier && n.pier.color,
partCol(ch.hostile) || [0.9, 0.2, 0.2], partCol(ch.patrol) || [0.95, 0.65, 0.15]]
.map(function (c) { return '<span style="background:' + rgb(c) + '"></span>'; }).join('');
}
var ov = document.createElement('div');
ov.className = 'e29-overlay show'; ov.id = 'e29-start';
function esc(t) { return String(t == null ? '' : t).replace(/[&<>"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); }
function render() {
var act = M.active();
var cards = M.list().map(function (l) {
var p = M.get(l.id) || {};
return '<div class="e29-look' + (l.id === act ? ' sel' : '') + '" data-id="' + esc(l.id) + '"><div class="t">Look ' + esc(l.id) + ' · ' + esc(l.name) +
'</div><div class="b">' + esc(l.blurb || '') + '</div><div class="e29-sw">' + swatches(p) + '</div></div>';
}).join('');
ov.innerHTML = '<div class="e29-card"><h1>Muse Engine 29 · Look Picker</h1>' +
'<div class="e29-sub">Phase 29 engine (combat feel + Phase 28 movement). Pick a look — gameplay, colliders and hitboxes are identical in both. ' +
'Change it any time with <b>L</b> or in the config panel (<b>Tab</b>).</div>' +
'<h2>Choose a look</h2><div class="e29-looks">' + cards + '</div>' +
'<div class="e29-foot"><span class="e29-sub">1 / 2 or ← → to choose · Enter to play · your choice is remembered</span>' +
'<button class="e29-btn ok" id="e29-play">Play</button></div></div>';
ov.querySelectorAll('.e29-look').forEach(function (el) {
el.onclick = function () { M.setActive(el.getAttribute('data-id')); render(); };
});
ov.querySelector('#e29-play').onclick = play;
}
function play() {
ov.classList.remove('show');
window.removeEventListener('keydown', onKey, true);
E.setBlocked(false);
E.flashHint('LOOK ' + M.active() + ' · click to aim · Tab = config · L = look');
var c = document.getElementById('muse-canvas'); if (c) c.focus();
}
function onKey(e) {
if (!ov.classList.contains('show')) return;
var ids = M.list().map(function (l) { return l.id; });
var i = ids.indexOf(M.active());
if (e.code === 'Enter' || e.code === 'NumpadEnter') { e.preventDefault(); play(); }
else if (e.code === 'ArrowRight' || e.code === 'ArrowLeft') { e.preventDefault(); M.setActive(ids[(i + (e.code === 'ArrowRight' ? 1 : ids.length - 1)) % ids.length]); render(); }
else if (/^Digit[1-9]$/.test(e.code) && ids[+e.code.slice(5) - 1]) { M.setActive(ids[+e.code.slice(5) - 1]); render(); }
else if (e.code === 'KeyL') { e.preventDefault(); M.next(); render(); }
e.stopPropagation();
}
window.addEventListener('keydown', onKey, true);
stage.appendChild(ov);
render();
E.setBlocked(true);
window.E29Start = { show: function () { ov.classList.add('show'); window.addEventListener('keydown', onKey, true); render(); E.setBlocked(true); }, play: play };
})();