Add some more actor inspection to debug mode
This commit is contained in:
1 parent
134270e3e3
commit
54823f62bf
4 files changed
+168
-42
No files matched your search
+86
-20
@@ -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();
|
||||
|
||||
+26
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user