Implement CC2 input handling, bumping, and block slapping
This commit is contained in:
parent
64bd6c49d9
commit
5d39e37ad2
32
js/game.js
32
js/game.js
@ -330,7 +330,7 @@ export class Level {
|
||||
}
|
||||
|
||||
// Move the game state forwards by one tic
|
||||
advance_tic(player_direction) {
|
||||
advance_tic(p1_primary_direction, p1_secondary_direction) {
|
||||
if (this.state !== 'playing') {
|
||||
console.warn(`Level.advance_tic() called when state is ${this.state}`);
|
||||
return;
|
||||
@ -391,6 +391,10 @@ export class Level {
|
||||
if (actor.type.uses_teeth_hesitation && (this.tic_counter + this.step_parity) % 8 >= 4)
|
||||
continue;
|
||||
|
||||
if (actor.type.is_player) {
|
||||
this._set_prop(actor, 'secondary_direction', p1_secondary_direction);
|
||||
}
|
||||
|
||||
let direction_preference;
|
||||
// Actors can't make voluntary moves on ice, so they're stuck with
|
||||
// whatever they've got
|
||||
@ -405,10 +409,10 @@ export class Level {
|
||||
// can override forwards??) and DEFINITELY all kinds of stuff
|
||||
// in ms
|
||||
if (actor === this.player &&
|
||||
player_direction &&
|
||||
p1_primary_direction &&
|
||||
actor.last_move_was_force)
|
||||
{
|
||||
direction_preference = [player_direction];
|
||||
direction_preference = [p1_primary_direction];
|
||||
this._set_prop(actor, 'last_move_was_force', false);
|
||||
}
|
||||
else {
|
||||
@ -419,8 +423,8 @@ export class Level {
|
||||
}
|
||||
}
|
||||
else if (actor === this.player) {
|
||||
if (player_direction) {
|
||||
direction_preference = [player_direction];
|
||||
if (p1_primary_direction) {
|
||||
direction_preference = [p1_primary_direction];
|
||||
this._set_prop(actor, 'last_move_was_force', false);
|
||||
}
|
||||
}
|
||||
@ -753,6 +757,24 @@ export class Level {
|
||||
}
|
||||
}
|
||||
|
||||
// Players can also bump the tiles next to where they landed
|
||||
if (actor.type.is_player && actor.secondary_direction) {
|
||||
let neighbor = this.cell_with_offset(actor.cell, actor.secondary_direction);
|
||||
if (neighbor) {
|
||||
for (let tile of neighbor) {
|
||||
// TODO repeating myself with tile.stuck (also should technically check for actor)
|
||||
if (actor.type.pushes && actor.type.pushes[tile.type.name] && ! tile.stuck) {
|
||||
// Block slapping: you can shove a block by walking past it sideways
|
||||
this.set_actor_direction(tile, actor.secondary_direction);
|
||||
this.attempt_step(tile, actor.secondary_direction);
|
||||
}
|
||||
else if (tile.type.on_bump) {
|
||||
tile.type.on_bump(tile, this, actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle teleporting, now that the dust has cleared
|
||||
// FIXME something funny happening here, your input isn't ignore while walking out of it?
|
||||
let current_cell = actor.cell;
|
||||
|
||||
70
js/main.js
70
js/main.js
@ -414,41 +414,57 @@ class Player extends PrimaryView {
|
||||
advance_by(tics) {
|
||||
for (let i = 0; i < tics; i++) {
|
||||
let input = this.get_input();
|
||||
let current_input = input;
|
||||
if (! input.has('up') && ! input.has('down') && ! input.has('left') && ! input.has('right')) {
|
||||
//input = this.previous_input;
|
||||
}
|
||||
|
||||
// Choose the movement direction based on the held keys. A
|
||||
// newly pressed action takes priority; in the case of a tie,
|
||||
// um, XXX ????
|
||||
let chosen_action = null;
|
||||
let any_action = null;
|
||||
for (let action of ['up', 'down', 'left', 'right']) {
|
||||
if (input.has(action)) {
|
||||
if (this.previous_input.has(action)) {
|
||||
chosen_action = action;
|
||||
// Replica of CC2 input handling, based on experimentation
|
||||
// FIXME unclear how this should interact with undo when playing normally, and
|
||||
// definitely wrong when playing a replay; should this be in Level??
|
||||
if ((input.has('up') && input.has('down')) || (input.has('left') && input.has('right'))) {
|
||||
// If opposing keys are ever held, stop moving and forget our state
|
||||
this.primary_action = null;
|
||||
this.secondary_action = null;
|
||||
}
|
||||
else if (this.primary_action && input.has(this.primary_action)) {
|
||||
// Our primary action is locked in as long as it's held down, but check for a
|
||||
// newly pressed secondary action; remember, there can't be two opposing keys held,
|
||||
// because we already checked for that above, so this is only necessary if there's
|
||||
// not already a secondary action
|
||||
if (! this.secondary_action) {
|
||||
for (let action of ['down', 'left', 'right', 'up']) {
|
||||
if (action !== this.primary_action &&
|
||||
input.has(action) && ! this.previous_input.has(action))
|
||||
{
|
||||
this.secondary_action = action;
|
||||
break;
|
||||
}
|
||||
}
|
||||
any_action = action;
|
||||
}
|
||||
}
|
||||
if (! chosen_action) {
|
||||
// No keys are new, so check whether we were previously
|
||||
// holding a key and are still doing it
|
||||
if (this.previous_action && input.has(this.previous_action)) {
|
||||
chosen_action = this.previous_action;
|
||||
}
|
||||
else {
|
||||
// No dice, so use an arbitrary action
|
||||
chosen_action = any_action;
|
||||
else {
|
||||
// Either we weren't holding any keys, or we let go of our primary action; either
|
||||
// way, act like we're starting from scratch and check keys in priority order
|
||||
this.primary_action = null;
|
||||
this.secondary_action = null;
|
||||
for (let action of ['down', 'left', 'right', 'up']) {
|
||||
if (! input.has(action))
|
||||
continue;
|
||||
|
||||
if (! this.primary_action) {
|
||||
this.primary_action = action;
|
||||
}
|
||||
else {
|
||||
// Note that because of the opposing keys check, there can never be more
|
||||
// than two keys held down here
|
||||
this.secondary_action = action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let player_move = chosen_action ? ACTION_DIRECTIONS[chosen_action] : null;
|
||||
this.previous_action = chosen_action;
|
||||
this.previous_input = current_input;
|
||||
this.previous_input = input;
|
||||
|
||||
this.level.advance_tic(player_move);
|
||||
this.level.advance_tic(
|
||||
this.primary_action ? ACTION_DIRECTIONS[this.primary_action] : null,
|
||||
this.secondary_action ? ACTION_DIRECTIONS[this.secondary_action] : null,
|
||||
);
|
||||
|
||||
if (this.level.state !== 'playing') {
|
||||
// We either won or lost!
|
||||
|
||||
@ -111,6 +111,7 @@ const TILE_TYPES = {
|
||||
},
|
||||
popdown_floor: {
|
||||
draw_layer: LAYER_TERRAIN,
|
||||
// FIXME should be on_approach
|
||||
on_arrive(me, level, other) {
|
||||
// FIXME could probably do this with state? or, eh
|
||||
level.transmute_tile(me, 'popdown_floor_visible');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user