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
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');

View File

@ -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}`;

View File

@ -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;
}
}

View File

@ -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 {