From 62eb1a86e43cb0c6676049de418e39129b92db1d Mon Sep 17 00:00:00 2001 From: "Eevee (Evelyn Woods)" Date: Tue, 15 Dec 2020 22:57:32 -0700 Subject: [PATCH] Fix some minor wire bugs: NOT/counter/pink button power drawing, circuit block motion, nested wire tunnels --- js/game.js | 26 ++++++++---- js/tileset.js | 110 +++++++++++++++++++++++++----------------------- js/tiletypes.js | 7 ++- 3 files changed, 81 insertions(+), 62 deletions(-) diff --git a/js/game.js b/js/game.js index 1977e38..4348467 100644 --- a/js/game.js +++ b/js/game.js @@ -151,7 +151,7 @@ export class Cell extends Array { get_wired_tile() { let ret = null; 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; // Don't break; we want the topmost tile! } @@ -1430,7 +1430,6 @@ export class Level { // - make this undoable :( // - blue tele, red tele, and pink button have different connections // - 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 // changed since last tic, so we can skip this work entirely if none did @@ -1453,11 +1452,11 @@ export class Level { if (! actor.cell) continue; // 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')) { let wired_tile = actor.cell.get_wired_tile(); - if (wired_tile && wired_tile.type.name === 'floor') { - emitting = true; + if (wired_tile && (wired_tile === actor || wired_tile.type.name === 'floor')) { + emitting = 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; if (wire && (wire.wire_tunnel_directions & dirinfo.bit)) { // Search in the given direction until we find a matching tunnel - // FIXME these act like nested parens! let x = cell.x; let y = cell.y; let nesting = 0; @@ -1543,9 +1541,19 @@ export class Level { let candidate = this.cells[y][x]; neighbor_wire = candidate.get_wired_tile(); - if (neighbor_wire && ((neighbor_wire.wire_tunnel_directions ?? 0) & opposite_bit)) { - neighbor = candidate; - break; + if (neighbor_wire) { + if ((neighbor_wire.wire_tunnel_directions ?? 0) & opposite_bit) { + if (nesting === 0) { + neighbor = candidate; + break; + } + else { + nesting -= 1; + } + } + if ((neighbor_wire.wire_tunnel_directions ?? 0) & dirinfo.bit) { + nesting += 1; + } } } } diff --git a/js/tileset.js b/js/tileset.js index f4de817..41dd50d 100644 --- a/js/tileset.js +++ b/js/tileset.js @@ -982,20 +982,25 @@ export class Tileset { // What goes on top varies a bit... // FIXME implement for NOT and counter! let r = this.layout['#wire-width'] / 2; - if (tile.cell.powered_edges & DIRECTIONS[tile.direction].bit) { - // Output (on top) - let [x0, y0, x1, y1] = this._rotate(tile.direction, 0.5 - r, 0, 0.5 + r, 0.5); - blit(powered_coords[0], powered_coords[1], x0, y0, x1 - x0, y1 - y0); + if (tile.gate_type === 'not' || tile.gate_type === 'counter') { + this._draw_fourway_tile_power(tile, 0x0f, blit); } - if (tile.cell.powered_edges & DIRECTIONS[DIRECTIONS[tile.direction].right].bit) { - // Right input, which includes the middle - let [x0, y0, x1, y1] = this._rotate(tile.direction, 0.5 - r, 0.5 - r, 1, 1); - blit(powered_coords[0], powered_coords[1], x0, y0, x1 - x0, y1 - y0); - } - if (tile.cell.powered_edges & DIRECTIONS[DIRECTIONS[tile.direction].left].bit) { - // Left input, which does not include the middle - let [x0, y0, x1, y1] = this._rotate(tile.direction, 0, 0.5 - r, 0.5 - r, 1); - blit(powered_coords[0], powered_coords[1], x0, y0, x1 - x0, y1 - y0); + else { + if (tile.cell.powered_edges & DIRECTIONS[tile.direction].bit) { + // Output (on top) + let [x0, y0, x1, y1] = this._rotate(tile.direction, 0.5 - r, 0, 0.5 + r, 0.5); + blit(powered_coords[0], powered_coords[1], x0, y0, x1 - x0, y1 - y0); + } + if (tile.cell.powered_edges & DIRECTIONS[DIRECTIONS[tile.direction].right].bit) { + // Right input, which includes the middle + let [x0, y0, x1, y1] = this._rotate(tile.direction, 0.5 - r, 0.5 - r, 1, 1); + blit(powered_coords[0], powered_coords[1], x0, y0, x1 - x0, y1 - y0); + } + if (tile.cell.powered_edges & DIRECTIONS[DIRECTIONS[tile.direction].left].bit) { + // Left input, which does not include the middle + let [x0, y0, x1, y1] = this._rotate(tile.direction, 0, 0.5 - r, 0.5 - r, 1); + blit(powered_coords[0], powered_coords[1], x0, y0, x1 - x0, y1 - y0); + } } } @@ -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) { // All railroads have regular gravel underneath // 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) { // This /should/ match CC2's draw order exactly, based on experimentation let wire_radius = this.layout['#wire-width'] / 2; - if (tile && tile.wire_directions === 0x0f) { - // This is a wired tile with crossing wires, which acts a little differently + // TODO circuit block with a lightning bolt is always powered + // TODO circuit block in motion doesn't inherit cell's power + if (tile && tile.wire_directions) { // Draw the base tile blit(drawspec.base[0], drawspec.base[1]); - // Draw the two wires as separate rectangles, NS then EW - 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); + this._draw_fourway_tile_power(tile, tile.wire_directions, blit); // Then draw the wired tile on top of it all coords = drawspec.wired; diff --git a/js/tiletypes.js b/js/tiletypes.js index b9c2dc8..b600c74 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -1528,7 +1528,6 @@ const TILE_TYPES = { }, }, button_black: { - // TODO not implemented draw_layer: DRAW_LAYERS.terrain, is_power_source: true, get_emitting_edges(me, level) { @@ -1540,6 +1539,12 @@ const TILE_TYPES = { 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: { // TODO only partially implemented