Make animations explicit, and fix almost every rendering problem
- `Tileset.animation_slowdown` is gone! - Actors are now free to animate every move or every two moves, and have been configured to do so appropriately. This fixes the appearance of blobs, most noticeably. (Also fixes #36.) - Actors that are always animated in CC2 are now always animated in LL. - Lilypads/turtles now bob randomly. More randomly than CC2, even. - Players no longer appear to be swimming when stepping off of lilypads. - Invisible walls no longer temporarily reveal themselves when you have the x-ray glasses (secret eye). - There's a new option for using the CC2 animation timing, though god knows why you would want to.
This commit is contained in:
parent
8533eac5db
commit
26c66d6857
@ -1092,6 +1092,9 @@ export class Level extends LevelInterface {
|
|||||||
if (actor.is_pulled) {
|
if (actor.is_pulled) {
|
||||||
this._set_tile_prop(actor, 'is_pulled', false);
|
this._set_tile_prop(actor, 'is_pulled', false);
|
||||||
}
|
}
|
||||||
|
if (actor.not_swimming) {
|
||||||
|
this._set_tile_prop(actor, 'not_swimming', false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actor === this.player) {
|
if (actor === this.player) {
|
||||||
|
|||||||
@ -533,6 +533,8 @@ class Player extends PrimaryView {
|
|||||||
|
|
||||||
this.use_interpolation = true;
|
this.use_interpolation = true;
|
||||||
// Default to the LL tileset for safety, but change when we load a level
|
// Default to the LL tileset for safety, but change when we load a level
|
||||||
|
// (Note also that this must be created in the constructor so the CC2 timing option can be
|
||||||
|
// applied to it)
|
||||||
this.renderer = new CanvasRenderer(this.conductor.tilesets['ll']);
|
this.renderer = new CanvasRenderer(this.conductor.tilesets['ll']);
|
||||||
this._loaded_tileset = false;
|
this._loaded_tileset = false;
|
||||||
this.level_el.append(this.renderer.canvas);
|
this.level_el.append(this.renderer.canvas);
|
||||||
@ -1212,6 +1214,7 @@ class Player extends PrimaryView {
|
|||||||
this.music_enabled = options.music_enabled ?? true;
|
this.music_enabled = options.music_enabled ?? true;
|
||||||
this.sfx_player.volume = options.sound_volume ?? 1.0;
|
this.sfx_player.volume = options.sound_volume ?? 1.0;
|
||||||
this.sfx_player.enabled = options.sound_enabled ?? true;
|
this.sfx_player.enabled = options.sound_enabled ?? true;
|
||||||
|
this.renderer.use_cc2_anim_speed = options.use_cc2_anim_speed ?? false;
|
||||||
|
|
||||||
if (this.level) {
|
if (this.level) {
|
||||||
this.update_tileset();
|
this.update_tileset();
|
||||||
@ -2584,6 +2587,8 @@ class OptionsOverlay extends DialogOverlay {
|
|||||||
mk('label', mk('input', {name: 'sound-enabled', type: 'checkbox'}), " Enabled"),
|
mk('label', mk('input', {name: 'sound-enabled', type: 'checkbox'}), " Enabled"),
|
||||||
mk('input', {name: 'sound-volume', type: 'range', min: 0, max: 1, step: 0.05}),
|
mk('input', {name: 'sound-volume', type: 'range', min: 0, max: 1, step: 0.05}),
|
||||||
),
|
),
|
||||||
|
mk('dt'),
|
||||||
|
mk('dd', mk('label', mk('input', {name: 'use-cc2-anim-speed', type: 'checkbox'}), " Use CC2 animation speed")),
|
||||||
);
|
);
|
||||||
// Update volume live, if the player is active and was playing when this dialog was opened
|
// Update volume live, if the player is active and was playing when this dialog was opened
|
||||||
// (note that it won't auto-pause until open())
|
// (note that it won't auto-pause until open())
|
||||||
@ -2692,6 +2697,7 @@ class OptionsOverlay extends DialogOverlay {
|
|||||||
this.root.elements['music-enabled'].checked = this.conductor.options.music_enabled ?? true;
|
this.root.elements['music-enabled'].checked = this.conductor.options.music_enabled ?? true;
|
||||||
this.root.elements['sound-volume'].value = this.conductor.options.sound_volume ?? 1.0;
|
this.root.elements['sound-volume'].value = this.conductor.options.sound_volume ?? 1.0;
|
||||||
this.root.elements['sound-enabled'].checked = this.conductor.options.sound_enabled ?? true;
|
this.root.elements['sound-enabled'].checked = this.conductor.options.sound_enabled ?? true;
|
||||||
|
this.root.elements['use-cc2-anim-speed'].checked = this.conductor.options.use_cc2_anim_speed ?? false;
|
||||||
|
|
||||||
this.root.elements['custom-tileset'].addEventListener('change', ev => {
|
this.root.elements['custom-tileset'].addEventListener('change', ev => {
|
||||||
this._load_custom_tileset(ev.target.files[0]);
|
this._load_custom_tileset(ev.target.files[0]);
|
||||||
@ -2703,6 +2709,7 @@ class OptionsOverlay extends DialogOverlay {
|
|||||||
options.music_enabled = this.root.elements['music-enabled'].checked;
|
options.music_enabled = this.root.elements['music-enabled'].checked;
|
||||||
options.sound_volume = parseFloat(this.root.elements['sound-volume'].value);
|
options.sound_volume = parseFloat(this.root.elements['sound-volume'].value);
|
||||||
options.sound_enabled = this.root.elements['sound-enabled'].checked;
|
options.sound_enabled = this.root.elements['sound-enabled'].checked;
|
||||||
|
options.use_cc2_anim_speed = this.root.elements['use-cc2-anim-speed'].checked;
|
||||||
|
|
||||||
// Tileset stuff: slightly more complicated. Save custom ones to localStorage as data
|
// Tileset stuff: slightly more complicated. Save custom ones to localStorage as data
|
||||||
// URIs, and /delete/ any custom ones we're not using any more, both of which require
|
// URIs, and /delete/ any custom ones we're not using any more, both of which require
|
||||||
|
|||||||
@ -14,6 +14,8 @@ class CanvasRendererDrawPacket extends DrawPacket {
|
|||||||
// Offset within the cell, for actors in motion
|
// Offset within the cell, for actors in motion
|
||||||
this.offsetx = 0;
|
this.offsetx = 0;
|
||||||
this.offsety = 0;
|
this.offsety = 0;
|
||||||
|
// Compatibility settings
|
||||||
|
this.use_cc2_anim_speed = renderer.use_cc2_anim_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
blit(tx, ty, mx = 0, my = 0, mw = 1, mh = mw, mdx = mx, mdy = my) {
|
blit(tx, ty, mx = 0, my = 0, mw = 1, mh = mw, mdx = mx, mdy = my) {
|
||||||
@ -60,6 +62,7 @@ export class CanvasRenderer {
|
|||||||
this.show_actor_order = false;
|
this.show_actor_order = false;
|
||||||
this.use_rewind_effect = false;
|
this.use_rewind_effect = false;
|
||||||
this.perception = 'normal'; // normal, xray, editor, palette
|
this.perception = 'normal'; // normal, xray, editor, palette
|
||||||
|
this.use_cc2_anim_speed = false;
|
||||||
this.active_player = null;
|
this.active_player = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
800
js/tileset.js
800
js/tileset.js
File diff suppressed because it is too large
Load Diff
@ -146,9 +146,12 @@ function player_visual_state(me) {
|
|||||||
else if (me.exited) {
|
else if (me.exited) {
|
||||||
return 'exited';
|
return 'exited';
|
||||||
}
|
}
|
||||||
else if (me.cell && (me.previous_cell || me.cell).has('water')) {
|
// This is slightly complicated. We should show a swimming pose while still in water, or moving
|
||||||
// CC2 shows a swimming pose while still in water, or moving away from water
|
// away from water (as CC2 does), but NOT when stepping off a lilypad (which will already have
|
||||||
// FIXME this also shows in some cases when we don't have flippers, e.g. when starting in water
|
// been turned into water), and NOT without flippers (which can happen if we start on water)
|
||||||
|
else if (me.cell && (me.previous_cell || me.cell).has('water') &&
|
||||||
|
! me.not_swimming && me.has_item('flippers'))
|
||||||
|
{
|
||||||
return 'swimming';
|
return 'swimming';
|
||||||
}
|
}
|
||||||
else if (me.slide_mode === 'ice') {
|
else if (me.slide_mode === 'ice') {
|
||||||
@ -833,6 +836,9 @@ const TILE_TYPES = {
|
|||||||
level.transmute_tile(me, 'water');
|
level.transmute_tile(me, 'water');
|
||||||
level.spawn_animation(me.cell, 'splash');
|
level.spawn_animation(me.cell, 'splash');
|
||||||
level.sfx.play_once('splash', me.cell);
|
level.sfx.play_once('splash', me.cell);
|
||||||
|
// Visual property, so the actor knows it's stepping off a lilypad, not swimming out of
|
||||||
|
// the water we just turned into
|
||||||
|
level._set_tile_prop(other, 'not_swimming', true);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
cracked_ice: {
|
cracked_ice: {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user