From de53582d476114ef63a7a890930d29ec7a10ab6f Mon Sep 17 00:00:00 2001 From: "Eevee (Evelyn Woods)" Date: Tue, 29 Dec 2020 20:42:53 -0700 Subject: [PATCH] Fix perception and use it to implement the xray eye --- js/main-editor.js | 2 +- js/main.js | 2 ++ js/renderer-canvas.js | 48 ++++++++++++++++++++++++++++--------------- js/tileset.js | 40 ++++++++++++++++++++---------------- 4 files changed, 57 insertions(+), 35 deletions(-) diff --git a/js/main-editor.js b/js/main-editor.js index 0d1febd..e631197 100644 --- a/js/main-editor.js +++ b/js/main-editor.js @@ -1504,7 +1504,7 @@ export class Editor extends PrimaryView { // FIXME don't hardcode size here, convey this to renderer some other way this.renderer = new CanvasRenderer(this.conductor.tileset, 32); - this.renderer.perception = 2; + this.renderer.perception = 'editor'; // FIXME need this in load_level which is called even if we haven't been setup yet this.connections_g = mk_svg('g'); diff --git a/js/main.js b/js/main.js index 4c24b49..dfa2741 100644 --- a/js/main.js +++ b/js/main.js @@ -1309,6 +1309,8 @@ class Player extends PrimaryView { this.current_toolbelt[i] = tool; } + this.renderer.perception = (this.level && this.level.player.has_item('xray_eye')) ? 'xray' : 'normal'; + if (this.debug.enabled) { let t = this.level.tic_counter; this.debug.time_tics_el.textContent = `${t}`; diff --git a/js/renderer-canvas.js b/js/renderer-canvas.js index 01d736f..5e8fded 100644 --- a/js/renderer-canvas.js +++ b/js/renderer-canvas.js @@ -27,7 +27,7 @@ export class CanvasRenderer { this.viewport_dirty = false; this.show_actor_bboxes = false; this.use_rewind_effect = false; - this.perception = 0; // 0 normal, 1 secret eye, 2 editor + this.perception = 'normal'; // normal, xray, editor, palette } set_level(level) { @@ -70,6 +70,18 @@ export class CanvasRenderer { dx * tw, dy * th, w * tw, h * th); } + _make_tileset_blitter(ctx, offsetx = 0, offsety = 0) { + // The blit we pass to the tileset has a different signature than our own: + // blit( + // source_tile_x, source_tile_y, + // mask_x = 0, mask_y = 0, mask_width = 1, mask_height = mask_width, + // mask_dx = mask_x, mask_dy = mask_y) + // This makes it easier to use in the extremely common case of drawing part of one tile atop + // another tile, but still aligned to the grid. + return (tx, ty, mx = 0, my = 0, mw = 1, mh = mw, mdx = mx, mdy = my) => + this.blit(ctx, tx + mx, ty + my, offsetx + mdx, offsety + mdy, mw, mh); + } + draw(tic_offset = 0) { if (! this.level) { console.warn("CanvasRenderer.draw: No level to render"); @@ -144,10 +156,12 @@ export class CanvasRenderer { // neighboring terrain // FIXME this is a bit inefficient when there are a lot of rarely-used layers; consider // instead drawing everything under actors, then actors, then everything above actors? + // (note: will need to first fix the game to ensure everything is stacked correctly!) for (let layer = 0; layer < DRAW_LAYERS.MAX; layer++) { for (let x = xf0; x <= x1; x++) { for (let y = yf0; y <= y1; y++) { - for (let tile of this.level.cell(x, y)) { + let cell = this.level.cell(x, y); + for (let tile of cell) { if (tile.type.draw_layer !== layer) continue; @@ -168,18 +182,20 @@ export class CanvasRenderer { vy = y; } - // Note that the blit we pass to the tileset has a different signature: - // blit( - // source_tile_x, source_tile_y, - // mask_x = 0, mask_y = 0, mask_width = 1, mask_height = mask_width, - // mask_dx = mask_x, mask_dy = mask_y) - // This makes it easier to use in the extremely common case of drawing - // part of one tile atop another tile, but still aligned to the grid. - this.tileset.draw(tile, tic, (tx, ty, mx = 0, my = 0, mw = 1, mh = mw, mdx = mx, mdy = my) => - this.blit(this.ctx, - tx + mx, ty + my, - vx - x0 + mdx, vy - y0 + mdy, - mw, mh)); + // For actors (i.e., blocks), perception only applies if there's something + // of potential interest underneath + let perception = this.perception; + if (perception !== 'normal' && tile.type.is_actor && + ! cell.some(t => + t.type.draw_layer < layer && + ! (t.type.name === 'floor' && (t.wire_directions | t.wire_tunnel_directions) === 0))) + { + perception = 'normal'; + } + + this.tileset.draw( + tile, tic, perception, + this._make_tileset_blitter(this.ctx, vx - x0, vy - y0)); } } } @@ -221,8 +237,8 @@ export class CanvasRenderer { create_tile_type_canvas(name, tile = null) { let canvas = mk('canvas', {width: this.tileset.size_x, height: this.tileset.size_y}); let ctx = canvas.getContext('2d'); - this.tileset.draw_type(name, tile, 0, this.perception, (tx, ty, mx = 0, my = 0, mw = 1, mh = mw, mdx = mx, mdy = my) => - this.blit(ctx, tx + mx, ty + my, mdx, mdy, mw, mh)); + // Individual tile types always reveal what they are + this.tileset.draw_type(name, tile, 0, 'palette', this._make_tileset_blitter(ctx)); return canvas; } } diff --git a/js/tileset.js b/js/tileset.js index c635f6a..83d0634 100644 --- a/js/tileset.js +++ b/js/tileset.js @@ -43,10 +43,9 @@ export const CC2_TILESET_LAYOUT = { key_blue: [5, 1], key_yellow: [6, 1], key_green: [7, 1], - // FIXME these shouldn't be drawn with a hole when drawn in isolation, gruh dirt_block: { special: 'perception', - threshold: 2, + modes: new Set(['editor', 'xray']), hidden: [8, 1], revealed: [9, 1], }, @@ -64,10 +63,9 @@ export const CC2_TILESET_LAYOUT = { wired_cross: [10, 26], is_wired_optional: true, }, - // FIXME i think these are visible with the secret eye, but my tileset puts text on them, whoops wall_invisible: { special: 'perception', - threshold: 2, + modes: new Set(['palette', 'editor', 'xray']), hidden: [0, 2], revealed: [9, 31], }, @@ -75,7 +73,7 @@ export const CC2_TILESET_LAYOUT = { wall_invisible_revealed: [1, 2], wall_appearing: { special: 'perception', - threshold: 2, + modes: new Set(['palette', 'editor', 'xray']), hidden: [0, 2], revealed: [11, 31], }, @@ -109,10 +107,9 @@ export const CC2_TILESET_LAYOUT = { [8, 2], [9, 2], ], - // FIXME these shouldn't be drawn with a hole when drawn in isolation, gruh ice_block: { special: 'perception', - threshold: 2, + modes: new Set(['editor', 'xray']), hidden: [10, 2], revealed: [11, 2], }, @@ -123,12 +120,21 @@ export const CC2_TILESET_LAYOUT = { // LCD digit font green_chip: [9, 3], - chip_extra: [10, 3], + chip_extra: { + special: 'perception', + modes: new Set(['palette', 'editor']), + hidden: [11, 3], + revealed: [10, 3], + }, chip: [11, 3], bribe: [12, 3], speed_boots: [13, 3], - canopy: [14, 3], - // canopy xray + canopy: { + special: 'perception', + modes: new Set(['editor', 'xray']), + hidden: [14, 3], + revealed: [15, 3], + }, dynamite: [0, 4], // FIXME lit frames @@ -153,7 +159,7 @@ export const CC2_TILESET_LAYOUT = { popdown_wall: [12, 5], popdown_floor: { special: 'perception', - threshold: 2, + modes: new Set(['palette', 'editor', 'xray']), hidden: [12, 5], revealed: [13, 5], }, @@ -238,10 +244,9 @@ export const CC2_TILESET_LAYOUT = { ], fake_wall: [0, 10], - // FIXME i think these are visible with the secret eye, but my tileset puts text on them, whoops fake_floor: { special: 'perception', - threshold: 2, + modes: new Set(['palette', 'editor', 'xray']), hidden: [0, 10], revealed: [10, 31], }, @@ -318,7 +323,7 @@ export const CC2_TILESET_LAYOUT = { // TODO [0, 16] some kinda red/blue outline floor_mimic: { special: 'perception', - threshold: 1, + modes: new Set(['palette', 'editor', 'xray']), hidden: [0, 2], revealed: [14, 16], }, @@ -893,9 +898,8 @@ export class Tileset { this.animation_slowdown = 2; } - draw(tile, tic, blit) { - // FIXME perception - this.draw_type(tile.type.name, tile, tic, 0, blit); + draw(tile, tic, perception, blit) { + this.draw_type(tile.type.name, tile, tic, perception, blit); } // Draw a "standard" drawspec, which is either: @@ -1174,7 +1178,7 @@ export class Tileset { return; } else if (drawspec.special === 'perception') { - if (perception >= drawspec.threshold) { + if (drawspec.modes.has(perception)) { drawspec = drawspec.revealed; } else {