Add a delay before restarting a failed level by tapping the viewport

This commit is contained in:
Eevee (Evelyn Woods) 2020-12-11 14:39:14 -07:00
parent 75e981335f
commit b8dd0ae41e
2 changed files with 34 additions and 3 deletions

View File

@ -439,6 +439,7 @@ class Player extends PrimaryView {
key_target.addEventListener('keydown', ev => { key_target.addEventListener('keydown', ev => {
if (! this.active) if (! this.active)
return; return;
this.using_touch = false;
if (ev.key === 'p' || ev.key === 'Pause') { if (ev.key === 'p' || ev.key === 'Pause') {
this.toggle_pause(); this.toggle_pause();
@ -506,10 +507,12 @@ class Player extends PrimaryView {
}); });
// Similarly, grab touch events and translate them to directions // Similarly, grab touch events and translate them to directions
this.current_touches = {}; // ident => action this.current_touches = {}; // ident => action
this.touch_restart_delay = new util.DelayTimer;
let touch_target = this.root.querySelector('.-main-area'); let touch_target = this.root.querySelector('.-main-area');
let collect_touches = ev => { let collect_touches = ev => {
ev.stopPropagation(); ev.stopPropagation();
ev.preventDefault(); ev.preventDefault();
this.using_touch = true;
// If state is anything other than playing/waiting, probably switch to playing, similar // If state is anything other than playing/waiting, probably switch to playing, similar
// to pressing spacebar // to pressing spacebar
@ -519,10 +522,13 @@ class Player extends PrimaryView {
return; return;
} }
else if (this.state === 'stopped') { else if (this.state === 'stopped') {
if (this.level.state === 'success') { if (this.touch_restart_delay.active) {
// If it's only been a very short time since the level ended, ignore taps
// here, so you don't accidentally mash restart and lose the chance to undo
}
else if (this.level.state === 'success') {
// Advance to the next level // Advance to the next level
// TODO game ending? // TODO game ending?
// TODO this immediately begins it too, not sure why
this.conductor.change_level(this.conductor.level_index + 1); this.conductor.change_level(this.conductor.level_index + 1);
} }
else { else {
@ -1249,6 +1255,9 @@ class Player extends PrimaryView {
} }
} }
else if (this.state === 'stopped') { else if (this.state === 'stopped') {
// Set a timer before tapping the overlay will restart/advance
this.touch_restart_delay.set(2000);
if (this.level.state === 'failure') { if (this.level.state === 'failure') {
overlay_reason = 'failure'; overlay_reason = 'failure';
overlay_top = "whoops"; overlay_top = "whoops";
@ -1256,7 +1265,7 @@ class Player extends PrimaryView {
overlay_bottom = random_choice(obits); overlay_bottom = random_choice(obits);
if (this.using_touch) { if (this.using_touch) {
// TODO touch gesture to rewind? // TODO touch gesture to rewind?
overlay_keyhint = "tap to try again, or tap undo/rewind above"; overlay_keyhint = "tap to try again, or use undo/rewind above";
} }
else { else {
overlay_keyhint = "press space to try again, or Z to rewind"; overlay_keyhint = "press space to try again, or Z to rewind";

View File

@ -162,6 +162,28 @@ export function bytestring_to_buffer(bytestring) {
return Uint8Array.from(bytestring, c => c.charCodeAt(0)).buffer; return Uint8Array.from(bytestring, c => c.charCodeAt(0)).buffer;
} }
export class DelayTimer {
constructor() {
this.active = false;
this._handle = null;
this._bound_alarm = this._alarm.bind(this);
}
set(duration) {
if (this._handle) {
window.clearTimeout(this._handle);
}
this.active = true;
this._handle = window.setTimeout(this._bound_alarm, duration);
}
_alarm() {
this._handle = null;
this.active = false;
}
}
// Cast a line through a grid and yield every cell it touches // Cast a line through a grid and yield every cell it touches
export function* walk_grid(x0, y0, x1, y1, min_a, min_b, max_a, max_b) { export function* walk_grid(x0, y0, x1, y1, min_a, min_b, max_a, max_b) {
// TODO if the ray starts outside the grid (extremely unlikely), we should // TODO if the ray starts outside the grid (extremely unlikely), we should