This commit is contained in:
Timothy Stiles 2020-10-14 22:23:13 +11:00
parent e9d542f438
commit be5cc7f97f
3 changed files with 127 additions and 127 deletions

View File

@ -329,12 +329,12 @@ export class Level {
} }
} }
player_awaiting_input() { player_awaiting_input() {
return this.player.movement_cooldown === 0 && (this.player.slide_mode === null || (this.player.slide_mode === 'force' && this.player.last_move_was_force)) return this.player.movement_cooldown === 0 && (this.player.slide_mode === null || (this.player.slide_mode === 'force' && this.player.last_move_was_force))
} }
// Move the game state forwards by one tic // Move the game state forwards by one tic
// split into two parts for turn-based mode: first part is the consequences of the previous tick, second part depends on the player's input // split into two parts for turn-based mode: first part is the consequences of the previous tick, second part depends on the player's input
advance_tic(p1_primary_direction, p1_secondary_direction, pass) { advance_tic(p1_primary_direction, p1_secondary_direction, pass) {
if (this.state !== 'playing') { if (this.state !== 'playing') {
console.warn(`Level.advance_tic() called when state is ${this.state}`); console.warn(`Level.advance_tic() called when state is ${this.state}`);
@ -342,18 +342,18 @@ export class Level {
} }
try { try {
if (pass == 1) if (pass == 1)
{ {
this._advance_tic_part1(p1_primary_direction, p1_secondary_direction); this._advance_tic_part1(p1_primary_direction, p1_secondary_direction);
} }
else if (pass == 2) else if (pass == 2)
{ {
this._advance_tic_part2(p1_primary_direction, p1_secondary_direction); this._advance_tic_part2(p1_primary_direction, p1_secondary_direction);
} }
else else
{ {
console.warn(`What pass is this?`); console.warn(`What pass is this?`);
} }
} }
catch (e) { catch (e) {
if (e instanceof GameEnded) { if (e instanceof GameEnded) {
@ -388,68 +388,68 @@ export class Level {
// arrival as its own mini pass, for one reason: if the player dies (which will end the game // arrival as its own mini pass, for one reason: if the player dies (which will end the game
// immediately), we still want every time's animation to finish, or it'll look like some // immediately), we still want every time's animation to finish, or it'll look like some
// objects move backwards when the death screen appears! // objects move backwards when the death screen appears!
let cell_steppers = []; let cell_steppers = [];
for (let actor of this.actors) { for (let actor of this.actors) {
// Actors with no cell were destroyed // Actors with no cell were destroyed
if (! actor.cell) if (! actor.cell)
continue; continue;
// Clear any old decisions ASAP. Note that this prop is only used internally within a // Clear any old decisions ASAP. Note that this prop is only used internally within a
// single tic, so it doesn't need to be undoable // single tic, so it doesn't need to be undoable
actor.decision = null; actor.decision = null;
// Decrement the cooldown here, but don't check it quite yet, // Decrement the cooldown here, but don't check it quite yet,
// because stepping on cells in the next block might reset it // because stepping on cells in the next block might reset it
if (actor.movement_cooldown > 0) { if (actor.movement_cooldown > 0) {
this._set_prop(actor, 'movement_cooldown', actor.movement_cooldown - 1); this._set_prop(actor, 'movement_cooldown', actor.movement_cooldown - 1);
} }
if (actor.animation_speed) { if (actor.animation_speed) {
// Deal with movement animation // Deal with movement animation
this._set_prop(actor, 'animation_progress', actor.animation_progress + 1); this._set_prop(actor, 'animation_progress', actor.animation_progress + 1);
if (actor.animation_progress >= actor.animation_speed) { if (actor.animation_progress >= actor.animation_speed) {
if (actor.type.ttl) { if (actor.type.ttl) {
// This is purely an animation so it disappears once it's played // This is purely an animation so it disappears once it's played
this.remove_tile(actor); this.remove_tile(actor);
continue; continue;
} }
this._set_prop(actor, 'previous_cell', null); this._set_prop(actor, 'previous_cell', null);
this._set_prop(actor, 'animation_progress', null); this._set_prop(actor, 'animation_progress', null);
this._set_prop(actor, 'animation_speed', null); this._set_prop(actor, 'animation_speed', null);
if (! this.compat.tiles_react_instantly) { if (! this.compat.tiles_react_instantly) {
// We need to track the actor AND the cell explicitly, because it's possible // We need to track the actor AND the cell explicitly, because it's possible
// that one actor's step will cause another actor to start another move, and // that one actor's step will cause another actor to start another move, and
// then they'd end up stepping on the new cell they're moving to instead of // then they'd end up stepping on the new cell they're moving to instead of
// the one they just landed on! // the one they just landed on!
cell_steppers.push([actor, actor.cell]); cell_steppers.push([actor, actor.cell]);
} }
} }
} }
} }
for (let [actor, cell] of cell_steppers) { for (let [actor, cell] of cell_steppers) {
this.step_on_cell(actor, cell); this.step_on_cell(actor, cell);
} }
// Only reset the player's is_pushing between movement, so it lasts for the whole push // Only reset the player's is_pushing between movement, so it lasts for the whole push
if (this.player.movement_cooldown <= 0) { if (this.player.movement_cooldown <= 0) {
this.player.is_pushing = false; this.player.is_pushing = false;
} }
// Second pass: actors decide their upcoming movement simultaneously // Second pass: actors decide their upcoming movement simultaneously
// (we'll do the player's decision in part 2!) // (we'll do the player's decision in part 2!)
for (let actor of this.actors) { for (let actor of this.actors) {
if (actor != this.player) if (actor != this.player)
{ {
this.actor_decision(actor, p1_primary_direction); this.actor_decision(actor, p1_primary_direction);
} }
} }
} }
_advance_tic_part2(p1_primary_direction, p1_secondary_direction) { _advance_tic_part2(p1_primary_direction, p1_secondary_direction) {
//player now makes a decision based on input //player now makes a decision based on input
this.actor_decision(this.player, p1_primary_direction); this.actor_decision(this.player, p1_primary_direction);
// Third pass: everyone actually moves // Third pass: everyone actually moves
for (let actor of this.actors) { for (let actor of this.actors) {
if (! actor.cell) if (! actor.cell)

View File

@ -428,7 +428,7 @@ class Player extends PrimaryView {
while (this.level.undo_stack.length > 0 && while (this.level.undo_stack.length > 0 &&
! (moved && this.level.player.slide_mode === null)) ! (moved && this.level.player.slide_mode === null))
{ {
this.undo(); this.undo();
if (player_cell !== this.level.player.cell) { if (player_cell !== this.level.player.cell) {
moved = true; moved = true;
} }
@ -509,7 +509,7 @@ class Player extends PrimaryView {
this.previous_input = new Set; // actions that were held last tic this.previous_input = new Set; // actions that were held last tic
this.previous_action = null; // last direction we were moving, if any this.previous_action = null; // last direction we were moving, if any
this.current_keys = new Set; // keys that are currently held this.current_keys = new Set; // keys that are currently held
this.current_keys_new = new Set; //for keys that have only been held a frame this.current_keys_new = new Set; //for keys that have only been held a frame
// TODO this could all probably be more rigorous but it's fine for now // TODO this could all probably be more rigorous but it's fine for now
key_target.addEventListener('keydown', ev => { key_target.addEventListener('keydown', ev => {
if (ev.key === 'p' || ev.key === 'Pause') { if (ev.key === 'p' || ev.key === 'Pause') {
@ -550,7 +550,7 @@ class Player extends PrimaryView {
if (this.key_mapping[ev.key]) { if (this.key_mapping[ev.key]) {
this.current_keys.add(ev.key); this.current_keys.add(ev.key);
this.current_keys_new.add(ev.key); this.current_keys_new.add(ev.key);
ev.stopPropagation(); ev.stopPropagation();
ev.preventDefault(); ev.preventDefault();
@ -656,7 +656,7 @@ class Player extends PrimaryView {
_clear_state() { _clear_state() {
this.set_state('waiting'); this.set_state('waiting');
this.waiting_for_input = false; this.waiting_for_input = false;
this.tic_offset = 0; this.tic_offset = 0;
this.last_advance = 0; this.last_advance = 0;
this.demo_faucet = null; this.demo_faucet = null;
@ -701,15 +701,15 @@ class Player extends PrimaryView {
for (let key of this.current_keys) { for (let key of this.current_keys) {
input.add(this.key_mapping[key]); input.add(this.key_mapping[key]);
} }
for (let key of this.current_keys_new) { for (let key of this.current_keys_new) {
input.add(this.key_mapping[key]); input.add(this.key_mapping[key]);
} }
this.current_keys_new = new Set; this.current_keys_new = new Set;
return input; return input;
} }
} }
waiting_for_input = false; waiting_for_input = false;
advance_by(tics) { advance_by(tics) {
for (let i = 0; i < tics; i++) { for (let i = 0; i < tics; i++) {
@ -773,43 +773,43 @@ class Player extends PrimaryView {
this.previous_input = input; this.previous_input = input;
this.sfx_player.advance_tic(); this.sfx_player.advance_tic();
var primary_dir = this.primary_action ? ACTION_DIRECTIONS[this.primary_action] : null; var primary_dir = this.primary_action ? ACTION_DIRECTIONS[this.primary_action] : null;
var secondary_dir = this.secondary_action ? ACTION_DIRECTIONS[this.secondary_action] : null; var secondary_dir = this.secondary_action ? ACTION_DIRECTIONS[this.secondary_action] : null;
//turn based logic //turn based logic
//first, handle a part 2 we just got input for //first, handle a part 2 we just got input for
if (this.waiting_for_input) if (this.waiting_for_input)
{ {
if (!this.turn_based || primary_dir != null || input.has('wait')) if (!this.turn_based || primary_dir != null || input.has('wait'))
{ {
this.waiting_for_input = false; this.waiting_for_input = false;
this.level.advance_tic( this.level.advance_tic(
primary_dir, primary_dir,
secondary_dir, secondary_dir,
2); 2);
} }
} }
else //TODO: or `if (!this.waiting_for_input)` to be snappier else //TODO: or `if (!this.waiting_for_input)` to be snappier
{ {
this.level.advance_tic( this.level.advance_tic(
primary_dir, primary_dir,
secondary_dir, secondary_dir,
1); 1);
//then if we should wait for input, the player needs input and we don't have input, we set waiting_for_input, else we run part 2 //then if we should wait for input, the player needs input and we don't have input, we set waiting_for_input, else we run part 2
if (this.turn_based && this.level.player_awaiting_input() && !(primary_dir != null || input.has('wait'))) if (this.turn_based && this.level.player_awaiting_input() && !(primary_dir != null || input.has('wait')))
{ {
this.waiting_for_input = true; this.waiting_for_input = true;
} }
else else
{ {
this.level.advance_tic( this.level.advance_tic(
primary_dir, primary_dir,
secondary_dir, secondary_dir,
2); 2);
} }
} }
if (this.level.state !== 'playing') { if (this.level.state !== 'playing') {
// We either won or lost! // We either won or lost!
@ -843,7 +843,7 @@ class Player extends PrimaryView {
} }
else { else {
// Rewind by undoing one tic every tic // Rewind by undoing one tic every tic
this.undo(); this.undo();
this.update_ui(); this.update_ui();
} }
} }
@ -862,11 +862,11 @@ class Player extends PrimaryView {
this._advance_handle = window.setTimeout(this._advance_bound, dt); this._advance_handle = window.setTimeout(this._advance_bound, dt);
} }
undo() { undo() {
//if we were waiting for input and undo, well, now we're not //if we were waiting for input and undo, well, now we're not
this.waiting_for_input = false; this.waiting_for_input = false;
this.level.undo(); this.level.undo();
} }
// Redraws every frame, unless the game isn't running // Redraws every frame, unless the game isn't running
redraw() { redraw() {
@ -901,7 +901,7 @@ class Player extends PrimaryView {
// Actually redraw. Used to force drawing outside of normal play // Actually redraw. Used to force drawing outside of normal play
_redraw() { _redraw() {
this.renderer.waiting_for_input = this.waiting_for_input; this.renderer.waiting_for_input = this.waiting_for_input;
this.renderer.draw(this.tic_offset); this.renderer.draw(this.tic_offset);
} }

View File

@ -51,8 +51,8 @@ export class CanvasRenderer {
sx * tw, sy * th, w * tw, h * th, sx * tw, sy * th, w * tw, h * th,
dx * tw, dy * th, w * tw, h * th); dx * tw, dy * th, w * tw, h * th);
} }
waiting_for_input = false; waiting_for_input = false;
draw(tic_offset = 0) { draw(tic_offset = 0) {
if (! this.level) { if (! this.level) {