Implement score flags and the stopwatches
This commit is contained in:
parent
9b9536d586
commit
16bfe22593
10
index.html
10
index.html
@ -81,6 +81,16 @@
|
|||||||
<div class="input"></div>
|
<div class="input"></div>
|
||||||
</div>
|
</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>
|
||||||
<main id="editor" hidden>
|
<main id="editor" hidden>
|
||||||
<header>
|
<header>
|
||||||
|
|||||||
@ -138,8 +138,8 @@ const TILE_ENCODING = {
|
|||||||
0x49: ['swivel_nw', 'swivel_floor'],
|
0x49: ['swivel_nw', 'swivel_floor'],
|
||||||
0x4a: ['swivel_ne', 'swivel_floor'],
|
0x4a: ['swivel_ne', 'swivel_floor'],
|
||||||
0x4b: ['swivel_se', 'swivel_floor'],
|
0x4b: ['swivel_se', 'swivel_floor'],
|
||||||
// 0x4c: Time bonus : '#next'
|
0x4c: ['stopwatch_bonus', '#next'],
|
||||||
// 0x4d: Stopwatch : '#next'
|
0x4d: ['stopwatch_toggle', '#next'],
|
||||||
// 0x4e: Transmogrifier :
|
// 0x4e: Transmogrifier :
|
||||||
// 0x4f: Railroad track (Modifier required, see section below) :
|
// 0x4f: Railroad track (Modifier required, see section below) :
|
||||||
// 0x50: Steel wall :
|
// 0x50: Steel wall :
|
||||||
@ -163,7 +163,7 @@ const TILE_ENCODING = {
|
|||||||
// 0x66: Mirror Melinda : '#direction', '#next'
|
// 0x66: Mirror Melinda : '#direction', '#next'
|
||||||
// 0x68: Bowling ball : '#next'
|
// 0x68: Bowling ball : '#next'
|
||||||
// 0x69: Rover : '#direction', '#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']],
|
0x6b: ['#mod8?', ['floor_custom_green', 'floor_custom_pink', 'floor_custom_yellow', 'floor_custom_blue']],
|
||||||
0x6d: ['#thinwall/canopy', '#next'],
|
0x6d: ['#thinwall/canopy', '#next'],
|
||||||
// 0x6f: Railroad sign : '#next'
|
// 0x6f: Railroad sign : '#next'
|
||||||
@ -240,7 +240,7 @@ export function parse_level(buf) {
|
|||||||
let level = new util.StoredLevel;
|
let level = new util.StoredLevel;
|
||||||
let full_view = new DataView(buf);
|
let full_view = new DataView(buf);
|
||||||
let next_section_start = 0;
|
let next_section_start = 0;
|
||||||
let extra_hints;
|
let extra_hints = [];
|
||||||
let hint_tiles = [];
|
let hint_tiles = [];
|
||||||
while (next_section_start < buf.byteLength) {
|
while (next_section_start < buf.byteLength) {
|
||||||
// Read section header and length
|
// Read section header and length
|
||||||
|
|||||||
44
js/game.js
44
js/game.js
@ -178,13 +178,16 @@ export class Level {
|
|||||||
this.player = null;
|
this.player = null;
|
||||||
this.actors = [];
|
this.actors = [];
|
||||||
this.chips_remaining = this.stored_level.chips_required;
|
this.chips_remaining = this.stored_level.chips_required;
|
||||||
|
this.bonus_points = 0;
|
||||||
|
|
||||||
|
// Time
|
||||||
if (this.stored_level.time_limit === 0) {
|
if (this.stored_level.time_limit === 0) {
|
||||||
this.time_remaining = null;
|
this.time_remaining = null;
|
||||||
}
|
}
|
||||||
else {
|
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;
|
this.tic_counter = 0;
|
||||||
// 0 to 7, indicating the first tic that teeth can move on.
|
// 0 to 7, indicating the first tic that teeth can move on.
|
||||||
// 0 is equivalent to even step; 4 is equivalent to odd step.
|
// 0 is equivalent to even step; 4 is equivalent to odd step.
|
||||||
@ -551,10 +554,9 @@ export class Level {
|
|||||||
|
|
||||||
// Advance the clock
|
// Advance the clock
|
||||||
let tic_counter = this.tic_counter;
|
let tic_counter = this.tic_counter;
|
||||||
let time_remaining = this.time_remaining;
|
this.tic_counter += 1;
|
||||||
this.tic_counter++;
|
if (this.time_remaining !== null && ! this.timer_paused) {
|
||||||
if (this.time_remaining !== null && this.tic_counter % 20 === 0) {
|
let time_remaining = this.time_remaining;
|
||||||
// 20 tics means one second! Tic that time down
|
|
||||||
this.pending_undo.push(() => {
|
this.pending_undo.push(() => {
|
||||||
this.tic_counter = tic_counter;
|
this.tic_counter = tic_counter;
|
||||||
this.time_remaining = time_remaining;
|
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) {
|
fail(message) {
|
||||||
this.pending_undo.push(() => {
|
this.pending_undo.push(() => {
|
||||||
this.state = 'playing';
|
this.state = 'playing';
|
||||||
|
|||||||
@ -508,7 +508,7 @@ class Player extends PrimaryView {
|
|||||||
this.time_el.textContent = '---';
|
this.time_el.textContent = '---';
|
||||||
}
|
}
|
||||||
else {
|
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.bonus_el.textContent = this.level.bonus_points;
|
||||||
this.message_el.textContent = this.level.hint_shown ?? "";
|
this.message_el.textContent = this.level.hint_shown ?? "";
|
||||||
@ -557,7 +557,7 @@ class Player extends PrimaryView {
|
|||||||
else {
|
else {
|
||||||
this.bummer_el.textContent = "";
|
this.bummer_el.textContent = "";
|
||||||
let base = (this.conductor.level_index + 1) * 500;
|
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(
|
this.bummer_el.append(
|
||||||
mk('p', "go bit buster!"),
|
mk('p', "go bit buster!"),
|
||||||
mk('dl.score-chart',
|
mk('dl.score-chart',
|
||||||
|
|||||||
@ -188,7 +188,7 @@ export const CC2_TILESET_LAYOUT = {
|
|||||||
swivel_se: [12, 11],
|
swivel_se: [12, 11],
|
||||||
swivel_floor: [13, 11],
|
swivel_floor: [13, 11],
|
||||||
// TODO some kinda four-edges thing again
|
// TODO some kinda four-edges thing again
|
||||||
// TODO stopwatch with a - sign??
|
stopwatch_penalty: [15, 11],
|
||||||
paramecium: {
|
paramecium: {
|
||||||
north: [[0, 12], [1, 12], [2, 12]],
|
north: [[0, 12], [1, 12], [2, 12]],
|
||||||
east: [[3, 12], [4, 12], [5, 12]],
|
east: [[3, 12], [4, 12], [5, 12]],
|
||||||
@ -205,8 +205,8 @@ export const CC2_TILESET_LAYOUT = {
|
|||||||
walker: [0, 13],
|
walker: [0, 13],
|
||||||
// TODO walker animations span multiple tiles, rgh
|
// TODO walker animations span multiple tiles, rgh
|
||||||
helmet: [0, 14],
|
helmet: [0, 14],
|
||||||
// 14: stopwatch
|
stopwatch_toggle: [14, 14],
|
||||||
// 15: stopwatch with +
|
stopwatch_bonus: [15, 14],
|
||||||
|
|
||||||
blob: [0, 15],
|
blob: [0, 15],
|
||||||
// TODO blob animations also span multiple tiles
|
// TODO blob animations also span multiple tiles
|
||||||
|
|||||||
@ -392,6 +392,9 @@ const TILE_TYPES = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (other.type.is_player) {
|
||||||
|
level.adjust_bonus(0, 0.5);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
thief_keys: {
|
thief_keys: {
|
||||||
@ -406,6 +409,9 @@ const TILE_TYPES = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (other.type.is_player) {
|
||||||
|
level.adjust_bonus(0, 0.5);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
forbidden: {
|
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
|
// Critters
|
||||||
bug: {
|
bug: {
|
||||||
@ -683,6 +722,7 @@ const TILE_TYPES = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Keys
|
// Keys
|
||||||
|
// Note that red and blue keys do NOT block monsters, but yellow and green DO
|
||||||
key_red: {
|
key_red: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_item: true,
|
is_item: true,
|
||||||
@ -697,11 +737,15 @@ const TILE_TYPES = {
|
|||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_item: true,
|
is_item: true,
|
||||||
is_key: true,
|
is_key: true,
|
||||||
|
blocks_monsters: true,
|
||||||
|
blocks_blocks: true,
|
||||||
},
|
},
|
||||||
key_green: {
|
key_green: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_item: true,
|
is_item: true,
|
||||||
is_key: true,
|
is_key: true,
|
||||||
|
blocks_monsters: true,
|
||||||
|
blocks_blocks: true,
|
||||||
},
|
},
|
||||||
// Tools
|
// Tools
|
||||||
// TODO note: ms allows blocks to pass over tools
|
// TODO note: ms allows blocks to pass over tools
|
||||||
@ -794,15 +838,47 @@ const TILE_TYPES = {
|
|||||||
},
|
},
|
||||||
score_10: {
|
score_10: {
|
||||||
draw_layer: LAYER_ITEM,
|
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: {
|
score_100: {
|
||||||
draw_layer: LAYER_ITEM,
|
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: {
|
score_1000: {
|
||||||
draw_layer: LAYER_ITEM,
|
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: {
|
score_2x: {
|
||||||
draw_layer: LAYER_ITEM,
|
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: {
|
hint: {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user