From aeac5c285bf46652265e6f8486c9aee128f48e60 Mon Sep 17 00:00:00 2001 From: "Eevee (Evelyn Woods)" Date: Sun, 6 Dec 2020 18:51:12 -0700 Subject: [PATCH] Finally add and wire up most of the debug panel --- index.html | 118 ++++++++++++++++++++++++------------ js/main.js | 156 ++++++++++++++++++++++++++++++++++++++++++------ js/tiletypes.js | 16 +++-- style.css | 82 +++++++++++++++++++++++-- 4 files changed, 303 insertions(+), 69 deletions(-) diff --git a/index.html b/index.html index 6029ebe..a20f8c6 100644 --- a/index.html +++ b/index.html @@ -109,6 +109,85 @@
+
+
+ + + + + + + + + + + + + + + + + + + +
0tics
0moves
0seconds
+

Game speed: + +

+
+
+
+

Viewport size: + +

+
    +
  • Show actor info
  • +
  • Show actor bounding boxes
  • +
  • Freeze time for everything else
  • +
  • Player is immortal
  • +
  • Player ignores collision
  • +
  • Player levitates
  • +
+

(Middle-click to teleport.)

+
+
+ +
+
+ +
+ + +
🎵 title by author @@ -157,45 +236,6 @@
-
-

Play time: A tics, B moves, C seconds

-

- - - - - - -

-

Speed: 6× (0.5 frame), 3× (1 frame), 2× (???), 1.5× (2 frames), 1× (3 frames), ½× (6 frames), ⅓× (9 frames), ¼× (12 frames)

-

Viewport: 9/10, 12, 16, 24, 32, map size

-
- -

Show actor info

-

Show actor bounding boxes

- -

Freeze time for everything else

-

Immortal / intangible?

-

Ignore collisions

-

Levitate

-

Stop clock

-

Give item: (Click inventory to destroy items)

- -

- - -

- - -
diff --git a/js/main.js b/js/main.js index d62a6bc..aa25b05 100644 --- a/js/main.js +++ b/js/main.js @@ -256,6 +256,7 @@ class Player extends PrimaryView { this.scale = 1; + this.play_speed = 1; this.compat = { popwalls_react_on_arrive: false, auto_convert_ccl_popwalls: true, @@ -417,12 +418,14 @@ class Player extends PrimaryView { this.renderer.canvas.addEventListener('auxclick', ev => { if (ev.button !== 1) return; - // TODO make a real debug flag? allow enabling this but consider it aid level 3? - if (! location.host.match(/localhost/)) + if (! this.debug.enabled) return; let [x, y] = this.renderer.cell_coords_from_event(ev); this.level.move_to(this.level.player, this.level.cells[y][x], 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 inventory @@ -459,11 +462,20 @@ class Player extends PrimaryView { if (! this.active) return; - if (ev.key === 'p' || ev.key === 'Pause') { + if (ev.key === 'p') { this.toggle_pause(); return; } + if (ev.key === 'Pause' && ! this.debug.enabled) { + new ConfirmOverlay(this.conductor, + "Enable debug mode? This will disable all saving of scores until you reload!", + () => { + this.setup_debug(); + }, + ).open(); + } + if (ev.key === ' ') { if (this.state === 'waiting') { // Start without moving @@ -618,6 +630,7 @@ class Player extends PrimaryView { }); // Populate input debugger + this.debug = { enabled: false }; this.input_el = this.root.querySelector('.input'); this.input_action_elements = {}; for (let [action, label] of Object.entries(ACTION_LABELS)) { @@ -645,6 +658,102 @@ class Player extends PrimaryView { setup() { } + // Link up the debug panel and enable debug features + setup_debug() { + this.root.classList.add('--debug'); + let debug_el = this.root.querySelector('#player-debug'); + this.debug = { + enabled: true, + time_tics_el: this.root.querySelector('#player-debug-time-tics'), + time_moves_el: this.root.querySelector('#player-debug-time-moves'), + time_secs_el: this.root.querySelector('#player-debug-time-secs'), + }; + // Add a button for every kind of inventory item + let inventory_el = debug_el.querySelector('.-inventory'); + let make_button = (label, onclick) => { + let button = mk('button', {type: 'button'}, label); + button.addEventListener('click', onclick); + return button; + }; + for (let name of [ + 'key_blue', 'key_red', 'key_yellow', 'key_green', + 'flippers', 'fire_boots', 'cleats', 'suction_boots', + 'bribe', 'railroad_sign', 'hiking_boots', 'speed_boots', + 'xray_eye', 'helmet', 'foil', 'lightning_bolt', + ]) { + inventory_el.append(make_button( + mk('img', {src: this.render_inventory_tile(name)}), + () => { + this.level.give_actor(this.level.player, name); + this.update_ui(); + })); + } + let clear_button = mk('button.-wide', {type: 'button'}, "clear inventory"); + clear_button.addEventListener('click', ev => { + this.level.take_all_keys_from_actor(this.level.player); + this.level.take_all_tools_from_actor(this.level.player); + this.update_ui(); + }); + inventory_el.append(clear_button); + + debug_el.querySelector('.-time-controls').addEventListener('click', ev => { + let button = ev.target.closest('button.-time-button'); + if (! button) + return; + + let dt = parseInt(button.getAttribute('data-dt')); + if (dt > 0) { + this.advance_by(dt); + } + else if (dt < 0) { + for (let i = 0; i < -dt; i++) { + if (! this.level.has_undo()) + break; + this.undo(); + } + } + this._redraw(); + this.update_ui(); + }); + + let speed_el = debug_el.elements.speed; + speed_el.value = "1"; + speed_el.addEventListener('change', ev => { + let speed = ev.target.value; + let [numer, denom] = speed.split('/'); + this.play_speed = parseInt(numer, 10) / parseInt(denom ?? '1', 10); + }); + + debug_el.querySelector('.-buttons').append( + make_button("green button", () => { + TILE_TYPES['button_green'].do_button(this.level); + this._redraw(); + }), + make_button("blue button", () => { + TILE_TYPES['button_blue'].do_button(this.level); + this._redraw(); + }), + make_button("toggle clock", () => { + this.level.pause_timer(); + this.update_ui(); + }), + make_button("+10s", () => { + this.level.adjust_timer(+10); + this.update_ui(); + }), + make_button("−10s", () => { + this.level.adjust_timer(-10); + this.update_ui(); + }), + make_button("stop clock", () => { + this.level.time_remaining = null; + this.update_ui(); + }), + ); + + this.update_ui(); + } + activate() { // We can't resize when we're not visible, so do it now super.activate(); @@ -907,7 +1016,7 @@ class Player extends PrimaryView { // buffer dry) and change to 'waiting' instead? } - let dt = 1000 / TICS_PER_SECOND; + let dt = 1000 / (TICS_PER_SECOND * this.play_speed); if (this.state === 'rewinding') { // Rewind faster than normal time dt *= 0.5; @@ -936,7 +1045,7 @@ class Player extends PrimaryView { this.tic_offset = 1; } else { - this.tic_offset = Math.min(0.9999, (performance.now() - this.last_advance) / 1000 / (1 / TICS_PER_SECOND)); + this.tic_offset = Math.min(0.9999, (performance.now() - this.last_advance) / 1000 * TICS_PER_SECOND * this.play_speed); if (this.state === 'rewinding') { this.tic_offset = 1 - this.tic_offset; } @@ -1034,6 +1143,13 @@ class Player extends PrimaryView { for (let action of Object.keys(ACTION_LABELS)) { this.input_action_elements[action].classList.toggle('--pressed', this.previous_input.has(action)); } + + if (this.debug.enabled) { + let t = this.level.tic_counter; + this.debug.time_tics_el.textContent = `${t}`; + this.debug.time_moves_el.textContent = `${Math.floor(t/4)}`; + this.debug.time_secs_el.textContent = (t / 20).toFixed(2); + } } toggle_pause() { @@ -1108,22 +1224,24 @@ class Player extends PrimaryView { let scorecard = this.level.get_scorecard(); let savefile = this.conductor.current_pack_savefile; let old_scorecard; - if (! savefile.scorecards[level_index] || - savefile.scorecards[level_index].score < scorecard.score || - (savefile.scorecards[level_index].score === scorecard.score && - savefile.scorecards[level_index].aid > scorecard.aid)) - { - old_scorecard = savefile.scorecards[level_index]; + if (! this.debug.enabled) { + if (! savefile.scorecards[level_index] || + savefile.scorecards[level_index].score < scorecard.score || + (savefile.scorecards[level_index].score === scorecard.score && + savefile.scorecards[level_index].aid > scorecard.aid)) + { + old_scorecard = savefile.scorecards[level_index]; - // Adjust the total score - savefile.total_score = savefile.total_score ?? 0; - if (old_scorecard) { - savefile.total_score -= old_scorecard.score; + // Adjust the total score + savefile.total_score = savefile.total_score ?? 0; + if (old_scorecard) { + savefile.total_score -= old_scorecard.score; + } + savefile.total_score += scorecard.score; + + savefile.scorecards[level_index] = scorecard; + this.conductor.save_savefile(); } - savefile.total_score += scorecard.score; - - savefile.scorecards[level_index] = scorecard; - this.conductor.save_savefile(); } overlay_reason = 'success'; diff --git a/js/tiletypes.js b/js/tiletypes.js index b6a3a1d..539f33a 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -1174,9 +1174,7 @@ const TILE_TYPES = { // Buttons button_blue: { draw_layer: DRAW_LAYERS.terrain, - on_arrive(me, level, other) { - level.sfx.play_once('button-press', me.cell); - + do_button(level) { // Flip direction of all blue tanks for (let actor of level.actors) { // TODO generify somehow?? @@ -1185,6 +1183,10 @@ const TILE_TYPES = { } } }, + on_arrive(me, level, other) { + level.sfx.play_once('button-press', me.cell); + me.type.do_button(level); + }, on_depart(me, level, other) { level.sfx.play_once('button-release', me.cell); }, @@ -1209,9 +1211,7 @@ const TILE_TYPES = { }, button_green: { draw_layer: DRAW_LAYERS.terrain, - on_arrive(me, level, other) { - level.sfx.play_once('button-press', me.cell); - + do_button(level) { // Swap green floors and walls // TODO could probably make this more compact for undo purposes for (let row of level.cells) { @@ -1233,6 +1233,10 @@ const TILE_TYPES = { } } }, + on_arrive(me, level, other) { + level.sfx.play_once('button-press', me.cell); + me.type.do_button(level); + }, on_depart(me, level, other) { level.sfx.play_once('button-release', me.cell); }, diff --git a/style.css b/style.css index 2c34189..f4ab3d9 100644 --- a/style.css +++ b/style.css @@ -202,10 +202,15 @@ svg.svg-icon { dl.formgrid { display: grid; grid: auto-flow min-content / 1fr 4fr; + align-items: baseline; gap: 1em; margin: 0; } +dl.formgrid > dt { + grid-column: 1; +} dl.formgrid > dd { + grid-column: 2; margin: 0; } @@ -561,7 +566,7 @@ button.level-pack-button p { "level inventory" min-content "level actions" min-content /* Need explicit min-content to force the hint to wrap */ - / min-content min-content + / min-content min-content min-content ; column-gap: 2em; row-gap: 0.5em; @@ -603,6 +608,10 @@ button.level-pack-button p { text-align: center; text-shadow: 0 2px 1px black; } +/* Allow clicking through the overlay in debug mode */ +#player.--debug .overlay-message { + pointer-events: none; +} #player .overlay-message p { margin: 0; } @@ -840,13 +849,76 @@ main.--has-demo .demo-controls { } /* Debug stuff */ +#player.--debug #player-debug { + display: grid; +} #player-debug { display: none; + grid: + "time inventory options" + "buttons buttons buttons" + / 2fr 1fr 2fr + ; + gap: 0.25em; + padding: 0.5em; background-image: repeating-linear-gradient(135deg, - hsl(0, 0%, 12.5%) 0em, - hsl(0, 0%, 12.5%) 1em, - hsl(45, 25%, 12.5%) 1em, - hsl(45, 25%, 12.5%) 2em); + hsl(0, 0%, 4%) 0em, + hsl(0, 0%, 4%) 1em, + hsl(15, 25%, 8%) 1em, + hsl(15, 25%, 8%) 2em); + border: 0.25em solid hsla(30, 100%, 50%, 0.5); + box-shadow: inset 0 0 0.25em 0.25em #0004; + +} +#player-debug > .-time { + grid-area: time; +} +#player-debug > .-time table.-time-controls { +} +#player-debug > .-time table.-time-controls button { + width: 100%; + text-align: inherit; +} +#player-debug > .-time table.-time-controls td:nth-child(1) { + /* go backwards button */ + text-align: left; +} +#player-debug > .-time table.-time-controls td:nth-child(2) { + /* value */ + width: 6em; + text-align: right; +} +#player-debug > .-time table.-time-controls td:nth-child(3) { + /* label */ +} +#player-debug > .-time table.-time-controls td:nth-child(4) { + /* go forward button */ + text-align: right; +} +#player-debug > .-options { + grid-area: options; +} +#player-debug > .-inventory { + grid-area: inventory; + display: grid; + margin: auto; + grid: auto-fill var(--tile-height) / repeat(4, var(--tile-width)); + gap: 2px; +} +#player-debug > .-inventory > button { + padding: 0; +} +#player-debug > .-inventory > button > img { + display: block; +} +#player-debug > .-inventory > button.-wide { + grid-column: span 4; + padding: 0.25em; +} +#player-debug > .-buttons { + grid-area: buttons; + display: flex; + gap: 0.25em; } .input { display: grid;