diff --git a/js/game.js b/js/game.js index 640e4e3..2fdd27e 100644 --- a/js/game.js +++ b/js/game.js @@ -78,9 +78,10 @@ export class Tile { return false; } - can_push(tile) { + can_push(tile, direction) { return ( this.type.pushes && this.type.pushes[tile.type.name] && + (! tile.type.allows_push || tile.type.allows_push(tile, direction)) && ! tile.stuck); } @@ -150,7 +151,7 @@ export class Cell extends Array { blocks_entering(actor, direction, level, ignore_pushables = false) { for (let tile of this) { if (tile.blocks(actor, direction, level) && - ! (ignore_pushables && actor.can_push(tile))) + ! (ignore_pushables && actor.can_push(tile, direction))) { return true; } @@ -729,7 +730,7 @@ export class Level { if (tile.type.on_bump) { tile.type.on_bump(tile, this, actor); } - if (could_push && actor.can_push(tile)) { + if (could_push && actor.can_push(tile, dir2)) { // Block slapping: you can shove a block by walking past it sideways // TODO i think cc2 uses the push pose and possibly even turns you here? this.attempt_step(tile, dir2); @@ -824,7 +825,7 @@ export class Level { let blocked_by_pushable = false; for (let tile of goal_cell) { if (tile.blocks(actor, direction, this)) { - if (actor.can_push(tile)) { + if (actor.can_push(tile, direction)) { blocked_by_pushable = true; } else { @@ -855,7 +856,7 @@ export class Level { if (! blocked && blocked_by_pushable) { // This time make a copy, since we're modifying the contents of the cell for (let tile of Array.from(goal_cell)) { - if (actor.can_push(tile)) { + if (actor.can_push(tile, direction)) { if (! this.attempt_step(tile, direction) && tile.slide_mode !== null && tile.movement_cooldown !== 0) { diff --git a/js/tileset.js b/js/tileset.js index 5fd9da5..4bc24be 100644 --- a/js/tileset.js +++ b/js/tileset.js @@ -99,8 +99,10 @@ export const CC2_TILESET_LAYOUT = { popdown_floor: [12, 5], popdown_floor_visible: [13, 5], no_sign: [14, 5], - // TODO arrows overlay at [3, 10] - directional_block: [15, 5], + directional_block: { + base: [15, 5], + arrows: [3, 10], + }, flippers: [0, 6], fire_boots: [1, 6], @@ -711,6 +713,10 @@ export class Tileset { } } } + else if (drawspec.arrows) { + // Directional blocks have a specific overlay, but draw the base first + coords = drawspec.base; + } else if (drawspec.animate_width) { // Force floors animate their... cutout, I guess? let [x, y] = drawspec.base; @@ -826,6 +832,23 @@ export class Tileset { } } + // Directional blocks have arrows drawn on top + if (drawspec.arrows && tile && tile.arrows) { + let [x, y] = drawspec.arrows; + if (tile.arrows.has('north')) { + blit(x, y, 0, 0, 1, 0.25); + } + if (tile.arrows.has('east')) { + blit(x + 0.75, y, 0.75, 0, 0.25, 1); + } + if (tile.arrows.has('south')) { + blit(x, y + 0.75, 0, 0.75, 1, 0.25); + } + if (tile.arrows.has('west')) { + blit(x, y, 0, 0, 0.25, 1); + } + } + // Special behavior for special objects // TODO? hardcode this less? if (name === 'floor_letter') { diff --git a/js/tiletypes.js b/js/tiletypes.js index a4aed66..d036568 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -384,6 +384,10 @@ const TILE_TYPES = { level.transmute_tile(other, 'splash'); level.transmute_tile(me, 'dirt'); } + else if (other.type.name === 'directional_block') { + level.transmute_tile(other, 'splash'); + level.transmute_tile(me, 'floor'); + } else if (other.type.name === 'ice_block') { level.transmute_tile(other, 'splash'); level.transmute_tile(me, 'ice'); @@ -591,6 +595,9 @@ const TILE_TYPES = { is_block: true, can_reveal_walls: true, movement_speed: 4, + allows_push(me, direction) { + return me.arrows && me.arrows.has(direction); + }, pushes: { dirt_block: true, ice_block: true,