-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsound-controller.ts
137 lines (114 loc) · 3.71 KB
/
sound-controller.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import type { OnInit, OnStart } from "@flamework/core";
import { Controller } from "@flamework/core";
import type { Logger } from "@rbxts/log";
import { Inspect } from "@rbxts/rbx-debug";
import { SoundService, TweenService } from "@rbxts/services";
import { USER_ID } from "client/constants";
import { store } from "client/store";
import SoundSystem from "shared/modules/3d-sound-system";
import Make from "shared/modules/make";
import type { PlayerSettings } from "shared/store/persistent";
import { selectPlayerSettings } from "shared/store/persistent";
export const enum SoundType {
Music = "Music",
SoundEffect = "SoundEffect",
}
interface PlaySoundOptions {
attachToPoint?: BasePart;
debugName?: string;
sound: number;
soundProperties?: Omit<Partial<InstanceProperties<Sound>>, "Parent">;
soundType: SoundType;
}
/**
* A controller for managing sound effects and music in the game. This
* controller provides a way to play sounds and music with the ability to fade
* in and out the volume of the sound.
*
* ```
* const sound = soundController.createSound({ ... });.
* soundController.play(sound);.
*
* sound:Destroy(); -- Destroy the sound when you're done with it
* ```
*/
@Controller({})
export default class SoundController implements OnInit, OnStart {
private readonly soundGroups = new Map<SoundType, SoundGroup>();
constructor(private readonly logger: Logger) {}
/** @ignore */
public onInit(): void {
this.soundGroups.set(SoundType.Music, this.makeSoundGroup(SoundType.Music));
this.soundGroups.set(SoundType.SoundEffect, this.makeSoundGroup(SoundType.SoundEffect));
this.logger.Info("Setup SoundGroup instances");
}
/** @ignore */
public onStart(): void {
store.subscribe(selectPlayerSettings(USER_ID), current => {
if (!current) {
return;
}
this.onSettingsChanged(current);
});
}
public createSound({
attachToPoint,
debugName,
sound,
soundProperties = {},
soundType,
}: PlaySoundOptions): Sound {
const soundGroup = this.soundGroups.get(soundType);
assert(soundGroup, `SoundGroup not found for SoundType ${soundType}`);
const soundParent = attachToPoint ?? soundGroup;
const soundObject = Make("Sound", {
...soundProperties,
Name: debugName ?? Inspect(sound),
Parent: soundParent,
SoundGroup: soundGroup,
SoundId: `rbxassetid://${sound}`,
});
// Make it a 3D spatial sound if a point was declared
if (attachToPoint) {
SoundSystem.Attach(soundObject);
}
this.logger.Info(`Playing sound ${sound} of type ${soundType}`);
return soundObject;
}
public play(soundObject: Sound, fadeInTime?: number): void {
soundObject.Play();
if (fadeInTime !== undefined) {
this.fadeInSound(soundObject, fadeInTime);
}
}
public fadeInSound(soundObject: Sound, fadeInTime: number): void {
const desiredVolume = soundObject.Volume;
soundObject.Volume = 0;
const tweenInfo = new TweenInfo(
fadeInTime,
Enum.EasingStyle.Quad,
Enum.EasingDirection.Out,
);
TweenService.Create(soundObject, tweenInfo, { Volume: desiredVolume }).Play();
}
private makeSoundGroup(soundType: SoundType): SoundGroup {
// Make sure this SoundGroup doesn't already exist
const existing = SoundService.FindFirstChild(soundType);
if (existing?.IsA("SoundGroup") === true) {
return existing;
}
return Make("SoundGroup", {
Name: soundType,
Parent: SoundService,
Volume: 1,
});
}
private onSettingsChanged(current: PlayerSettings): void {
const musicGroup = this.soundGroups.get(SoundType.Music);
assert(musicGroup, "Music SoundGroup not found");
musicGroup.Volume = current.musicVolume;
const sfxGroup = this.soundGroups.get(SoundType.SoundEffect);
assert(sfxGroup, "SoundEffect SoundGroup not found");
sfxGroup.Volume = current.sfxVolume;
}
}