Standardize visual state, and use it instead of transmuting a dead player
This commit is contained in:
parent
171c52acb5
commit
e0bfb0aadf
@ -934,13 +934,15 @@ export class Level {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fail(message) {
|
fail(reason) {
|
||||||
this.pending_undo.push(() => {
|
this.pending_undo.push(() => {
|
||||||
this.state = 'playing';
|
this.state = 'playing';
|
||||||
this.fail_reason = null;
|
this.fail_reason = null;
|
||||||
|
this.player.fail_reason = null;
|
||||||
});
|
});
|
||||||
this.state = 'failure';
|
this.state = 'failure';
|
||||||
this.fail_reason = message;
|
this.fail_reason = reason;
|
||||||
|
this.player.fail_reason = reason;
|
||||||
throw new GameEnded;
|
throw new GameEnded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { DIRECTIONS } from './defs.js';
|
import { DIRECTIONS } from './defs.js';
|
||||||
|
import TILE_TYPES from './tiletypes.js';
|
||||||
|
|
||||||
// TODO really need to specify this format more concretely, whoof
|
// TODO really need to specify this format more concretely, whoof
|
||||||
// XXX special kinds of drawing i know this has for a fact:
|
// XXX special kinds of drawing i know this has for a fact:
|
||||||
@ -268,19 +269,24 @@ export const CC2_TILESET_LAYOUT = {
|
|||||||
// switch
|
// switch
|
||||||
thief_keys: [15, 21],
|
thief_keys: [15, 21],
|
||||||
|
|
||||||
// TODO moving + swimming + pushing animations
|
|
||||||
player: {
|
player: {
|
||||||
|
normal: {
|
||||||
|
north: [0, 22],
|
||||||
|
south: [0, 23],
|
||||||
|
west: [8, 23],
|
||||||
|
east: [8, 22],
|
||||||
|
},
|
||||||
moving: {
|
moving: {
|
||||||
north: [[0, 22], [1, 22], [2, 22], [3, 22], [4, 22], [5, 22], [6, 22], [7, 22]],
|
north: [[0, 22], [1, 22], [2, 22], [3, 22], [4, 22], [5, 22], [6, 22], [7, 22]],
|
||||||
south: [[0, 23], [1, 23], [2, 23], [3, 23], [4, 23], [5, 23], [6, 23], [7, 23]],
|
south: [[0, 23], [1, 23], [2, 23], [3, 23], [4, 23], [5, 23], [6, 23], [7, 23]],
|
||||||
west: [[8, 23], [9, 23], [10, 23], [11, 23], [12, 23], [13, 23], [14, 23], [15, 23]],
|
west: [[8, 23], [9, 23], [10, 23], [11, 23], [12, 23], [13, 23], [14, 23], [15, 23]],
|
||||||
east: [[8, 22], [9, 22], [10, 22], [11, 22], [12, 22], [13, 22], [14, 22], [15, 22]],
|
east: [[8, 22], [9, 22], [10, 22], [11, 22], [12, 22], [13, 22], [14, 22], [15, 22]],
|
||||||
},
|
},
|
||||||
standing: {
|
pushing: {
|
||||||
north: [0, 22],
|
north: [8, 24],
|
||||||
south: [0, 23],
|
east: [9, 24],
|
||||||
west: [8, 23],
|
south: [10, 24],
|
||||||
east: [8, 22],
|
west: [11, 24],
|
||||||
},
|
},
|
||||||
swimming: {
|
swimming: {
|
||||||
north: [[0, 24], [1, 24]],
|
north: [[0, 24], [1, 24]],
|
||||||
@ -288,6 +294,11 @@ export const CC2_TILESET_LAYOUT = {
|
|||||||
south: [[4, 24], [5, 24]],
|
south: [[4, 24], [5, 24]],
|
||||||
west: [[6, 24], [7, 24]],
|
west: [[6, 24], [7, 24]],
|
||||||
},
|
},
|
||||||
|
// These are frames from the splash/explosion animations
|
||||||
|
drowned: [5, 5],
|
||||||
|
burned: [1, 5],
|
||||||
|
exploded: [1, 5],
|
||||||
|
failed: [1, 5],
|
||||||
},
|
},
|
||||||
bogus_player_win: {
|
bogus_player_win: {
|
||||||
overlay: [0, 23],
|
overlay: [0, 23],
|
||||||
@ -316,7 +327,7 @@ export const CC2_TILESET_LAYOUT = {
|
|||||||
west: [[8, 28], [9, 28], [10, 28], [11, 28], [12, 28], [13, 28], [14, 28], [15, 28]],
|
west: [[8, 28], [9, 28], [10, 28], [11, 28], [12, 28], [13, 28], [14, 28], [15, 28]],
|
||||||
east: [[8, 27], [9, 27], [10, 27], [11, 27], [12, 27], [13, 27], [14, 27], [15, 27]],
|
east: [[8, 27], [9, 27], [10, 27], [11, 27], [12, 27], [13, 27], [14, 27], [15, 27]],
|
||||||
},
|
},
|
||||||
standing: {
|
normal: {
|
||||||
north: [0, 27],
|
north: [0, 27],
|
||||||
south: [0, 28],
|
south: [0, 28],
|
||||||
west: [8, 28],
|
west: [8, 28],
|
||||||
@ -409,7 +420,6 @@ export const TILE_WORLD_TILESET_LAYOUT = {
|
|||||||
explosion_other: [3, 7], // TODO ???
|
explosion_other: [3, 7], // TODO ???
|
||||||
// 3, 8 unused
|
// 3, 8 unused
|
||||||
bogus_player_win: [3, 9], // TODO 10 and 11 too? does this animate?
|
bogus_player_win: [3, 9], // TODO 10 and 11 too? does this animate?
|
||||||
// TODO player swimming is 3, 12-15
|
|
||||||
bogus_player_swimming: {
|
bogus_player_swimming: {
|
||||||
north: [3, 12],
|
north: [3, 12],
|
||||||
west: [3, 13],
|
west: [3, 13],
|
||||||
@ -482,10 +492,23 @@ export const TILE_WORLD_TILESET_LAYOUT = {
|
|||||||
cleats: [6, 10],
|
cleats: [6, 10],
|
||||||
suction_boots: [6, 11],
|
suction_boots: [6, 11],
|
||||||
player: {
|
player: {
|
||||||
north: [6, 12],
|
normal: {
|
||||||
south: [6, 14],
|
north: [6, 12],
|
||||||
west: [6, 13],
|
south: [6, 14],
|
||||||
east: [6, 15],
|
west: [6, 13],
|
||||||
|
east: [6, 15],
|
||||||
|
},
|
||||||
|
moving: 'normal',
|
||||||
|
pushing: 'normal',
|
||||||
|
swimming: {
|
||||||
|
north: [3, 12],
|
||||||
|
west: [3, 13],
|
||||||
|
south: [3, 14],
|
||||||
|
east: [3, 15],
|
||||||
|
},
|
||||||
|
burned: [3, 4], // TODO TW's lynx mode doesn't use this! it uses the generic failed
|
||||||
|
exploded: [3, 6],
|
||||||
|
failed: [3, 7],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -573,43 +596,29 @@ export class Tileset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwrap animations etc.
|
// Apply custom per-type visual states
|
||||||
if (!(coords instanceof Array)) {
|
if (TILE_TYPES[name].visual_state) {
|
||||||
// Must be an object of either tile-specific state, or directions
|
// Note that these accept null, too, and return a default
|
||||||
if (name === 'trap') {
|
let state = TILE_TYPES[name].visual_state(tile);
|
||||||
if (tile && tile.open) {
|
// If it's a string, that's an alias for another state
|
||||||
coords = coords.open;
|
if (typeof coords[state] === 'string') {
|
||||||
}
|
coords = coords[coords[state]];
|
||||||
else {
|
|
||||||
coords = coords.closed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO this is getting really ad-hoc and clumsy lol, maybe
|
coords = coords[state];
|
||||||
// have tiles expose a single 'state' prop or something
|
}
|
||||||
if (coords.moving) {
|
|
||||||
if (! tile) {
|
if (! coords) {
|
||||||
coords = coords.standing;
|
console.warn("No such state", state, "for tile", name, tile);
|
||||||
}
|
|
||||||
else if (coords.swimming &&
|
|
||||||
// Count as swimming if we're in water, but NOT if we're midway through
|
|
||||||
// stepping into water from a non-water tile
|
|
||||||
// TODO umm, only if we have flippers?
|
|
||||||
tile.cell.some(t => t.type.name === 'water') &&
|
|
||||||
(! tile.previous_cell || tile.previous_cell.some(t => t.type.name === 'water')))
|
|
||||||
{
|
|
||||||
coords = coords.swimming;
|
|
||||||
}
|
|
||||||
else if (tile.animation_speed) {
|
|
||||||
coords = coords.moving;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
coords = coords.standing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
coords = coords[(tile && tile.direction) ?? 'south'];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generic sprite definitions from here on!
|
||||||
|
// If we still have an object, it must be a table of directions
|
||||||
|
if (!(coords instanceof Array)) {
|
||||||
|
coords = coords[(tile && tile.direction) ?? 'south'];
|
||||||
|
}
|
||||||
|
|
||||||
// Deal with animation
|
// Deal with animation
|
||||||
if (coords[0] instanceof Array) {
|
if (coords[0] instanceof Array) {
|
||||||
if (tic !== null) {
|
if (tic !== null) {
|
||||||
|
|||||||
@ -7,6 +7,36 @@ const LAYER_ACTOR = 2;
|
|||||||
const LAYER_OVERLAY = 3;
|
const LAYER_OVERLAY = 3;
|
||||||
// TODO cc2 order is: swivel, thinwalls, canopy (and yes you can have them all in the same tile)
|
// TODO cc2 order is: swivel, thinwalls, canopy (and yes you can have them all in the same tile)
|
||||||
|
|
||||||
|
function player_visual_state(me) {
|
||||||
|
if (! me) {
|
||||||
|
return 'normal';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me.fail_reason === 'drowned') {
|
||||||
|
return 'drowned';
|
||||||
|
}
|
||||||
|
else if (me.fail_reason === 'burned') {
|
||||||
|
return 'burned';
|
||||||
|
}
|
||||||
|
else if (me.fail_reason === 'exploded') {
|
||||||
|
return 'exploded';
|
||||||
|
}
|
||||||
|
else if (me.fail_reason) {
|
||||||
|
return 'failed';
|
||||||
|
}
|
||||||
|
else if (me.cell.some(t => t.type.name === 'water') &&
|
||||||
|
(! me.previous_cell || me.previous_cell.some(t => t.type.name === 'water')))
|
||||||
|
{
|
||||||
|
return 'swimming';
|
||||||
|
}
|
||||||
|
else if (me.animation_speed) {
|
||||||
|
return 'moving';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 'normal';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const TILE_TYPES = {
|
const TILE_TYPES = {
|
||||||
// Floors and walls
|
// Floors and walls
|
||||||
floor: {
|
floor: {
|
||||||
@ -290,7 +320,6 @@ const TILE_TYPES = {
|
|||||||
level.transmute_tile(me, 'water');
|
level.transmute_tile(me, 'water');
|
||||||
}
|
}
|
||||||
else if (other.type.is_player) {
|
else if (other.type.is_player) {
|
||||||
level.transmute_tile(other, 'player_burned');
|
|
||||||
level.fail('burned');
|
level.fail('burned');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -311,7 +340,6 @@ const TILE_TYPES = {
|
|||||||
level.transmute_tile(me, 'ice');
|
level.transmute_tile(me, 'ice');
|
||||||
}
|
}
|
||||||
else if (other.type.is_player) {
|
else if (other.type.is_player) {
|
||||||
level.transmute_tile(other, 'splash');
|
|
||||||
level.fail('drowned');
|
level.fail('drowned');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -433,11 +461,12 @@ const TILE_TYPES = {
|
|||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
on_arrive(me, level, other) {
|
on_arrive(me, level, other) {
|
||||||
level.remove_tile(me);
|
level.remove_tile(me);
|
||||||
let was_player = other.type.is_player;
|
if (other.type.is_player) {
|
||||||
level.transmute_tile(other, 'explosion');
|
|
||||||
if (was_player) {
|
|
||||||
level.fail('exploded');
|
level.fail('exploded');
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
level.transmute_tile(other, 'explosion');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
thief_tools: {
|
thief_tools: {
|
||||||
@ -552,11 +581,12 @@ const TILE_TYPES = {
|
|||||||
is_required_chip: true,
|
is_required_chip: true,
|
||||||
on_arrive(me, level, other) {
|
on_arrive(me, level, other) {
|
||||||
level.remove_tile(me);
|
level.remove_tile(me);
|
||||||
let was_player = other.type.is_player;
|
if (other.type.is_player) {
|
||||||
level.transmute_tile(other, 'explosion');
|
|
||||||
if (was_player) {
|
|
||||||
level.fail('exploded');
|
level.fail('exploded');
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
level.transmute_tile(other, 'explosion');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
purple_floor: {
|
purple_floor: {
|
||||||
@ -605,6 +635,14 @@ const TILE_TYPES = {
|
|||||||
level.set_actor_stuck(other, true);
|
level.set_actor_stuck(other, true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
visual_state(me) {
|
||||||
|
if (me && me.open) {
|
||||||
|
return 'open';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 'closed';
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
transmogrifier: {
|
transmogrifier: {
|
||||||
draw_layer: LAYER_TERRAIN,
|
draw_layer: LAYER_TERRAIN,
|
||||||
@ -1093,6 +1131,7 @@ const TILE_TYPES = {
|
|||||||
infinite_items: {
|
infinite_items: {
|
||||||
key_green: true,
|
key_green: true,
|
||||||
},
|
},
|
||||||
|
visual_state: player_visual_state,
|
||||||
},
|
},
|
||||||
player2: {
|
player2: {
|
||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user