Fix perception and use it to implement the xray eye

This commit is contained in:
Eevee (Evelyn Woods) 2020-12-29 20:42:53 -07:00
parent 746300a514
commit de53582d47
4 changed files with 57 additions and 35 deletions

View File

@ -1504,7 +1504,7 @@ export class Editor extends PrimaryView {
// FIXME don't hardcode size here, convey this to renderer some other way // FIXME don't hardcode size here, convey this to renderer some other way
this.renderer = new CanvasRenderer(this.conductor.tileset, 32); 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 // FIXME need this in load_level which is called even if we haven't been setup yet
this.connections_g = mk_svg('g'); this.connections_g = mk_svg('g');

View File

@ -1309,6 +1309,8 @@ class Player extends PrimaryView {
this.current_toolbelt[i] = tool; this.current_toolbelt[i] = tool;
} }
this.renderer.perception = (this.level && this.level.player.has_item('xray_eye')) ? 'xray' : 'normal';
if (this.debug.enabled) { if (this.debug.enabled) {
let t = this.level.tic_counter; let t = this.level.tic_counter;
this.debug.time_tics_el.textContent = `${t}`; this.debug.time_tics_el.textContent = `${t}`;

View File

@ -27,7 +27,7 @@ export class CanvasRenderer {
this.viewport_dirty = false; this.viewport_dirty = false;
this.show_actor_bboxes = false; this.show_actor_bboxes = false;
this.use_rewind_effect = 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) { set_level(level) {
@ -70,6 +70,18 @@ export class CanvasRenderer {
dx * tw, dy * th, w * tw, h * th); 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) { draw(tic_offset = 0) {
if (! this.level) { if (! this.level) {
console.warn("CanvasRenderer.draw: No level to render"); console.warn("CanvasRenderer.draw: No level to render");
@ -144,10 +156,12 @@ export class CanvasRenderer {
// neighboring terrain // neighboring terrain
// FIXME this is a bit inefficient when there are a lot of rarely-used layers; consider // 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? // 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 layer = 0; layer < DRAW_LAYERS.MAX; layer++) {
for (let x = xf0; x <= x1; x++) { for (let x = xf0; x <= x1; x++) {
for (let y = yf0; y <= y1; y++) { 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) if (tile.type.draw_layer !== layer)
continue; continue;
@ -168,18 +182,20 @@ export class CanvasRenderer {
vy = y; vy = y;
} }
// Note that the blit we pass to the tileset has a different signature: // For actors (i.e., blocks), perception only applies if there's something
// blit( // of potential interest underneath
// source_tile_x, source_tile_y, let perception = this.perception;
// mask_x = 0, mask_y = 0, mask_width = 1, mask_height = mask_width, if (perception !== 'normal' && tile.type.is_actor &&
// mask_dx = mask_x, mask_dy = mask_y) ! cell.some(t =>
// This makes it easier to use in the extremely common case of drawing t.type.draw_layer < layer &&
// part of one tile atop another tile, but still aligned to the grid. ! (t.type.name === 'floor' && (t.wire_directions | t.wire_tunnel_directions) === 0)))
this.tileset.draw(tile, tic, (tx, ty, mx = 0, my = 0, mw = 1, mh = mw, mdx = mx, mdy = my) => {
this.blit(this.ctx, perception = 'normal';
tx + mx, ty + my, }
vx - x0 + mdx, vy - y0 + mdy,
mw, mh)); 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) { create_tile_type_canvas(name, tile = null) {
let canvas = mk('canvas', {width: this.tileset.size_x, height: this.tileset.size_y}); let canvas = mk('canvas', {width: this.tileset.size_x, height: this.tileset.size_y});
let ctx = canvas.getContext('2d'); 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) => // Individual tile types always reveal what they are
this.blit(ctx, tx + mx, ty + my, mdx, mdy, mw, mh)); this.tileset.draw_type(name, tile, 0, 'palette', this._make_tileset_blitter(ctx));
return canvas; return canvas;
} }
} }

View File

@ -43,10 +43,9 @@ export const CC2_TILESET_LAYOUT = {
key_blue: [5, 1], key_blue: [5, 1],
key_yellow: [6, 1], key_yellow: [6, 1],
key_green: [7, 1], key_green: [7, 1],
// FIXME these shouldn't be drawn with a hole when drawn in isolation, gruh
dirt_block: { dirt_block: {
special: 'perception', special: 'perception',
threshold: 2, modes: new Set(['editor', 'xray']),
hidden: [8, 1], hidden: [8, 1],
revealed: [9, 1], revealed: [9, 1],
}, },
@ -64,10 +63,9 @@ export const CC2_TILESET_LAYOUT = {
wired_cross: [10, 26], wired_cross: [10, 26],
is_wired_optional: true, is_wired_optional: true,
}, },
// FIXME i think these are visible with the secret eye, but my tileset puts text on them, whoops
wall_invisible: { wall_invisible: {
special: 'perception', special: 'perception',
threshold: 2, modes: new Set(['palette', 'editor', 'xray']),
hidden: [0, 2], hidden: [0, 2],
revealed: [9, 31], revealed: [9, 31],
}, },
@ -75,7 +73,7 @@ export const CC2_TILESET_LAYOUT = {
wall_invisible_revealed: [1, 2], wall_invisible_revealed: [1, 2],
wall_appearing: { wall_appearing: {
special: 'perception', special: 'perception',
threshold: 2, modes: new Set(['palette', 'editor', 'xray']),
hidden: [0, 2], hidden: [0, 2],
revealed: [11, 31], revealed: [11, 31],
}, },
@ -109,10 +107,9 @@ export const CC2_TILESET_LAYOUT = {
[8, 2], [8, 2],
[9, 2], [9, 2],
], ],
// FIXME these shouldn't be drawn with a hole when drawn in isolation, gruh
ice_block: { ice_block: {
special: 'perception', special: 'perception',
threshold: 2, modes: new Set(['editor', 'xray']),
hidden: [10, 2], hidden: [10, 2],
revealed: [11, 2], revealed: [11, 2],
}, },
@ -123,12 +120,21 @@ export const CC2_TILESET_LAYOUT = {
// LCD digit font // LCD digit font
green_chip: [9, 3], 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], chip: [11, 3],
bribe: [12, 3], bribe: [12, 3],
speed_boots: [13, 3], speed_boots: [13, 3],
canopy: [14, 3], canopy: {
// canopy xray special: 'perception',
modes: new Set(['editor', 'xray']),
hidden: [14, 3],
revealed: [15, 3],
},
dynamite: [0, 4], dynamite: [0, 4],
// FIXME lit frames // FIXME lit frames
@ -153,7 +159,7 @@ export const CC2_TILESET_LAYOUT = {
popdown_wall: [12, 5], popdown_wall: [12, 5],
popdown_floor: { popdown_floor: {
special: 'perception', special: 'perception',
threshold: 2, modes: new Set(['palette', 'editor', 'xray']),
hidden: [12, 5], hidden: [12, 5],
revealed: [13, 5], revealed: [13, 5],
}, },
@ -238,10 +244,9 @@ export const CC2_TILESET_LAYOUT = {
], ],
fake_wall: [0, 10], fake_wall: [0, 10],
// FIXME i think these are visible with the secret eye, but my tileset puts text on them, whoops
fake_floor: { fake_floor: {
special: 'perception', special: 'perception',
threshold: 2, modes: new Set(['palette', 'editor', 'xray']),
hidden: [0, 10], hidden: [0, 10],
revealed: [10, 31], revealed: [10, 31],
}, },
@ -318,7 +323,7 @@ export const CC2_TILESET_LAYOUT = {
// TODO [0, 16] some kinda red/blue outline // TODO [0, 16] some kinda red/blue outline
floor_mimic: { floor_mimic: {
special: 'perception', special: 'perception',
threshold: 1, modes: new Set(['palette', 'editor', 'xray']),
hidden: [0, 2], hidden: [0, 2],
revealed: [14, 16], revealed: [14, 16],
}, },
@ -893,9 +898,8 @@ export class Tileset {
this.animation_slowdown = 2; this.animation_slowdown = 2;
} }
draw(tile, tic, blit) { draw(tile, tic, perception, blit) {
// FIXME perception this.draw_type(tile.type.name, tile, tic, perception, blit);
this.draw_type(tile.type.name, tile, tic, 0, blit);
} }
// Draw a "standard" drawspec, which is either: // Draw a "standard" drawspec, which is either:
@ -1174,7 +1178,7 @@ export class Tileset {
return; return;
} }
else if (drawspec.special === 'perception') { else if (drawspec.special === 'perception') {
if (perception >= drawspec.threshold) { if (drawspec.modes.has(perception)) {
drawspec = drawspec.revealed; drawspec = drawspec.revealed;
} }
else { else {