Implement score flags and the stopwatches

This commit is contained in:
Eevee (Evelyn Woods) 2020-09-10 17:45:14 -06:00
parent 9b9536d586
commit 16bfe22593
6 changed files with 133 additions and 15 deletions

View File

@ -81,6 +81,16 @@
<div class="input"></div>
</div>
</div>
<!-- TODO debug panel?
- current tic
- list of actors, or currently pointed-to actor?
<div class="debug">
<button>« 4 tics</button>
<button>« 1 tic</button>
<button>1 tic »</button>
<button>4 tics »</button>
</div>
-->
</main>
<main id="editor" hidden>
<header>

View File

@ -138,8 +138,8 @@ const TILE_ENCODING = {
0x49: ['swivel_nw', 'swivel_floor'],
0x4a: ['swivel_ne', 'swivel_floor'],
0x4b: ['swivel_se', 'swivel_floor'],
// 0x4c: Time bonus : '#next'
// 0x4d: Stopwatch : '#next'
0x4c: ['stopwatch_bonus', '#next'],
0x4d: ['stopwatch_toggle', '#next'],
// 0x4e: Transmogrifier :
// 0x4f: Railroad track (Modifier required, see section below) :
// 0x50: Steel wall :
@ -163,7 +163,7 @@ const TILE_ENCODING = {
// 0x66: Mirror Melinda : '#direction', '#next'
// 0x68: Bowling ball : '#next'
// 0x69: Rover : '#direction', '#next'
// 0x6a: Time penalty : '#next'
0x6a: ['stopwatch_penalty', '#next'],
0x6b: ['#mod8?', ['floor_custom_green', 'floor_custom_pink', 'floor_custom_yellow', 'floor_custom_blue']],
0x6d: ['#thinwall/canopy', '#next'],
// 0x6f: Railroad sign : '#next'
@ -240,7 +240,7 @@ export function parse_level(buf) {
let level = new util.StoredLevel;
let full_view = new DataView(buf);
let next_section_start = 0;
let extra_hints;
let extra_hints = [];
let hint_tiles = [];
while (next_section_start < buf.byteLength) {
// Read section header and length

View File

@ -178,13 +178,16 @@ export class Level {
this.player = null;
this.actors = [];
this.chips_remaining = this.stored_level.chips_required;
this.bonus_points = 0;
// Time
if (this.stored_level.time_limit === 0) {
this.time_remaining = null;
}
else {
this.time_remaining = this.stored_level.time_limit;
this.time_remaining = this.stored_level.time_limit * 20;
}
this.bonus_points = 0;
this.timer_paused = false;
this.tic_counter = 0;
// 0 to 7, indicating the first tic that teeth can move on.
// 0 is equivalent to even step; 4 is equivalent to odd step.
@ -551,10 +554,9 @@ export class Level {
// Advance the clock
let tic_counter = this.tic_counter;
let time_remaining = this.time_remaining;
this.tic_counter++;
if (this.time_remaining !== null && this.tic_counter % 20 === 0) {
// 20 tics means one second! Tic that time down
this.tic_counter += 1;
if (this.time_remaining !== null && ! this.timer_paused) {
let time_remaining = this.time_remaining;
this.pending_undo.push(() => {
this.tic_counter = tic_counter;
this.time_remaining = time_remaining;
@ -834,6 +836,36 @@ export class Level {
}
}
adjust_bonus(add, mult = 1) {
let current = this.bonus_points;
this.pending_undo.push(() => this.bonus_points = current);
this.bonus_points = Math.ceil(this.bonus_points * mult) + add;
}
pause_timer() {
if (this.time_remaining === null)
return;
this.pending_undo.push(() => this.timer_paused = ! this.timer_paused);
this.timer_paused = ! this.timer_paused;
}
adjust_timer(dt) {
let current = this.time_remaining;
this.pending_undo.push(() => this.time_remaining = current);
// Untimed levels become timed levels with 0 seconds remaining
this.time_remaining = Math.max(0, (this.time_remaining ?? 0) + dt * 20);
if (this.time_remaining <= 0) {
if (this.timer_paused) {
this.time_remaining = 1;
}
else {
this.fail("Time's up!");
}
}
}
fail(message) {
this.pending_undo.push(() => {
this.state = 'playing';

View File

@ -508,7 +508,7 @@ class Player extends PrimaryView {
this.time_el.textContent = '---';
}
else {
this.time_el.textContent = this.level.time_remaining;
this.time_el.textContent = Math.ceil(this.level.time_remaining / 20);
}
this.bonus_el.textContent = this.level.bonus_points;
this.message_el.textContent = this.level.hint_shown ?? "";
@ -557,7 +557,7 @@ class Player extends PrimaryView {
else {
this.bummer_el.textContent = "";
let base = (this.conductor.level_index + 1) * 500;
let time = (this.level.time_remaining || 0) * 10;
let time = Math.ceil((this.level.time_remaining ?? 0) / 20) * 10;
this.bummer_el.append(
mk('p', "go bit buster!"),
mk('dl.score-chart',

View File

@ -188,7 +188,7 @@ export const CC2_TILESET_LAYOUT = {
swivel_se: [12, 11],
swivel_floor: [13, 11],
// TODO some kinda four-edges thing again
// TODO stopwatch with a - sign??
stopwatch_penalty: [15, 11],
paramecium: {
north: [[0, 12], [1, 12], [2, 12]],
east: [[3, 12], [4, 12], [5, 12]],
@ -205,8 +205,8 @@ export const CC2_TILESET_LAYOUT = {
walker: [0, 13],
// TODO walker animations span multiple tiles, rgh
helmet: [0, 14],
// 14: stopwatch
// 15: stopwatch with +
stopwatch_toggle: [14, 14],
stopwatch_bonus: [15, 14],
blob: [0, 15],
// TODO blob animations also span multiple tiles

View File

@ -392,6 +392,9 @@ const TILE_TYPES = {
}
}
}
if (other.type.is_player) {
level.adjust_bonus(0, 0.5);
}
},
},
thief_keys: {
@ -406,6 +409,9 @@ const TILE_TYPES = {
}
}
}
if (other.type.is_player) {
level.adjust_bonus(0, 0.5);
}
},
},
forbidden: {
@ -595,6 +601,39 @@ const TILE_TYPES = {
}
},
},
// Time alternation
stopwatch_bonus: {
draw_layer: LAYER_ITEM,
blocks_monsters: true,
blocks_blocks: true,
on_arrive(me, level, other) {
if (other.type.is_player) {
level.remove_tile(me);
level.adjust_timer(+10);
}
},
},
stopwatch_penalty: {
draw_layer: LAYER_ITEM,
blocks_monsters: true,
blocks_blocks: true,
on_arrive(me, level, other) {
if (other.type.is_player) {
level.remove_tile(me);
level.adjust_timer(-10);
}
},
},
stopwatch_toggle: {
draw_layer: LAYER_ITEM,
blocks_monsters: true,
blocks_blocks: true,
on_arrive(me, level, other) {
if (other.type.is_player) {
level.pause_timer();
}
},
},
// Critters
bug: {
@ -683,6 +722,7 @@ const TILE_TYPES = {
},
// Keys
// Note that red and blue keys do NOT block monsters, but yellow and green DO
key_red: {
draw_layer: LAYER_ITEM,
is_item: true,
@ -697,11 +737,15 @@ const TILE_TYPES = {
draw_layer: LAYER_ITEM,
is_item: true,
is_key: true,
blocks_monsters: true,
blocks_blocks: true,
},
key_green: {
draw_layer: LAYER_ITEM,
is_item: true,
is_key: true,
blocks_monsters: true,
blocks_blocks: true,
},
// Tools
// TODO note: ms allows blocks to pass over tools
@ -794,15 +838,47 @@ const TILE_TYPES = {
},
score_10: {
draw_layer: LAYER_ITEM,
blocks_monsters: true,
blocks_blocks: true,
on_arrive(me, level, other) {
if (other.type.is_player) {
level.adjust_bonus(10);
}
level.remove_tile(me);
},
},
score_100: {
draw_layer: LAYER_ITEM,
blocks_monsters: true,
blocks_blocks: true,
on_arrive(me, level, other) {
if (other.type.is_player) {
level.adjust_bonus(100);
}
level.remove_tile(me);
},
},
score_1000: {
draw_layer: LAYER_ITEM,
blocks_monsters: true,
blocks_blocks: true,
on_arrive(me, level, other) {
if (other.type.is_player) {
level.adjust_bonus(1000);
}
level.remove_tile(me);
},
},
score_2x: {
draw_layer: LAYER_ITEM,
blocks_monsters: true,
blocks_blocks: true,
on_arrive(me, level, other) {
if (other.type.is_player) {
level.adjust_bonus(0, 2);
}
level.remove_tile(me);
},
},
hint: {