diff --git a/index.html b/index.html index f83331c..9973398 100644 --- a/index.html +++ b/index.html @@ -140,7 +140,7 @@
+ p @@ -149,19 +149,19 @@ + z
+ drop q + cycle e + switch c
@@ -172,7 +172,7 @@

-
+

Hearts

diff --git a/js/game.js b/js/game.js index c747d9c..ced121f 100644 --- a/js/game.js +++ b/js/game.js @@ -412,7 +412,6 @@ export class Level extends LevelInterface { // global clock which doesn't get reset between levels (!). this.step_parity = 5; - this.hint_shown = null; // TODO in lynx/steam, this carries over between levels; in tile world, you can set it manually this.force_floor_direction = 'north'; // PRNG is initialized to zero @@ -668,9 +667,6 @@ export class Level extends LevelInterface { if (tile.type.on_ready) { tile.type.on_ready(tile, this); } - if (cell === this.player.cell && tile.type.is_hint) { - this.hint_shown = tile.hint_text ?? this.stored_level.hint; - } } } // Erase undo, in case any on_ready added to it (we don't want to undo initialization!) @@ -760,7 +756,7 @@ export class Level extends LevelInterface { for (let key of [ '_rng1', '_rng2', '_blob_modifier', 'force_floor_direction', 'tic_counter', 'time_remaining', 'timer_paused', - 'chips_remaining', 'bonus_points', 'hint_shown', 'state', + 'chips_remaining', 'bonus_points', 'state', 'remaining_players', 'player', ]) { this.pending_undo.level_props[key] = this[key]; @@ -1547,17 +1543,6 @@ export class Level extends LevelInterface { } } - // Check for a couple effects that always apply immediately - if (actor === this.player) { - this.hint_shown = null; - } - for (let tile of goal_cell) { - // FIXME this could go in on_approach now - if (tile && actor === this.player && tile.type.is_hint) { - this.hint_shown = tile.hint_text ?? this.stored_level.hint; - } - } - // Announce we're approaching. Slide mode is set here, since it's about the tile we're // moving towards and needs to last through our next decision this.make_slide(actor, null); @@ -1760,7 +1745,9 @@ export class Level extends LevelInterface { this.set_actor_direction(actor, direction); this.spawn_animation(actor.cell, 'teleport_flash'); - this.spawn_animation(dest.cell, 'teleport_flash'); + if (dest.cell !== actor.cell) { + this.spawn_animation(dest.cell, 'teleport_flash'); + } // Now physically move the actor, but their movement waits until next decision phase this.remove_tile(actor); diff --git a/js/main.js b/js/main.js index 760a3d5..9c0d5af 100644 --- a/js/main.js +++ b/js/main.js @@ -296,7 +296,7 @@ class Player extends PrimaryView { this.root.style.setProperty('--tile-height', `${this.conductor.tileset.size_y}px`); this.level_el = this.root.querySelector('.level'); this.overlay_message_el = this.root.querySelector('.overlay-message'); - this.message_el = this.root.querySelector('.message'); + this.hint_el = this.root.querySelector('.player-hint'); this.chips_el = this.root.querySelector('.chips output'); this.time_el = this.root.querySelector('.time output'); this.bonus_el = this.root.querySelector('.bonus output'); @@ -1061,6 +1061,7 @@ class Player extends PrimaryView { this.last_advance = 0; this.current_keyring = {}; this.current_toolbelt = []; + this.previous_hint_tile = null; this.chips_el.classList.remove('--done'); this.time_el.classList.remove('--frozen'); @@ -1350,7 +1351,38 @@ class Player extends PrimaryView { if (this.level.bonus_points > 0) { this.root.classList.add('--bonus-visible'); } - this.message_el.textContent = this.level.hint_shown ?? ""; + + // Check for the player standing on a hint tile; this is slightly invasive but lets us + // notice exactly when it changes (and anyway it's a UI thing, not gameplay) + let terrain = this.level.player.cell.get_terrain(); + let hint_tile = null; + if (terrain.type.is_hint) { + hint_tile = terrain; + } + if (hint_tile !== this.previous_hint_tile) { + this.previous_hint_tile = hint_tile; + this.hint_el.textContent = ''; + if (hint_tile) { + // Parse out %X sequences and replace them with elements + let hint_text = hint_tile.hint_text ?? this.level.stored_level.hint; + for (let [i, chunk] of hint_text.split(/%(\w)/).entries()) { + if (i % 2 === 0) { + this.hint_el.append(chunk); + } + else { + // TODO better place to get these? + // TODO 1 through 7 are player 2's inputs in split-screen mode + let key = { + // up, down, left, right + U: 'W', D: 'S', L: 'A', R: 'D', + // drop, cycle, swap + P: 'Q', C: 'E', S: 'C', + }[chunk] ?? "?"; + this.hint_el.append(mk('kbd', key)); + } + } + } + } this.renderer.set_active_player(this.level.remaining_players > 1 ? this.level.player : null); diff --git a/style.css b/style.css index 41c97a9..9719da4 100644 --- a/style.css +++ b/style.css @@ -125,6 +125,14 @@ pre { code { color: #c0c0e0; } +kbd { + padding: 0 0.25em; + border: 1px solid currentColor; + border-radius: 0.25em; + box-shadow: 0 2px 0 currentColor; + text-align: center; + text-transform: uppercase; +} a { color: #c0c0c0; @@ -931,7 +939,7 @@ ol.packtest-summary > li { "level chips" min-content "level time" min-content "level bonus" min-content - "level message" 1fr + "level hint" 1fr "level inventory" min-content /* Need explicit min-content to force the hint to wrap */ / min-content min-content @@ -1093,8 +1101,8 @@ dl.score-chart .-sum { display: flex; } -.message { - grid-area: message; +#player-game-area > .player-hint { + grid-area: hint; align-self: stretch; font-size: calc(var(--tile-height) * var(--scale) / 3); @@ -1105,10 +1113,10 @@ dl.score-chart .-sum { background: #080808; border: 1px inset #202020; - /* FIXME find a way to enforce that the message never makes the grid get bigger */ + /* FIXME find a way to enforce that the hint never makes the grid get bigger */ overflow: auto; } -.message:empty { +#player-game-area > .player-hint:empty { display: none; } @@ -1186,14 +1194,8 @@ dl.score-chart .-sum { left: 0; right: 0; top: -2em; - width: 1em; margin: auto; color: #404040; - border: 1px solid #202020; - border-radius: 0.25em; - box-shadow: 0 2px 0 #202020; - text-align: center; - text-transform: uppercase; } #player button:disabled .keyhint { display: none; @@ -1422,7 +1424,7 @@ body.--debug #player-debug { /* stick me in the center right */ place-self: center end; } - #player .message { + #player > .player-hint { /* Overlay hints on the inventory area */ grid-row: chips / bonus; grid-column: level;