Skip to content

Commit

Permalink
improving audio events. New audio_stop event.
Browse files Browse the repository at this point in the history
  • Loading branch information
jjppof committed Jan 28, 2024
1 parent 3f57372 commit d8e3d85
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 12 deletions.
122 changes: 114 additions & 8 deletions base/Audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class Audio {
private se_data: {[se_key: string]: Phaser.AudioSprite} = {};
private _current_bgm: Phaser.Sound = null;
private bgm_volume: number;
private playing_bgms: {[id_key: string]: Phaser.Sound} = {};

constructor(game: Phaser.Game, data: GoldenSun) {
this.game = game;
Expand Down Expand Up @@ -151,17 +152,84 @@ export class Audio {
* @param loop Whether the bgm should loop or not.
* @param volume The volume to be applied. [0,1].
* @param on_complete On bgm complete callback.
* @param fade_in if true, the bgm will fade in on start.
* @param fade_duration The fade in duration in ms.
*/
play_bgm(loop: boolean = true, volume?: number, on_complete?: () => void) {
play_bgm(
loop: boolean = true,
volume?: number,
on_complete?: () => void,
fade_in: boolean = false,
fade_duration: number = 750
) {
this.current_bgm.loop = loop;
this.current_bgm.volume = volume ?? Audio.DEFAULT_BGM_VOLUME;
this.bgm_volume = this.current_bgm.volume;
this.current_bgm.play();
if (fade_in) {
this.current_bgm.fadeIn(fade_duration);
} else {
this.current_bgm.play();
}
if (on_complete) {
this.current_bgm.onMarkerComplete.addOnce(on_complete);
}
}

/**
* Adds a new BGM audio to Phaser sound manager and plays it. You can give an unique name for this BGM by passing 'bgm_identifier' argument.
* @param bgm_key The bgm key name registered in the json db.
* @param loop Whether the bgm should loop or not.
* @param volume The volume to be applied. [0,1].
* @param on_complete On bgm complete callback.
* @param fade_in if true, the bgm will fade in on start.
* @param fade_duration The fade in duration in ms.
* @param bgm_identifier an unique name for this bgm.
* @returns returns the Phaser.Sound object.
*/
play_parallel_bgm(
bgm_key: string,
loop: boolean = true,
volume?: number,
on_complete?: () => void,
fade_in: boolean = false,
fade_duration: number = 750,
bgm_identifier?: string
) {
let bgm: Phaser.Sound;
if (bgm_identifier && bgm_identifier in this.playing_bgms) {
bgm = this.playing_bgms[bgm_identifier];
} else {
bgm = this.game.add.audio(bgm_key);
if (bgm_identifier) {
this.playing_bgms[bgm_identifier] = bgm;
}
}
bgm.loop = loop;
bgm.volume = volume ?? Audio.DEFAULT_BGM_VOLUME;
if (fade_in) {
bgm.fadeIn(fade_duration);
} else {
bgm.play();
}
if (on_complete) {
bgm.onMarkerComplete.addOnce(on_complete);
}
return bgm;
}

/**
* Gets the Phaser.Sound object of a bgm.
* @param bgm_identifier the bgm identifier.
* @returns the bgm Phaser.Sound object.
*/
get_bgm_object(bgm_identifier: string) {
if (bgm_identifier in this.playing_bgms) {
return this.playing_bgms[bgm_identifier];
} else {
return null;
}
}

/**
* Plays the current active battle bgm.
*/
Expand Down Expand Up @@ -200,16 +268,54 @@ export class Audio {
}

/**
* Pauses the current bgm sound.
* Pauses a bgm.
* @param bgm_identifier the bgm identifier to be paused. If not passed, it will pause current bgm.
* @param fade_out if true, the bgm will fade out before pausing.
* @param fade_duration the fadeout duration in ms.
*/
pause_bgm() {
this.current_bgm?.pause();
pause_bgm(bgm_identifier?: string, fade_out: boolean = false, fade_duration: number = 750) {
let bgm: Phaser.Sound;
if (bgm_identifier && bgm_identifier in this.playing_bgms) {
bgm = this.playing_bgms[bgm_identifier];
} else {
bgm = this.current_bgm;
}
if (fade_out) {
bgm.fadeOut(fade_duration);
bgm.onFadeComplete.addOnce(() => {
bgm?.pause();
});
} else {
bgm?.pause();
}
}

/**
* Stops the current bgm sound.
* Stops a bgm. If 'bgm_identifier', the bgm entry is removed on stop finish.
* @param bgm_identifier the bgm identifier to be stopped. If not passed, it will stop current bgm.
* @param fade_out if true, the bgm will fade out before stopping.
* @param fade_duration the fadeout duration in ms.
*/
stop_bgm() {
this.current_bgm?.stop();
stop_bgm(bgm_identifier?: string, fade_out: boolean = false, fade_duration: number = 750) {
let from_identifier = false;
let bgm: Phaser.Sound;
if (bgm_identifier && bgm_identifier in this.playing_bgms) {
bgm = this.playing_bgms[bgm_identifier];
from_identifier = true;
} else {
bgm = this.current_bgm;
}
if (fade_out) {
bgm.fadeOut(fade_duration);
bgm.onFadeComplete.addOnce(() => {
bgm?.stop();
if (from_identifier) {
bgm?.destroy();
delete this.playing_bgms[bgm_identifier];
}
});
} else {
bgm?.stop();
}
}
}
50 changes: 46 additions & 4 deletions base/game_events/AudioPlayEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,35 @@ export class AudioPlayEvent extends GameEvent {
private audio_key: string;
private volume: number;
private loop: boolean;
private fade_in: boolean;
private in_parallel: boolean;
private bgm_identifier: string;
private _bgm: Phaser.Sound;

constructor(game, data, active, key_name, keep_reveal, audio_type, audio_key, volume, loop, finish_events) {
constructor(
game,
data,
active,
key_name,
keep_reveal,
audio_type,
audio_key,
volume,
loop,
fade_in,
in_parallel,
bgm_identifier,
finish_events
) {
super(game, data, event_types.AUDIO_PLAY, active, key_name, keep_reveal);
this.audio_type = audio_type;
this.audio_key = audio_key;
this.volume = volume;
this.volume = volume ?? 1.0;
this.loop = loop;
this.fade_in = fade_in;
this.in_parallel = in_parallel;
this.bgm_identifier = bgm_identifier;
this._bgm = null;
if (finish_events !== undefined) {
finish_events.forEach(event_info => {
const event = this.data.game_event_manager.get_event_instance(event_info, this.type, this.origin_npc);
Expand All @@ -28,18 +50,38 @@ export class AudioPlayEvent extends GameEvent {

_fire() {
if (this.audio_type === audio_types.BGM) {
this.data.audio.set_bgm(this.audio_key);
this.data.audio.play_bgm(this.loop, this.volume, this.finish.bind(this));
if (this.in_parallel) {
this._bgm = this.data.audio.play_parallel_bgm(
this.audio_key,
this.loop,
this.volume,
this.finish.bind(this),
this.fade_in,
undefined,
this.bgm_identifier
);
} else {
this.data.audio.set_bgm(this.audio_key);
this.data.audio.play_bgm(this.loop, this.volume, this.finish.bind(this), this.fade_in);
}
} else if (this.audio_type === audio_types.SFX) {
this.data.audio.play_se(this.audio_key, this.finish.bind(this), undefined, this.volume);
}
}

finish() {
if (this._bgm) {
this._bgm.destroy();
this._bgm = null;
}
this.finish_events.forEach(event => event.fire(this.origin_npc));
}

_destroy() {
if (this._bgm) {
this._bgm.destroy();
this._bgm = null;
}
this.finish_events.forEach(event => event?.destroy());
}
}
28 changes: 28 additions & 0 deletions base/game_events/AudioStopEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {GameEvent, event_types} from "./GameEvent";

export class AudioStopEvent extends GameEvent {
private pause_only: boolean;
private fade_out: boolean;
private bgm_identifier: string;

constructor(game, data, active, key_name, keep_reveal, pause_only, fade_out, bgm_identifier) {
super(game, data, event_types.AUDIO_STOP, active, key_name, keep_reveal);
this.pause_only = pause_only;
this.fade_out = fade_out;
this.bgm_identifier = bgm_identifier;
}

_fire() {
if (this.data.audio.get_bgm_object(this.bgm_identifier)) {
if (this.pause_only) {
this.data.audio.pause_bgm(this.bgm_identifier, this.fade_out);
} else {
this.data.audio.stop_bgm(this.bgm_identifier, this.fade_out);
}
} else {
this.data.logger.log_message(`There's no active BGM with '${this.bgm_identifier}' identifier.`);
}
}

_destroy() {}
}
1 change: 1 addition & 0 deletions base/game_events/GameEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export enum event_types {
EXIT_SAND_MODE = "exit_sand_mode",
CHAR_FALL = "char_fall",
SET_CHAR_HP_PP = "set_char_hp_pp",
AUDIO_STOP = "audio_stop",
}

export enum game_event_misc_origin {
Expand Down
15 changes: 15 additions & 0 deletions base/game_events/GameEventManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ import {IOTweenPositionEvent} from "./IOTweenPositionEvent";
import {ExitSandModeEvent} from "./ExitSandModeEvent";
import {CharFallEvent} from "./CharFallEvent";
import {SetCharHPPPEvent} from "./SetCharHPPPEvent";
import {AudioStopEvent} from "./AudioStopEvent";

export enum interaction_patterns {
NO_INTERACTION = "no_interaction",
Expand Down Expand Up @@ -682,6 +683,9 @@ export class GameEventManager {
info.audio_key,
info.volume,
info.loop,
info.fade_in,
info.in_parallel,
info.bgm_identifier,
info.finish_events
);
case event_types.CONTROL_BGM:
Expand Down Expand Up @@ -1272,6 +1276,17 @@ export class GameEventManager {
info.points_type,
info.value
);
case event_types.AUDIO_STOP:
return new AudioStopEvent(
this.game,
this.data,
info.active,
info.key_name,
info.keep_reveal,
info.pause_only,
info.fade_out,
info.bgm_identifier
);
default:
const origin = `Event origin: ${event_origin}. ${
entity_origin?.label
Expand Down

0 comments on commit d8e3d85

Please sign in to comment.