Fix some minor wire bugs: NOT/counter/pink button power drawing, circuit block motion, nested wire tunnels

This commit is contained in:
Eevee (Evelyn Woods) 2020-12-15 22:57:32 -07:00
parent 3790e0f07e
commit 62eb1a86e4
3 changed files with 81 additions and 62 deletions

View File

@ -151,7 +151,7 @@ export class Cell extends Array {
get_wired_tile() { get_wired_tile() {
let ret = null; let ret = null;
for (let tile of this) { for (let tile of this) {
if (tile.wire_directions || tile.wire_tunnel_directions) { if ((tile.wire_directions || tile.wire_tunnel_directions) && ! tile.movement_cooldown) {
ret = tile; ret = tile;
// Don't break; we want the topmost tile! // Don't break; we want the topmost tile!
} }
@ -1430,7 +1430,6 @@ export class Level {
// - make this undoable :( // - make this undoable :(
// - blue tele, red tele, and pink button have different connections // - blue tele, red tele, and pink button have different connections
// - would like to reuse the walk for blue teles // - would like to reuse the walk for blue teles
// - currently doesn't notice when circuit block moves sometimes
// Gather every tile that's emitting power. Along the way, check whether any of them have // Gather every tile that's emitting power. Along the way, check whether any of them have
// changed since last tic, so we can skip this work entirely if none did // changed since last tic, so we can skip this work entirely if none did
@ -1453,11 +1452,11 @@ export class Level {
if (! actor.cell) if (! actor.cell)
continue; continue;
// Only count when they're on a floor tile AND not in transit! // Only count when they're on a floor tile AND not in transit!
let emitting = 0; let emitting = null;
if (actor.movement_cooldown === 0 && actor.has_item('lightning_bolt')) { if (actor.movement_cooldown === 0 && actor.has_item('lightning_bolt')) {
let wired_tile = actor.cell.get_wired_tile(); let wired_tile = actor.cell.get_wired_tile();
if (wired_tile && wired_tile.type.name === 'floor') { if (wired_tile && (wired_tile === actor || wired_tile.type.name === 'floor')) {
emitting = true; emitting = wired_tile.wire_directions;
neighbors.push([actor.cell, wired_tile.wire_directions]); neighbors.push([actor.cell, wired_tile.wire_directions]);
} }
} }
@ -1531,7 +1530,6 @@ export class Level {
let opposite_bit = DIRECTIONS[dirinfo.opposite].bit; let opposite_bit = DIRECTIONS[dirinfo.opposite].bit;
if (wire && (wire.wire_tunnel_directions & dirinfo.bit)) { if (wire && (wire.wire_tunnel_directions & dirinfo.bit)) {
// Search in the given direction until we find a matching tunnel // Search in the given direction until we find a matching tunnel
// FIXME these act like nested parens!
let x = cell.x; let x = cell.x;
let y = cell.y; let y = cell.y;
let nesting = 0; let nesting = 0;
@ -1543,10 +1541,20 @@ export class Level {
let candidate = this.cells[y][x]; let candidate = this.cells[y][x];
neighbor_wire = candidate.get_wired_tile(); neighbor_wire = candidate.get_wired_tile();
if (neighbor_wire && ((neighbor_wire.wire_tunnel_directions ?? 0) & opposite_bit)) { if (neighbor_wire) {
if ((neighbor_wire.wire_tunnel_directions ?? 0) & opposite_bit) {
if (nesting === 0) {
neighbor = candidate; neighbor = candidate;
break; break;
} }
else {
nesting -= 1;
}
}
if ((neighbor_wire.wire_tunnel_directions ?? 0) & dirinfo.bit) {
nesting += 1;
}
}
} }
} }
else { else {

View File

@ -982,6 +982,10 @@ export class Tileset {
// What goes on top varies a bit... // What goes on top varies a bit...
// FIXME implement for NOT and counter! // FIXME implement for NOT and counter!
let r = this.layout['#wire-width'] / 2; let r = this.layout['#wire-width'] / 2;
if (tile.gate_type === 'not' || tile.gate_type === 'counter') {
this._draw_fourway_tile_power(tile, 0x0f, blit);
}
else {
if (tile.cell.powered_edges & DIRECTIONS[tile.direction].bit) { if (tile.cell.powered_edges & DIRECTIONS[tile.direction].bit) {
// Output (on top) // Output (on top)
let [x0, y0, x1, y1] = this._rotate(tile.direction, 0.5 - r, 0, 0.5 + r, 0.5); let [x0, y0, x1, y1] = this._rotate(tile.direction, 0.5 - r, 0, 0.5 + r, 0.5);
@ -998,6 +1002,7 @@ export class Tileset {
blit(powered_coords[0], powered_coords[1], x0, y0, x1 - x0, y1 - y0); blit(powered_coords[0], powered_coords[1], x0, y0, x1 - x0, y1 - y0);
} }
} }
}
// Layer 2: the tile itself // Layer 2: the tile itself
this._draw_standard(drawspec.logic_gate_tiles[tile.gate_type], tile, tic, blit); this._draw_standard(drawspec.logic_gate_tiles[tile.gate_type], tile, tic, blit);
@ -1008,6 +1013,42 @@ export class Tileset {
} }
} }
_draw_fourway_tile_power(tile, wires, blit) {
// Draw the unpowered tile underneath, if any edge is unpowered (and in fact if /none/ of it
// is powered then we're done here)
let powered = (tile.cell ? tile.cell.powered_edges : 0) & wires;
if (! tile.cell || powered !== tile.wire_directions) {
this._draw_fourway_power_underlay(this.layout['#unpowered'], wires, blit);
if (! tile.cell || powered === 0)
return;
}
this._draw_fourway_power_underlay(this.layout['#powered'], powered, blit);
}
_draw_fourway_power_underlay(drawspec, bits, blit) {
// Draw the part as a single rectangle, initially just a small dot in the center, but
// extending out to any edge that has a bit present
let wire_radius = this.layout['#wire-width'] / 2;
let x0 = 0.5 - wire_radius;
let x1 = 0.5 + wire_radius;
let y0 = 0.5 - wire_radius;
let y1 = 0.5 + wire_radius;
if (bits & DIRECTIONS['north'].bit) {
y0 = 0;
}
if (bits & DIRECTIONS['east'].bit) {
x1 = 1;
}
if (bits & DIRECTIONS['south'].bit) {
y1 = 1;
}
if (bits & DIRECTIONS['west'].bit) {
x0 = 0;
}
blit(drawspec[0], drawspec[1], x0, y0, x1 - x0, y1 - y0);
}
_draw_railroad(drawspec, tile, tic, blit) { _draw_railroad(drawspec, tile, tic, blit) {
// All railroads have regular gravel underneath // All railroads have regular gravel underneath
// TODO would be nice to disambiguate since it's possible to have nothing visible // TODO would be nice to disambiguate since it's possible to have nothing visible
@ -1107,48 +1148,13 @@ export class Tileset {
else if (drawspec.wired) { else if (drawspec.wired) {
// This /should/ match CC2's draw order exactly, based on experimentation // This /should/ match CC2's draw order exactly, based on experimentation
let wire_radius = this.layout['#wire-width'] / 2; let wire_radius = this.layout['#wire-width'] / 2;
if (tile && tile.wire_directions === 0x0f) { // TODO circuit block with a lightning bolt is always powered
// This is a wired tile with crossing wires, which acts a little differently // TODO circuit block in motion doesn't inherit cell's power
if (tile && tile.wire_directions) {
// Draw the base tile // Draw the base tile
blit(drawspec.base[0], drawspec.base[1]); blit(drawspec.base[0], drawspec.base[1]);
// Draw the two wires as separate rectangles, NS then EW this._draw_fourway_tile_power(tile, tile.wire_directions, blit);
let wire_inset = 0.5 - wire_radius;
let wire_coords_ns = this.layout[
tile.cell && tile.cell.powered_edges & DIRECTIONS['north'].bit ? '#powered' : '#unpowered'];
let wire_coords_ew = this.layout[
tile.cell && tile.cell.powered_edges & DIRECTIONS['east'].bit ? '#powered' : '#unpowered'];
blit(wire_coords_ns[0], wire_coords_ns[1], wire_inset, 0, wire_radius * 2, 1);
blit(wire_coords_ew[0], wire_coords_ew[1], 0, wire_inset, 1, wire_radius * 2);
// Draw the cross tile on top
coords = drawspec.wired_cross ?? drawspec.wired;
}
else if (tile && tile.wire_directions) {
// Draw the base tile
blit(drawspec.base[0], drawspec.base[1]);
// FIXME some tiles don't have active wiring on all sides...
// Draw the wire part as a single rectangle, initially just a small dot in the
// center, but extending out to any edge that has a wire present
let x0 = 0.5 - wire_radius;
let x1 = 0.5 + wire_radius;
let y0 = 0.5 - wire_radius;
let y1 = 0.5 + wire_radius;
if (tile.wire_directions & DIRECTIONS['north'].bit) {
y0 = 0;
}
if (tile.wire_directions & DIRECTIONS['east'].bit) {
x1 = 1;
}
if (tile.wire_directions & DIRECTIONS['south'].bit) {
y1 = 1;
}
if (tile.wire_directions & DIRECTIONS['west'].bit) {
x0 = 0;
}
let wire_coords = this.layout[tile.cell && tile.cell.powered_edges ? '#powered' : '#unpowered'];
blit(wire_coords[0], wire_coords[1], x0, y0, x1 - x0, y1 - y0);
// Then draw the wired tile on top of it all // Then draw the wired tile on top of it all
coords = drawspec.wired; coords = drawspec.wired;

View File

@ -1528,7 +1528,6 @@ const TILE_TYPES = {
}, },
}, },
button_black: { button_black: {
// TODO not implemented
draw_layer: DRAW_LAYERS.terrain, draw_layer: DRAW_LAYERS.terrain,
is_power_source: true, is_power_source: true,
get_emitting_edges(me, level) { get_emitting_edges(me, level) {
@ -1540,6 +1539,12 @@ const TILE_TYPES = {
return 0; return 0;
} }
}, },
on_arrive(me, level, other) {
level.sfx.play_once('button-press', me.cell);
},
on_depart(me, level, other) {
level.sfx.play_once('button-release', me.cell);
},
}, },
button_gray: { button_gray: {
// TODO only partially implemented // TODO only partially implemented