Add some more actor inspection to debug mode
This commit is contained in:
parent
134270e3e3
commit
54823f62bf
33
index.html
33
index.html
@ -221,22 +221,18 @@
|
||||
<div class="-buttons" id="player-debug-time-buttons">
|
||||
<!-- populated in js -->
|
||||
</div>
|
||||
<p>Game speed:
|
||||
<select name="speed">
|
||||
<option value="100">100× faster</option>
|
||||
<option value="50">50× faster</option>
|
||||
<option value="20">20× faster</option>
|
||||
<option value="10">10× faster</option>
|
||||
<option value="5">5× faster</option>
|
||||
<option value="3">3× faster</option>
|
||||
<option value="2">2× faster</option>
|
||||
<option value="3/2">1½× faster</option>
|
||||
<option value="1" selected>Normal speed</option>
|
||||
<option value="1/2">2× slower</option>
|
||||
<option value="1/3">3× slower</option>
|
||||
<option value="1/4">4× slower</option>
|
||||
</select>
|
||||
</p>
|
||||
<div id="player-debug-speed" class="radio-faux-button-set">
|
||||
<label><input type="radio" name="speed" value="100"><span class="-button">100</span></label>
|
||||
<label><input type="radio" name="speed" value="25"><span class="-button">25</span></label>
|
||||
<label><input type="radio" name="speed" value="10"><span class="-button">10</span></label>
|
||||
<label><input type="radio" name="speed" value="5"><span class="-button">5</span></label>
|
||||
<label><input type="radio" name="speed" value="3"><span class="-button">3</span></label>
|
||||
<label><input type="radio" name="speed" value="2"><span class="-button">2</span></label>
|
||||
<label><input type="radio" name="speed" value="1"><span class="-button"><strong>1×</strong></span></label>
|
||||
<label><input type="radio" name="speed" value="1/2"><span class="-button">½</span></label>
|
||||
<label><input type="radio" name="speed" value="1/3"><span class="-button">⅓</span></label>
|
||||
<label><input type="radio" name="speed" value="1/4"><span class="-button">¼</span></label>
|
||||
</div>
|
||||
|
||||
<h3>Inventory</h3>
|
||||
<div class="-inventory">
|
||||
@ -280,10 +276,11 @@
|
||||
</select>
|
||||
</p>
|
||||
<ul>
|
||||
<li><label><input type="checkbox" name="show_actor_bboxes"> Show actor bounding boxes</label></li>
|
||||
<li><label><input type="checkbox" name="disable_interpolation"> Disable interpolation</label></li>
|
||||
<li><label><input type="checkbox" name="show_actor_bboxes"> Show actor bounding boxes</label></li>
|
||||
<li><label><input type="checkbox" name="show_actor_order"> Show actor order</label></li>
|
||||
<li><label><input type="checkbox" name="show_actor_tooltips"> Show actor tooltips</label></li>
|
||||
<!--
|
||||
<li><label><input type="checkbox" disabled> Show actor info</label></li>
|
||||
<li><label><input type="checkbox" disabled> Freeze time for everything else</label></li>
|
||||
<li><label><input type="checkbox" disabled> Player is immortal</label></li>
|
||||
<li><label><input type="checkbox" disabled> Player ignores collision</label></li>
|
||||
|
||||
106
js/main.js
106
js/main.js
@ -515,18 +515,6 @@ class Player extends PrimaryView {
|
||||
this.renderer = new CanvasRenderer(this.conductor.tilesets['ll']);
|
||||
this._loaded_tileset = false;
|
||||
this.level_el.append(this.renderer.canvas);
|
||||
this.renderer.canvas.addEventListener('auxclick', ev => {
|
||||
if (ev.button !== 1)
|
||||
return;
|
||||
if (! this.debug.enabled)
|
||||
return;
|
||||
|
||||
let [x, y] = this.renderer.cell_coords_from_event(ev);
|
||||
this.level.move_to(this.level.player, this.level.cell(x, y), 1);
|
||||
// TODO this behaves a bit weirdly when paused (doesn't redraw even with a force), i
|
||||
// think because we're still claiming a speed of 1 so time has to pass before the move
|
||||
// actually "happens"
|
||||
});
|
||||
|
||||
// Populate a skeleton inventory
|
||||
this.inventory_key_nodes = {};
|
||||
@ -864,10 +852,9 @@ class Player extends PrimaryView {
|
||||
}),
|
||||
);
|
||||
// Hook up play speed
|
||||
let speed_el = debug_el.elements.speed;
|
||||
speed_el.value = "1";
|
||||
speed_el.addEventListener('change', ev => {
|
||||
let speed = ev.target.value;
|
||||
debug_el.elements.speed.value = "1";
|
||||
debug_el.querySelector('#player-debug-speed').addEventListener('change', ev => {
|
||||
let speed = debug_el.elements.speed.value;
|
||||
let [numer, denom] = speed.split('/');
|
||||
this.play_speed = parseInt(numer, 10) / parseInt(denom ?? '1', 10);
|
||||
});
|
||||
@ -877,9 +864,10 @@ class Player extends PrimaryView {
|
||||
let inventory_el = debug_el.querySelector('.-inventory');
|
||||
for (let name of [
|
||||
'key_blue', 'key_red', 'key_yellow', 'key_green',
|
||||
'xray_eye', 'foil', 'lightning_bolt', 'hook',
|
||||
'flippers', 'fire_boots', 'cleats', 'suction_boots',
|
||||
'bribe', 'railroad_sign', 'hiking_boots', 'speed_boots',
|
||||
'xray_eye', 'helmet', 'foil', 'lightning_bolt',
|
||||
'hiking_boots', 'speed_boots', 'railroad_sign', 'helmet',
|
||||
'bribe', 'bowling_ball', 'dynamite',
|
||||
]) {
|
||||
inventory_el.append(make_button(
|
||||
mk('img', {src: this.render_inventory_tile(name)}),
|
||||
@ -1067,6 +1055,31 @@ class Player extends PrimaryView {
|
||||
this.renderer.show_actor_bboxes = ev.target.checked;
|
||||
this._redraw();
|
||||
});
|
||||
wire_checkbox('show_actor_order', ev => {
|
||||
this.renderer.show_actor_order = ev.target.checked;
|
||||
this._redraw();
|
||||
});
|
||||
wire_checkbox('show_actor_tooltips', ev => {
|
||||
if (ev.target.checked) {
|
||||
let element = mk('div.player-debug-actor-tooltip');
|
||||
let header = mk('h3');
|
||||
let dl = mk('dl');
|
||||
let props = {};
|
||||
for (let key of ['direction', 'movement_speed', 'movement_cooldown']) {
|
||||
let dd = mk('dd');
|
||||
props[key] = dd;
|
||||
dl.append(mk('dt', key), dd);
|
||||
}
|
||||
let inventory = mk('p');
|
||||
element.append(header, dl, inventory);
|
||||
this.debug.actor_tooltip = {element, header, props, inventory};
|
||||
document.body.append(element);
|
||||
}
|
||||
else if (this.debug.actor_tooltip) {
|
||||
this.debug.actor_tooltip.element.remove();
|
||||
this.debug.actor_tooltip = null;
|
||||
}
|
||||
});
|
||||
wire_checkbox('disable_interpolation', ev => {
|
||||
this.use_interpolation = ! ev.target.checked;
|
||||
this._redraw();
|
||||
@ -1082,6 +1095,60 @@ class Player extends PrimaryView {
|
||||
}),
|
||||
);
|
||||
|
||||
// Bind some debug events on the canvas
|
||||
this.renderer.canvas.addEventListener('auxclick', ev => {
|
||||
if (ev.button !== 1)
|
||||
return;
|
||||
|
||||
let [x, y] = this.renderer.cell_coords_from_event(ev);
|
||||
this.level.move_to(this.level.player, this.level.cell(x, y), 1);
|
||||
// TODO this behaves a bit weirdly when paused (doesn't redraw even with a force), i
|
||||
// think because we're still claiming a speed of 1 so time has to pass before the move
|
||||
// actually "happens"
|
||||
});
|
||||
this.renderer.canvas.addEventListener('mousemove', ev => {
|
||||
let tooltip = this.debug.actor_tooltip;
|
||||
if (! tooltip)
|
||||
return;
|
||||
|
||||
// FIXME this doesn't work so well for actors in motion :S
|
||||
// TODO show bounding box for hovered actor?
|
||||
let [x, y] = this.renderer.cell_coords_from_event(ev);
|
||||
// TODO should update the tooltip if the game advances but the mouse doesn't move
|
||||
let cell = this.level.cell(x, y);
|
||||
let actor = cell.get_actor();
|
||||
tooltip.element.classList.toggle('--visible', actor);
|
||||
if (! actor)
|
||||
return;
|
||||
|
||||
tooltip.element.style.left = `${ev.clientX}px`;
|
||||
tooltip.element.style.top = `${ev.clientY}px`;
|
||||
tooltip.header.textContent = actor.type.name;
|
||||
for (let [key, element] of Object.entries(tooltip.props)) {
|
||||
element.textContent = String(actor[key] ?? "—");
|
||||
}
|
||||
|
||||
// TODO it would be cool to use icons and whatever for this, but that would be tricky to
|
||||
// do without serious canvas churn
|
||||
let inv = [];
|
||||
if (actor.keyring) {
|
||||
for (let [key, count] of Object.entries(actor.keyring)) {
|
||||
inv.push(`${key} ×${count}`);
|
||||
}
|
||||
}
|
||||
if (actor.toolbelt) {
|
||||
for (let tool of actor.toolbelt) {
|
||||
inv.push(tool);
|
||||
}
|
||||
}
|
||||
tooltip.inventory.textContent = inv.join(', ');
|
||||
});
|
||||
this.renderer.canvas.addEventListener('mouseout', ev => {
|
||||
if (this.debug.actor_tooltip) {
|
||||
this.debug.actor_tooltip.element.classList.remove('--visible');
|
||||
}
|
||||
});
|
||||
|
||||
this.adjust_scale();
|
||||
if (this.level) {
|
||||
this.update_ui();
|
||||
@ -1869,8 +1936,7 @@ class Player extends PrimaryView {
|
||||
|
||||
confirm_game_interruption(question, action) {
|
||||
if (this.state === 'playing' || this.state === 'paused' || this.state === 'rewinding') {
|
||||
new ConfirmOverlay(this.conductor, "Restart this level and watch the replay?", action)
|
||||
.open();
|
||||
new ConfirmOverlay(this.conductor, question, action).open();
|
||||
}
|
||||
else {
|
||||
action();
|
||||
|
||||
@ -57,6 +57,7 @@ export class CanvasRenderer {
|
||||
this.viewport_y = 0;
|
||||
this.viewport_dirty = false;
|
||||
this.show_actor_bboxes = false;
|
||||
this.show_actor_order = false;
|
||||
this.use_rewind_effect = false;
|
||||
this.perception = 'normal'; // normal, xray, editor, palette
|
||||
this.active_player = null;
|
||||
@ -264,6 +265,11 @@ export class CanvasRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.use_rewind_effect) {
|
||||
this.draw_rewind_effect(tic);
|
||||
}
|
||||
|
||||
// Debug overlays
|
||||
if (this.show_actor_bboxes) {
|
||||
this.ctx.fillStyle = '#f004';
|
||||
for (let x = xf0; x <= x1; x++) {
|
||||
@ -277,9 +283,27 @@ export class CanvasRenderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.show_actor_order) {
|
||||
this.ctx.fillStyle = '#fff';
|
||||
this.ctx.strokeStyle = '#000';
|
||||
this.ctx.lineWidth = 3;
|
||||
this.ctx.font = '16px monospace';
|
||||
this.ctx.textAlign = 'center';
|
||||
this.ctx.textBaseline = 'middle';
|
||||
for (let [n, actor] of this.level.actors.entries()) {
|
||||
let cell = actor.cell;
|
||||
if (! cell)
|
||||
continue;
|
||||
if (cell.x < xf0 || cell.x > x1 || cell.y < yf0 || cell.y > y1)
|
||||
continue;
|
||||
|
||||
if (this.use_rewind_effect) {
|
||||
this.draw_rewind_effect(tic);
|
||||
let [vx, vy] = actor.visual_position(tic_offset, packet.update_rate);
|
||||
let x = (vx + 0.5 - x0) * tw;
|
||||
let y = (vy + 0.5 - y0) * th;
|
||||
let label = String(this.level.actors.length - 1 - n);
|
||||
this.ctx.strokeText(label, x, y);
|
||||
this.ctx.fillText(label, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
43
style.css
43
style.css
@ -1490,7 +1490,7 @@ body.--debug #player-debug {
|
||||
#player-debug .-inventory {
|
||||
display: grid;
|
||||
margin: 0 auto;
|
||||
grid: auto-fill var(--tile-height) / repeat(8, var(--tile-width));
|
||||
grid: auto-flow min-content / repeat(8, min-content);
|
||||
gap: 2px;
|
||||
}
|
||||
#player-debug > .-inventory > button {
|
||||
@ -1500,7 +1500,7 @@ body.--debug #player-debug {
|
||||
display: block;
|
||||
}
|
||||
#player-debug > .-inventory > button.-wide {
|
||||
grid-column: span 8;
|
||||
grid-column: span 5;
|
||||
padding: 0.25em;
|
||||
}
|
||||
#player-debug .-buttons {
|
||||
@ -1604,6 +1604,45 @@ body.--debug #player-debug {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.player-debug-actor-tooltip {
|
||||
position: absolute;
|
||||
display: none;
|
||||
|
||||
/* similar to editor tooltip */
|
||||
padding: 0.33em 0.75em;
|
||||
border: 1px solid black;
|
||||
color: #d8d8d8;
|
||||
background: hsl(225, 10%, 20%);
|
||||
box-shadow: 0 1px 2px 1px #0004;
|
||||
|
||||
opacity: 0.9;
|
||||
font-family: monospace;
|
||||
pointer-events: none;
|
||||
}
|
||||
.player-debug-actor-tooltip.--visible {
|
||||
display: block;
|
||||
}
|
||||
.player-debug-actor-tooltip h3 {
|
||||
font-size: 1.25em;
|
||||
margin-bottom: 0.25rem;
|
||||
border-bottom: 1px solid currentColor;
|
||||
color: white;
|
||||
}
|
||||
.player-debug-actor-tooltip dl {
|
||||
display: grid;
|
||||
grid: auto-flow min-content / auto auto;
|
||||
align-items: baseline;
|
||||
gap: 0.25em 1em;
|
||||
margin: 0;
|
||||
}
|
||||
.player-debug-actor-tooltip dl > dt {
|
||||
grid-column: 1;
|
||||
}
|
||||
.player-debug-actor-tooltip dl > dd {
|
||||
grid-column: 2;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************************************/
|
||||
/* Editor */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user