diff --git a/assets/_Game/Scenes/Default-theme.scene b/assets/_Game/Scenes/Default-theme.scene index 01bd011..4294a77 100644 --- a/assets/_Game/Scenes/Default-theme.scene +++ b/assets/_Game/Scenes/Default-theme.scene @@ -1559,7 +1559,6 @@ "__type__": "6bb6fbw5PNPYq7zksYK1kHJ", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 33 }, @@ -1881,7 +1880,6 @@ "__type__": "6bb6fbw5PNPYq7zksYK1kHJ", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 41 }, @@ -2465,7 +2463,6 @@ "__type__": "6bb6fbw5PNPYq7zksYK1kHJ", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 49 }, @@ -3021,7 +3018,6 @@ "__type__": "6bb6fbw5PNPYq7zksYK1kHJ", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 63 }, @@ -3371,7 +3367,6 @@ "__type__": "6bb6fbw5PNPYq7zksYK1kHJ", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 77 }, @@ -3721,7 +3716,6 @@ "__type__": "6bb6fbw5PNPYq7zksYK1kHJ", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 86 }, @@ -7127,7 +7121,6 @@ "__type__": "ce7b7e0d6BHlaRFoKBZN0h/", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 135 }, @@ -7798,7 +7791,6 @@ "__type__": "e3b5fa7tUtAbK3rQJ/G2Rox", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 212 }, @@ -8265,7 +8257,6 @@ "__type__": "671bfEgTTVFgLo1v+x/wd06", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 221 }, @@ -11835,7 +11826,6 @@ "__type__": "58a5aCWE8VEqJK+0wznWL24", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 311 }, @@ -14665,7 +14655,6 @@ "__type__": "c5e2dm0qXVOuKP1ju7uyMtJ", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 458 }, @@ -15900,7 +15889,6 @@ "__type__": "ecf07La1rNA8YjY0h97yfWf", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 237 }, @@ -17284,7 +17272,6 @@ "__type__": "204c1A707JPjYYnhqfMvkXj", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 587 }, @@ -17751,7 +17738,6 @@ "__type__": "fe619HtEX1OQq7oeACKrANd", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 609 }, @@ -18406,7 +18392,6 @@ "__type__": "02a884WNWtExrO21yAjQDWZ", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 221 }, @@ -19052,7 +19037,6 @@ "__type__": "bed15fuvPJLIp1O3BWg43ad", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 648 }, @@ -19696,7 +19680,6 @@ "__type__": "bed15fuvPJLIp1O3BWg43ad", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 664 }, @@ -20340,7 +20323,6 @@ "__type__": "bed15fuvPJLIp1O3BWg43ad", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 683 }, @@ -20984,7 +20966,6 @@ "__type__": "bed15fuvPJLIp1O3BWg43ad", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 702 }, @@ -21664,7 +21645,6 @@ "__type__": "85a1du42gFMrIHUG6qev0l/", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 723 }, @@ -22251,7 +22231,6 @@ "__type__": "85a1du42gFMrIHUG6qev0l/", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 738 }, @@ -22838,7 +22817,6 @@ "__type__": "85a1du42gFMrIHUG6qev0l/", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 753 }, @@ -23410,7 +23388,6 @@ "__type__": "85a1du42gFMrIHUG6qev0l/", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 768 }, @@ -23584,7 +23561,6 @@ "__type__": "ca8a0x4KJRGNJFfMRlEhSED", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 784 }, @@ -31090,7 +31066,6 @@ "__type__": "402d0NRh/pCFotZG+o5aE8p", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 789 }, @@ -33550,7 +33525,6 @@ "__type__": "1f970S32ylOnofatPpSgI1Z", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 999 }, @@ -35568,7 +35542,6 @@ "__type__": "1f970S32ylOnofatPpSgI1Z", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 1134 }, @@ -36067,7 +36040,6 @@ "__type__": "85b9aaRsZBAn5sUxS5RQ3EF", "_name": "", "_objFlags": 0, - "__editorExtras__": {}, "node": { "__id__": 9 }, @@ -36094,7 +36066,7 @@ "y": -1200, "z": 0 }, - "_timePlay": 120, + "_timePlay": 10, "_clockIcon": { "__uuid__": "f7bd5166-9d5f-4d43-a3d3-58ae9a4957fc@f9941", "__expectedType__": "cc.SpriteFrame" diff --git a/assets/_Game/Scripts/Base.meta b/assets/_Game/Scripts/Base.meta new file mode 100644 index 0000000..788b1c0 --- /dev/null +++ b/assets/_Game/Scripts/Base.meta @@ -0,0 +1,9 @@ +{ + "ver": "1.2.0", + "importer": "directory", + "imported": true, + "uuid": "94327d15-4016-4b65-9832-dba77c986128", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/assets/_Game/Scripts/Base/Timer.ts b/assets/_Game/Scripts/Base/Timer.ts new file mode 100644 index 0000000..1075e24 --- /dev/null +++ b/assets/_Game/Scripts/Base/Timer.ts @@ -0,0 +1,46 @@ +import { Director, director, game } from 'cc'; + +export enum TimerType { + countDown, + CountUp, +} + +export default class Timer { + private _timer: number = 0; + private _paused: boolean = true; + private _type: TimerType; + + constructor(type: TimerType) { + this._type = type; + director.on(Director.EVENT_AFTER_UPDATE, this.update, this); + } + + public get time() { + return this._timer; + } + + public get timeRound() { + return Math.round(this._timer); + } + + public set time(value: number) { + this._timer = value; + } + + protected update(dt: number): void { + if (this._paused) return; + if (this._type == TimerType.CountUp) { + this._timer += game.deltaTime; + } else { + this._timer -= game.deltaTime; + } + } + + public startCount() { + this._paused = false; + } + + public stopCount() { + this._paused = true; + } +} diff --git a/assets/_Game/Scripts/Manager/SoundManager.ts.meta b/assets/_Game/Scripts/Base/Timer.ts.meta similarity index 70% rename from assets/_Game/Scripts/Manager/SoundManager.ts.meta rename to assets/_Game/Scripts/Base/Timer.ts.meta index dd2a5d0..f54de8b 100644 --- a/assets/_Game/Scripts/Manager/SoundManager.ts.meta +++ b/assets/_Game/Scripts/Base/Timer.ts.meta @@ -2,7 +2,7 @@ "ver": "4.0.23", "importer": "typescript", "imported": true, - "uuid": "995ccd98-cdc8-4a0c-96f0-e10abd60ec3a", + "uuid": "20fc6cb6-0b98-42cc-b2a9-cdb2aa2d6e34", "files": [], "subMetas": {}, "userData": {} diff --git a/assets/_Game/Scripts/Booster/BoosterBase.ts b/assets/_Game/Scripts/Booster/BoosterBase.ts index 06a4523..4e29466 100644 --- a/assets/_Game/Scripts/Booster/BoosterBase.ts +++ b/assets/_Game/Scripts/Booster/BoosterBase.ts @@ -1,7 +1,7 @@ import { _decorator, Animation, AudioClip, CCFloat, CCString, Collider2D, Component, Contact2DType } from 'cc'; import GameEvent from '../Events/GameEvent'; +import { AudioManager } from '../Manager/AudioManager'; import { EventManger } from '../Manager/EventManger'; -import { SoundManager } from '../Manager/SoundManager'; import IPoolable from '../Pool/IPoolable'; import ObjectPool from '../Pool/ObjectPool'; import Utilities from '../Utilities'; @@ -31,7 +31,7 @@ export class BoosterBase extends Component implements IPoolable { if (!this._enabled) return; this.boosterActive(); this._enabled = false; - SoundManager.instance.playSfx(this._collectSound); + AudioManager.instance.playSfx(this._collectSound); EventManger.instance.emit(GameEvent.ObjectRelease, this.node); ObjectPool.release(this.node); } diff --git a/assets/_Game/Scripts/Environments/CumulativeBar.ts b/assets/_Game/Scripts/Environments/CumulativeBar.ts index 32c252c..83fd4e2 100644 --- a/assets/_Game/Scripts/Environments/CumulativeBar.ts +++ b/assets/_Game/Scripts/Environments/CumulativeBar.ts @@ -19,9 +19,9 @@ import { import BoosterType from '../Enum/BoosterType'; import ScoreType from '../Enum/ScoreType'; import GameEvent from '../Events/GameEvent'; +import AudioManager from '../Manager/AudioManager'; import { EventManger } from '../Manager/EventManger'; import { GameManager } from '../Manager/GameManager'; -import { SoundManager } from '../Manager/SoundManager'; import ObjectPool from '../Pool/ObjectPool'; import Utilities from '../Utilities'; import { SequenceSound } from './SequenceSound'; @@ -150,7 +150,7 @@ export class CumulativeBar extends Component { pos.z = 10; fx.node.setWorldPosition(pos); this._starPool.release(star); - SoundManager.instance.playSfx(this._collectStartSoundFx); + AudioManager.playSfx(this._collectStartSoundFx); await Utilities.waitUntil(() => { return fx.isStopped; }, 0.1); @@ -166,10 +166,10 @@ export class CumulativeBar extends Component { break; case ScoreType.Goal: if (this._currentValue == 0) { - SoundManager.instance.playSfx(this._goalSound, { volume: 3 }); + AudioManager.playSfx(this._goalSound, { volume: 3 }); return; } - SoundManager.instance.playSfx(this._cheeseModeGoalSound, { volume: 3 }); + AudioManager.playSfx(this._cheeseModeGoalSound, { volume: 3 }); this._multiplier = 0; this._goal = true; let items = Math.ceil(this._currentValue / 10); @@ -239,7 +239,7 @@ export class CumulativeBar extends Component { const pos = this.node.getWorldPosition(); pos.z = 10; fx.node.setWorldPosition(pos); - SoundManager.instance.playSfx(selectReward.sound); + AudioManager.playSfx(selectReward.sound); await Utilities.waitUntil(() => fx.isStopped, 0.1); selectReward.pool.release(fx); } diff --git a/assets/_Game/Scripts/Environments/ScoreObject.ts b/assets/_Game/Scripts/Environments/ScoreObject.ts index 776ba43..efc958c 100644 --- a/assets/_Game/Scripts/Environments/ScoreObject.ts +++ b/assets/_Game/Scripts/Environments/ScoreObject.ts @@ -11,9 +11,9 @@ import { Vec3, } from 'cc'; import GameEvent from '../Events/GameEvent'; +import AudioManager from '../Manager/AudioManager'; import { EventManger } from '../Manager/EventManger'; import { GameManager } from '../Manager/GameManager'; -import { SoundManager } from '../Manager/SoundManager'; import IPoolable from '../Pool/IPoolable'; import ObjectPool from '../Pool/ObjectPool'; import Utilities from '../Utilities'; @@ -70,7 +70,7 @@ export class ScoreObject extends Component implements IPoolable { private async onContactBegin(selfCollider: Collider2D, otherCollider: Collider2D) { if (!this._enabled) return; if (this._isHit) return; - if (this._hitSound) SoundManager.instance.playSfx(this._hitSound); + if (this._hitSound) AudioManager.playSfx(this._hitSound); this._enabled = false; // let center = this.node.getWorldPosition(); // let other = otherCollider.node.getWorldPosition(); diff --git a/assets/_Game/Scripts/Environments/SequenceSound.ts b/assets/_Game/Scripts/Environments/SequenceSound.ts index 3bc9813..eed076b 100644 --- a/assets/_Game/Scripts/Environments/SequenceSound.ts +++ b/assets/_Game/Scripts/Environments/SequenceSound.ts @@ -1,5 +1,5 @@ import { _decorator, AudioClip, CCFloat, Component, Node } from 'cc'; -import { SoundManager } from '../Manager/SoundManager'; +import AudioManager from '../Manager/AudioManager'; const { ccclass, property } = _decorator; @ccclass('SequenceSound') @@ -20,12 +20,12 @@ export class SequenceSound extends Component { public playSound(volume: number = 1) { if (this._timer > 0) { - SoundManager.instance.playSfx(this._audioClips[this._currentIndex], { volume }); + AudioManager.playSfx(this._audioClips[this._currentIndex], { volume }); this._currentIndex++; if (this._currentIndex >= this._audioClips.length) this._currentIndex = 0; } else { this._currentIndex = 0; - SoundManager.instance.playSfx(this._audioClips[this._currentIndex], { volume }); + AudioManager.playSfx(this._audioClips[this._currentIndex], { volume }); } this._timer = this._duration; } diff --git a/assets/_Game/Scripts/Environments/SlingShot.ts b/assets/_Game/Scripts/Environments/SlingShot.ts index f3035f2..b50ce6c 100644 --- a/assets/_Game/Scripts/Environments/SlingShot.ts +++ b/assets/_Game/Scripts/Environments/SlingShot.ts @@ -1,6 +1,6 @@ -import { _decorator, Collider2D, Component, Contact2DType, Node, Animation, RigidBody2D, AudioClip } from 'cc'; +import { _decorator, Animation, AudioClip, Collider2D, Component, Contact2DType, Node, RigidBody2D } from 'cc'; +import AudioManager from '../Manager/AudioManager'; import { CameraController } from './CameraController'; -import { SoundManager } from '../Manager/SoundManager'; const { ccclass, property } = _decorator; @ccclass('SlingShot') @@ -20,7 +20,7 @@ export default class SlingShot extends Component { onBeginContact(self: Collider2D, other: Collider2D) { this._animation.play(); const velocity = other.getComponent(RigidBody2D).linearVelocity.length(); - SoundManager.instance.playSfx(this._soundFx); + AudioManager.playSfx(this._soundFx); if (velocity >= 40) { CameraController.instance.shake(0.08); } diff --git a/assets/_Game/Scripts/Events/GameEvent.ts b/assets/_Game/Scripts/Events/GameEvent.ts index 2d44e58..fe05bdc 100644 --- a/assets/_Game/Scripts/Events/GameEvent.ts +++ b/assets/_Game/Scripts/Events/GameEvent.ts @@ -1,8 +1,8 @@ import { Node, Vec3 } from 'cc'; -import GameState from '../Enum/GameState'; -import ScoreType from '../Enum/ScoreType'; import BoosterType from '../Enum/BoosterType'; import ControllerSide from '../Enum/ControllerSide'; +import GameState from '../Enum/GameState'; +import ScoreType from '../Enum/ScoreType'; enum GameEvent { Score, diff --git a/assets/_Game/Scripts/GamePlay/Cannon.ts b/assets/_Game/Scripts/GamePlay/Cannon.ts index 1f63b8a..b174dcb 100644 --- a/assets/_Game/Scripts/GamePlay/Cannon.ts +++ b/assets/_Game/Scripts/GamePlay/Cannon.ts @@ -14,8 +14,8 @@ import { import TimeConfig from '../Enum/TimeConfig'; import { CameraController } from '../Environments/CameraController'; import GameEvent from '../Events/GameEvent'; +import AudioManager from '../Manager/AudioManager'; import { EventManger } from '../Manager/EventManger'; -import { SoundManager } from '../Manager/SoundManager'; import Utilities from '../Utilities'; import { Ball } from './Ball'; const { ccclass, property } = _decorator; @@ -54,7 +54,7 @@ export class Cannon extends Component { this._animation.play(); ball.clearRigiState(true); ball.throwBall(new Vec2(0, this._force)); - SoundManager.instance.playSfx(this._soundFx); + AudioManager.playSfx(this._soundFx); await Utilities.delay(TimeConfig.DelayCannonDone); tween(this._collider.node).to(0.5, { scale: Vec3.ZERO }, { easing: 'backIn' }).start(); EventHandler.emitEvents(this.onDone, ball); diff --git a/assets/_Game/Scripts/GamePlay/Enemy.ts b/assets/_Game/Scripts/GamePlay/Enemy.ts index aff44c7..7d5dd28 100644 --- a/assets/_Game/Scripts/GamePlay/Enemy.ts +++ b/assets/_Game/Scripts/GamePlay/Enemy.ts @@ -1,24 +1,24 @@ import { _decorator, + AudioClip, CCFloat, CCInteger, + Collider2D, Component, + Contact2DType, geometry, math, Node, - Vec3, - tween, - Collider2D, Sprite, - Contact2DType, - AudioClip, + tween, Tween, + Vec3, } from 'cc'; -import { EventManger } from '../Manager/EventManger'; -import GameEvent from '../Events/GameEvent'; -import ScoreType from '../Enum/ScoreType'; import GameState from '../Enum/GameState'; -import { SoundManager } from '../Manager/SoundManager'; +import ScoreType from '../Enum/ScoreType'; +import GameEvent from '../Events/GameEvent'; +import AudioManager from '../Manager/AudioManager'; +import { EventManger } from '../Manager/EventManger'; const { ccclass, property } = _decorator; @ccclass('Enemy') @@ -107,7 +107,7 @@ export class Enemy extends Component { } private onBeginContact(self: Collider2D, other: Collider2D) { - SoundManager.instance.playSfx(this._hitSound); + AudioManager.playSfx(this._hitSound); Tween.stopAllByTarget(this._sprite.node.scale); tween(this._sprite.node.scale) .set(Vec3.ONE) diff --git a/assets/_Game/Scripts/GamePlay/Goal.ts b/assets/_Game/Scripts/GamePlay/Goal.ts index e212ec9..4bac072 100644 --- a/assets/_Game/Scripts/GamePlay/Goal.ts +++ b/assets/_Game/Scripts/GamePlay/Goal.ts @@ -11,10 +11,7 @@ import { } from 'cc'; import TimeConfig from '../Enum/TimeConfig'; import { CameraController } from '../Environments/CameraController'; -import GameEvent from '../Events/GameEvent'; -import { EventManger } from '../Manager/EventManger'; import { GameManager } from '../Manager/GameManager'; -import { SoundManager } from '../Manager/SoundManager'; import ObjectPool from '../Pool/ObjectPool'; import Utilities from '../Utilities'; import { Ball } from './Ball'; diff --git a/assets/_Game/Scripts/GamePlay/MutilBall.ts b/assets/_Game/Scripts/GamePlay/MutilBall.ts index 6bec0e0..4fe7ce7 100644 --- a/assets/_Game/Scripts/GamePlay/MutilBall.ts +++ b/assets/_Game/Scripts/GamePlay/MutilBall.ts @@ -1,8 +1,8 @@ import { _decorator, AudioClip, Collider2D, Component, Contact2DType, Node, ParticleSystem, Prefab, Vec2 } from 'cc'; import TimeConfig from '../Enum/TimeConfig'; import { CameraController } from '../Environments/CameraController'; +import AudioManager from '../Manager/AudioManager'; import { GameManager } from '../Manager/GameManager'; -import { SoundManager } from '../Manager/SoundManager'; import ObjectPool from '../Pool/ObjectPool'; import Utilities from '../Utilities'; import { Ball } from './Ball'; @@ -63,7 +63,7 @@ export class MultiBall extends Component { const pos = this.node.getWorldPosition(); pos.z = 10; fx.node.setWorldPosition(pos); - SoundManager.instance.playSfx(this._soundFX); + AudioManager.playSfx(this._soundFX); await Utilities.delay(TimeConfig.DelayMultiBall); this._enabled = true; await Utilities.waitUntil(() => fx.isStopped); diff --git a/assets/_Game/Scripts/Gameplay/Ball.ts b/assets/_Game/Scripts/Gameplay/Ball.ts index 6690154..9bed334 100644 --- a/assets/_Game/Scripts/Gameplay/Ball.ts +++ b/assets/_Game/Scripts/Gameplay/Ball.ts @@ -24,8 +24,8 @@ import { import PhysicsGroup from '../Enum/PhysicGroup'; import { SequenceSound } from '../Environments/SequenceSound'; import GameEvent from '../Events/GameEvent'; +import AudioManager from '../Manager/AudioManager'; import { EventManger } from '../Manager/EventManger'; -import { SoundManager } from '../Manager/SoundManager'; import IPoolable from '../Pool/IPoolable'; import ObjectPool from '../Pool/ObjectPool'; import Utilities from '../Utilities'; @@ -166,7 +166,7 @@ export class Ball extends Component implements IPoolable { } const hitFx = this._impactPool.get(ParticleSystem, this.node.parent); hitFx.node.setWorldPosition(new Vec3(hitPoint.x, hitPoint.y, 10)); - SoundManager.instance.playSfx( + AudioManager.playSfx( otherCollider.group == PhysicsGroup.FLIPPER ? this._impactFlipperSound : this._impactSound, ); await Utilities.waitUntil(() => hitFx.isStopped, 0.1); diff --git a/assets/_Game/Scripts/Gameplay/Flipper.ts b/assets/_Game/Scripts/Gameplay/Flipper.ts index ee0c5bd..e3930c3 100644 --- a/assets/_Game/Scripts/Gameplay/Flipper.ts +++ b/assets/_Game/Scripts/Gameplay/Flipper.ts @@ -1,21 +1,21 @@ import { _decorator, + Animation, + AudioClip, + CCFloat, Component, + EventKeyboard, HingeJoint2D, input, - CCFloat, Input, - EventKeyboard, KeyCode, - Animation, Vec3, - AudioClip, } from 'cc'; -import { EventManger } from '../Manager/EventManger'; -import GameEvent from '../Events/GameEvent'; -import TimeConfig from '../Enum/TimeConfig'; -import { SoundManager } from '../Manager/SoundManager'; import ControllerSide from '../Enum/ControllerSide'; +import TimeConfig from '../Enum/TimeConfig'; +import GameEvent from '../Events/GameEvent'; +import AudioManager from '../Manager/AudioManager'; +import { EventManger } from '../Manager/EventManger'; const { ccclass, property } = _decorator; @ccclass('Flipper') @@ -116,7 +116,7 @@ export class Flipper extends Component { //#endregion private activeFlipper(): void { - SoundManager.instance.playSfx(this._activeSound, { volume: 0.5 }); + AudioManager.playSfx(this._activeSound, { volume: 0.5 }); this._hingeJoint.motorSpeed = this._motorSpeedActive; } private deActiveFlipper(): void { diff --git a/assets/_Game/Scripts/Manager/AudioManager.ts b/assets/_Game/Scripts/Manager/AudioManager.ts new file mode 100644 index 0000000..520684b --- /dev/null +++ b/assets/_Game/Scripts/Manager/AudioManager.ts @@ -0,0 +1,144 @@ +import { _decorator, AudioClip, AudioSource, sys } from 'cc'; +import 'howler'; + +export class SfxSource { + private _source: AudioSource; + + public get playing() { + return this._source.playing; + } + + public get loop() { + return this._source.loop; + } + + public set loop(value: boolean) { + this._source.loop = value; + } + + private _volume = 1; + public get volume() { + return this._volume; + } + public set volume(value: number) { + this._volume = value; + if (!this.mute) { + this._source.volume = value; + } + } + + private _mute = false; + public get mute() { + return this._mute; + } + public set mute(value: boolean) { + if (value) { + this._source.volume = 0; + } else { + this._source.volume = this.volume; + } + + this._mute = value; + } + + constructor(audioClip: AudioClip) { + this._source = new AudioSource(); + this._source.playOnAwake = false; + this._source.clip = audioClip; + } + + public play() { + if (!this.loop) { + if (this.playing) { + this._source.playOneShot(this._source.clip, this.mute ? 0 : this.volume); + return; + } + this._source.play(); + } else { + if (!this.playing) this._source.play(); + } + } + + public stop() { + this._source.stop(); + } +} + +export default class AudioManager { + private static _audioSourcesSfx: Map = new Map(); + private static _audioSourceBgm: Howl; + private static _isMute: boolean = false; + + public static get mute() { + return this._isMute; + } + + public static toggleMute(): boolean { + this._isMute = !this._isMute; + this.setMute(this._isMute); + return this._isMute; + } + + public static setMute(mute: boolean) { + this._isMute = mute; + this._audioSourceBgm.mute(this._isMute); + this._audioSourcesSfx.forEach((source) => { + source.mute = this._isMute; + }); + } + + public static playBGM(audio: AudioClip, opts?: { volume?: number; loop?: boolean; rate?: number }) { + this._audioSourceBgm?.stop(); + this._audioSourceBgm = new Howl({ + src: audio.nativeUrl, + loop: true, + mute: this._isMute, + ...opts, + }); + this._audioSourceBgm.play(); + } + + public static setPlayRateBGM(rate: number) { + this._audioSourceBgm.rate(rate); + } + + public static playSfx(audioClip: AudioClip, opts?: { volume?: number; loop?: boolean }) { + let soundSource = this._audioSourcesSfx.get(audioClip); + const config = { + volume: 1, + loop: false, + ...opts, + }; + + if (soundSource) { + soundSource.volume = config.volume; + soundSource.loop = config.loop; + soundSource.mute = this._isMute; + soundSource.play(); + return; + } + + soundSource = new SfxSource(audioClip); + soundSource.loop = config.loop; + soundSource.volume = config.volume; + soundSource.mute = this._isMute; + this._audioSourcesSfx.set(audioClip, soundSource); + soundSource.play(); + } + + public static stopBgm() { + this._audioSourceBgm.stop(); + } + + public static stopSfx(audioClip: AudioClip) { + this._audioSourcesSfx.get(audioClip).stop(); + } + + public static stopAllSfxLoop() { + this._audioSourcesSfx.forEach((sfx) => sfx.stop()); + } + + public static findAudioSourcesSfx(audioClip: AudioClip): SfxSource { + return this._audioSourcesSfx.get(audioClip); + } +} diff --git a/assets/_Game/Scripts/Manager/AudioManager.ts.meta b/assets/_Game/Scripts/Manager/AudioManager.ts.meta new file mode 100644 index 0000000..dd25d1f --- /dev/null +++ b/assets/_Game/Scripts/Manager/AudioManager.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.23", + "importer": "typescript", + "imported": true, + "uuid": "acb93341-6e50-4b28-bb35-5403f1340145", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/assets/_Game/Scripts/Manager/GameManager.ts b/assets/_Game/Scripts/Manager/GameManager.ts index a15d21a..803110a 100644 --- a/assets/_Game/Scripts/Manager/GameManager.ts +++ b/assets/_Game/Scripts/Manager/GameManager.ts @@ -1,31 +1,32 @@ import { _decorator, + AudioClip, + CCInteger, + Color, + EPhysics2DDrawFlags, Node, + PhysicsSystem2D, Prefab, + Quat, + randomRangeInt, + SpriteFrame, Vec2, Vec3, - randomRangeInt, - CCInteger, - AudioClip, - Quat, - EPhysics2DDrawFlags, - PhysicsSystem2D, - SpriteFrame, - Color, } from 'cc'; -import ObjectPool from '../Pool/ObjectPool'; -import { Ball } from '../GamePlay/Ball'; -import Utilities from '../Utilities'; -import GameState from '../Enum/GameState'; -import { EventManger } from './EventManger'; -import GameEvent from '../Events/GameEvent'; -import ScoreType from '../Enum/ScoreType'; -import { FloatingText } from '../Environments/FloatingText'; -import { SoundManager } from './SoundManager'; -import TimeConfig from '../Enum/TimeConfig'; import BEConnector from '../API/BEConnector'; +import Timer, { TimerType } from '../Base/Timer'; import BoosterType from '../Enum/BoosterType'; +import GameState from '../Enum/GameState'; +import ScoreType from '../Enum/ScoreType'; +import TimeConfig from '../Enum/TimeConfig'; +import { FloatingText } from '../Environments/FloatingText'; +import GameEvent from '../Events/GameEvent'; +import { Ball } from '../GamePlay/Ball'; +import ObjectPool from '../Pool/ObjectPool'; import Singleton from '../Singleton'; +import Utilities from '../Utilities'; +import AudioManager from './AudioManager'; +import { EventManger } from './EventManger'; import { StickerManager } from './StickerManager'; const { ccclass, property } = _decorator; @@ -86,7 +87,7 @@ export class GameManager extends Singleton() { private _ballPool: ObjectPool; private _FloatingScorePool: ObjectPool; private _gameState: GameState; - private _timer: number; + private _timer: Timer = new Timer(TimerType.countDown); private _boostersActive: Booster[] = []; private _score = 0; @@ -136,7 +137,7 @@ export class GameManager extends Singleton() { if (booster.runningTime >= booster.time) { this._boostersActive.splice(i, 1); if (this._boostersActive.length == 0) { - SoundManager.instance.setPlayRateBGM(1); + AudioManager.setPlayRateBGM(1); } EventManger.instance.emit(GameEvent.BoosterDisable, booster.type); } @@ -206,16 +207,16 @@ export class GameManager extends Singleton() { private async countTime() { while (this._gameState == GameState.Playing) { - this._timer--; - if (this._timer <= 0) { - this._timer = 0; + if (this._timer.time <= 0) { + this._timer.time = 0; + this._timer.stopCount(); this.gameOver(); } - if (!this._warningTime && this._timer <= 10) { + if (!this._warningTime && this._timer.time <= 10) { this._warningTime = true; EventManger.instance.emit(GameEvent.WarningTime, true); } - EventManger.instance.emit(GameEvent.TimeUpdate, this._timer); + EventManger.instance.emit(GameEvent.TimeUpdate, this._timer.timeRound); await Utilities.delay(1); } } @@ -238,7 +239,7 @@ export class GameManager extends Singleton() { public spawnBall(throwBall: boolean, playStartSound: boolean = true): Ball { if (this._gameState != GameState.Playing) return; - if (playStartSound) SoundManager.instance.playSfx(this._startSound); + if (playStartSound) AudioManager.playSfx(this._startSound); this.setCurrentBallInGame(1); const ball = this._ballPool.get(Ball, this._ballHolder); ball.init(this._boostersActive.length > 0); @@ -258,7 +259,7 @@ export class GameManager extends Singleton() { this.setCurrentBallInGame(-1); if (this._currentBallInGame <= 0) { EventManger.instance.emit(GameEvent.BallOut, null); - SoundManager.instance.playSfx(this._ballOutSound); + AudioManager.playSfx(this._ballOutSound); this.DisableAllBooster(); await Utilities.delay(TimeConfig.DelayPLay); this.spawnBall(true); @@ -295,18 +296,18 @@ export class GameManager extends Singleton() { } public addTime(time: number) { - this._timer += time; - if (this._warningTime && this._timer > 10) { + this._timer.time += time; + if (this._warningTime && this._timer.time > 10) { this._warningTime = false; EventManger.instance.emit(GameEvent.WarningTime, false); } - EventManger.instance.emit(GameEvent.TimeUpdate, this._timer); + EventManger.instance.emit(GameEvent.TimeUpdate, this._timer.timeRound); } public async gameOver() { this._ballPool.releaseAll(); this.DisableAllBooster(); - SoundManager.instance.playBGM(this._gameOverMusic); + AudioManager.playBGM(this._gameOverMusic); StickerManager.instance.showLabel('TIME UP!!!', { color: new Color('#ed3a18'), outLineColor: Color.WHITE }); BEConnector.gameScore = this.score; if (this.isReplayed) { @@ -319,28 +320,30 @@ export class GameManager extends Singleton() { } public Ready() { - SoundManager.instance.playBGM(this._backgroundMusic); + AudioManager.playBGM(this._backgroundMusic); this.changeGameState(GameState.Ready); } public async play() { - this._timer = this._timePlay + TimeConfig.DelayPLay; + this._timer.time = this._timePlay; this._score = 0; this._currentBallInGame = 0; this._isMultiBall = false; this.changeGameState(GameState.Playing); await Utilities.delay(TimeConfig.DelayPLay); + this._timer.startCount(); this.spawnBall(true); } public async gameRelive() { this.changeGameState(GameState.Relive); - this._timer = this._timePlay + TimeConfig.DelayPLay; + this._timer.time = this._timePlay; this._currentBallInGame = 0; this._isMultiBall = false; - SoundManager.instance.playBGM(this._backgroundMusic); + AudioManager.playBGM(this._backgroundMusic); this.changeGameState(GameState.Playing); await Utilities.delay(TimeConfig.DelayPLay); + this._timer.startCount(); this.spawnBall(true); } @@ -350,7 +353,7 @@ export class GameManager extends Singleton() { EventManger.instance.emit(GameEvent.BoosterDisable, booster.type); } this._boostersActive = []; - SoundManager.instance.setPlayRateBGM(1); + AudioManager.setPlayRateBGM(1); } public async ActiveBooster(type: BoosterType, time: number, displayName: string) { @@ -361,7 +364,7 @@ export class GameManager extends Singleton() { } this._boostersActive.push(new Booster(type, time)); EventManger.instance.emit(GameEvent.BoosterActive, [type, displayName]); - SoundManager.instance.playSfx(this._boosterActiveSound); - SoundManager.instance.setPlayRateBGM(1.25); + AudioManager.playSfx(this._boosterActiveSound); + AudioManager.setPlayRateBGM(1.25); } } diff --git a/assets/_Game/Scripts/Manager/SoundManager.ts b/assets/_Game/Scripts/Manager/SoundManager.ts deleted file mode 100644 index 7efda42..0000000 --- a/assets/_Game/Scripts/Manager/SoundManager.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { _decorator, AudioClip, AudioSource, Component, Node } from 'cc'; -import Singleton from '../Singleton'; -import { Howl } from 'howler'; -const { ccclass, property } = _decorator; - -export class SoundSource { - public source: AudioSource; - private _volume = 1; - public get volume() { - return this._volume; - } - public set volume(value: number) { - this._volume = value; - if (!this.mute) this.source.volume = value; - } - - private _mute = false; - public get mute() { - return this._mute; - } - public set mute(value: boolean) { - if (value) { - this.source.volume = 0; - } else { - this.source.volume = this.volume; - } - - this._mute = value; - } - - public play() { - if (this.source.playing) { - this.source.playOneShot(this.source.clip, this.mute ? 0 : this.volume); - return; - } - this.source.play(); - } - - public stop() { - this.source.stop(); - } -} - -@ccclass('SoundManager') -export class SoundManager extends Singleton('SoundManager') { - private _audioSourcesSfx: { [key: string]: SoundSource } = {}; - private _audioSourceBgm: Howl; - - private _isMute = false; - - public toggleMute(): boolean { - this._isMute = !this._isMute; - this.setMute(this._isMute); - return this._isMute; - } - - public setMute(mute: boolean) { - this._isMute = mute; - this._audioSourceBgm.mute(this._isMute); - for (const key in this._audioSourcesSfx) { - this._audioSourcesSfx[key].mute = this._isMute; - } - } - - public playBGM(audio: AudioClip, opts?: { volume?: number; loop?: boolean; rate?: number }) { - this._audioSourceBgm?.stop(); - this._audioSourceBgm = new globalThis.Howl({ - src: audio.nativeUrl, - volume: opts?.volume || 1, - loop: opts?.loop || true, - rate: opts?.rate || 1, - mute: this._isMute, - }); - this._audioSourceBgm.play(); - } - - public setPlayRateBGM(rate: number) { - this._audioSourceBgm.rate(rate); - } - - public playSfx(audioClip: AudioClip, opts?: { volume?: number; loop?: boolean }) { - let soundSource = this._audioSourcesSfx[audioClip.uuid]; - - if (soundSource) { - soundSource.volume = opts?.volume || 1; - soundSource.source.loop = !!opts?.loop; - if (soundSource.source.playing && !!opts?.loop) return; - soundSource.play(); - return; - } - soundSource = new SoundSource(); - const audioSource = new AudioSource('audioSourceSfx:' + audioClip.name); - soundSource.source = audioSource; - soundSource.source.playOnAwake = false; - soundSource.source.clip = audioClip; - soundSource.source.loop = !!opts?.loop; - soundSource.source.volume = opts?.volume || 1; - soundSource.mute = this._isMute; - this._audioSourcesSfx[audioClip.uuid] = soundSource; - soundSource.play(); - } - - public stopBgm() { - this._audioSourceBgm.stop(); - } - - public stopSfx(audioClip: AudioClip) { - this._audioSourcesSfx[audioClip.uuid].stop(); - } - - public stopAllSfxLoop() { - for (const key in this._audioSourcesSfx) { - this._audioSourcesSfx[key].stop(); - } - } - - public findAudioSourcesSfx(audioClip: AudioClip): SoundSource { - return this._audioSourcesSfx[audioClip.uuid]; - } -} diff --git a/assets/_Game/Scripts/Manager/StickerManager.ts b/assets/_Game/Scripts/Manager/StickerManager.ts index 21e91bf..bebae5a 100644 --- a/assets/_Game/Scripts/Manager/StickerManager.ts +++ b/assets/_Game/Scripts/Manager/StickerManager.ts @@ -1,17 +1,4 @@ -import { - _decorator, - CCString, - Color, - Component, - Label, - LabelOutline, - Node, - Sprite, - SpriteFrame, - Tween, - tween, - Vec3, -} from 'cc'; +import { _decorator, CCString, Color, Component, Label, Node, Sprite, SpriteFrame, Tween, tween, Vec3 } from 'cc'; import Singleton from '../Singleton'; const { ccclass, property } = _decorator; @@ -53,7 +40,7 @@ export class StickerManager extends Singleton() { this._label.string = string; this._label.color = opts?.color || new Color('#FFFF00'); this._label.node.setPosition(opts?.position || Vec3.ZERO); - this._label.getComponent(LabelOutline).color = opts?.outLineColor || new Color('#FF6600'); + this._label.outlineColor = opts?.outLineColor || new Color('#FF6600'); Tween.stopAllByTarget(this._label.node); tween(this._label.node) diff --git a/assets/_Game/Scripts/Plugins.meta b/assets/_Game/Scripts/Plugins.meta deleted file mode 100644 index 1bf8e5a..0000000 --- a/assets/_Game/Scripts/Plugins.meta +++ /dev/null @@ -1,12 +0,0 @@ -{ - "ver": "1.2.0", - "importer": "directory", - "imported": true, - "uuid": "6ae044bb-dbd0-486b-83a1-ca4fbefbd254", - "files": [], - "subMetas": {}, - "userData": { - "compressionType": {}, - "isRemoteBundle": {} - } -} diff --git a/assets/_Game/Scripts/Plugins/howler.min.js b/assets/_Game/Scripts/Plugins/howler.min.js deleted file mode 100644 index 40f9a2f..0000000 --- a/assets/_Game/Scripts/Plugins/howler.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! howler.js v2.2.4 | (c) 2013-2020, James Simpson of GoldFire Studios | MIT License | howlerjs.com */ -!function(){"use strict";var e=function(){this.init()};e.prototype={init:function(){var e=this||n;return e._counter=1e3,e._html5AudioPool=[],e.html5PoolSize=10,e._codecs={},e._howls=[],e._muted=!1,e._volume=1,e._canPlayEvent="canplaythrough",e._navigator="undefined"!=typeof window&&window.navigator?window.navigator:null,e.masterGain=null,e.noAudio=!1,e.usingWebAudio=!0,e.autoSuspend=!0,e.ctx=null,e.autoUnlock=!0,e._setup(),e},volume:function(e){var o=this||n;if(e=parseFloat(e),o.ctx||_(),void 0!==e&&e>=0&&e<=1){if(o._volume=e,o._muted)return o;o.usingWebAudio&&o.masterGain.gain.setValueAtTime(e,n.ctx.currentTime);for(var t=0;t=0;o--)e._howls[o].unload();return e.usingWebAudio&&e.ctx&&void 0!==e.ctx.close&&(e.ctx.close(),e.ctx=null,_()),e},codecs:function(e){return(this||n)._codecs[e.replace(/^x-/,"")]},_setup:function(){var e=this||n;if(e.state=e.ctx?e.ctx.state||"suspended":"suspended",e._autoSuspend(),!e.usingWebAudio)if("undefined"!=typeof Audio)try{var o=new Audio;void 0===o.oncanplaythrough&&(e._canPlayEvent="canplay")}catch(n){e.noAudio=!0}else e.noAudio=!0;try{var o=new Audio;o.muted&&(e.noAudio=!0)}catch(e){}return e.noAudio||e._setupCodecs(),e},_setupCodecs:function(){var e=this||n,o=null;try{o="undefined"!=typeof Audio?new Audio:null}catch(n){return e}if(!o||"function"!=typeof o.canPlayType)return e;var t=o.canPlayType("audio/mpeg;").replace(/^no$/,""),r=e._navigator?e._navigator.userAgent:"",a=r.match(/OPR\/(\d+)/g),u=a&&parseInt(a[0].split("/")[1],10)<33,d=-1!==r.indexOf("Safari")&&-1===r.indexOf("Chrome"),i=r.match(/Version\/(.*?) /),_=d&&i&&parseInt(i[1],10)<15;return e._codecs={mp3:!(u||!t&&!o.canPlayType("audio/mp3;").replace(/^no$/,"")),mpeg:!!t,opus:!!o.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,""),ogg:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),oga:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),wav:!!(o.canPlayType('audio/wav; codecs="1"')||o.canPlayType("audio/wav")).replace(/^no$/,""),aac:!!o.canPlayType("audio/aac;").replace(/^no$/,""),caf:!!o.canPlayType("audio/x-caf;").replace(/^no$/,""),m4a:!!(o.canPlayType("audio/x-m4a;")||o.canPlayType("audio/m4a;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),m4b:!!(o.canPlayType("audio/x-m4b;")||o.canPlayType("audio/m4b;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),mp4:!!(o.canPlayType("audio/x-mp4;")||o.canPlayType("audio/mp4;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),weba:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),webm:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),dolby:!!o.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/,""),flac:!!(o.canPlayType("audio/x-flac;")||o.canPlayType("audio/flac;")).replace(/^no$/,"")},e},_unlockAudio:function(){var e=this||n;if(!e._audioUnlocked&&e.ctx){e._audioUnlocked=!1,e.autoUnlock=!1,e._mobileUnloaded||44100===e.ctx.sampleRate||(e._mobileUnloaded=!0,e.unload()),e._scratchBuffer=e.ctx.createBuffer(1,1,22050);var o=function(n){for(;e._html5AudioPool.length0?d._seek:t._sprite[e][0]/1e3),s=Math.max(0,(t._sprite[e][0]+t._sprite[e][1])/1e3-_),l=1e3*s/Math.abs(d._rate),c=t._sprite[e][0]/1e3,f=(t._sprite[e][0]+t._sprite[e][1])/1e3;d._sprite=e,d._ended=!1;var p=function(){d._paused=!1,d._seek=_,d._start=c,d._stop=f,d._loop=!(!d._loop&&!t._sprite[e][2])};if(_>=f)return void t._ended(d);var m=d._node;if(t._webAudio){var v=function(){t._playLock=!1,p(),t._refreshBuffer(d);var e=d._muted||t._muted?0:d._volume;m.gain.setValueAtTime(e,n.ctx.currentTime),d._playStart=n.ctx.currentTime,void 0===m.bufferSource.start?d._loop?m.bufferSource.noteGrainOn(0,_,86400):m.bufferSource.noteGrainOn(0,_,s):d._loop?m.bufferSource.start(0,_,86400):m.bufferSource.start(0,_,s),l!==1/0&&(t._endTimers[d._id]=setTimeout(t._ended.bind(t,d),l)),o||setTimeout(function(){t._emit("play",d._id),t._loadQueue()},0)};"running"===n.state&&"interrupted"!==n.ctx.state?v():(t._playLock=!0,t.once("resume",v),t._clearTimer(d._id))}else{var h=function(){m.currentTime=_,m.muted=d._muted||t._muted||n._muted||m.muted,m.volume=d._volume*n.volume(),m.playbackRate=d._rate;try{var r=m.play();if(r&&"undefined"!=typeof Promise&&(r instanceof Promise||"function"==typeof r.then)?(t._playLock=!0,p(),r.then(function(){t._playLock=!1,m._unlocked=!0,o?t._loadQueue():t._emit("play",d._id)}).catch(function(){t._playLock=!1,t._emit("playerror",d._id,"Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction."),d._ended=!0,d._paused=!0})):o||(t._playLock=!1,p(),t._emit("play",d._id)),m.playbackRate=d._rate,m.paused)return void t._emit("playerror",d._id,"Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction.");"__default"!==e||d._loop?t._endTimers[d._id]=setTimeout(t._ended.bind(t,d),l):(t._endTimers[d._id]=function(){t._ended(d),m.removeEventListener("ended",t._endTimers[d._id],!1)},m.addEventListener("ended",t._endTimers[d._id],!1))}catch(e){t._emit("playerror",d._id,e)}};"data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA"===m.src&&(m.src=t._src,m.load());var y=window&&window.ejecta||!m.readyState&&n._navigator.isCocoonJS;if(m.readyState>=3||y)h();else{t._playLock=!0,t._state="loading";var g=function(){t._state="loaded",h(),m.removeEventListener(n._canPlayEvent,g,!1)};m.addEventListener(n._canPlayEvent,g,!1),t._clearTimer(d._id)}}return d._id},pause:function(e){var n=this;if("loaded"!==n._state||n._playLock)return n._queue.push({event:"pause",action:function(){n.pause(e)}}),n;for(var o=n._getSoundIds(e),t=0;t=0?o=parseInt(r[0],10):e=parseFloat(r[0])}else r.length>=2&&(e=parseFloat(r[0]),o=parseInt(r[1],10));var a;if(!(void 0!==e&&e>=0&&e<=1))return a=o?t._soundById(o):t._sounds[0],a?a._volume:0;if("loaded"!==t._state||t._playLock)return t._queue.push({event:"volume",action:function(){t.volume.apply(t,r)}}),t;void 0===o&&(t._volume=e),o=t._getSoundIds(o);for(var u=0;u0?t/_:t),l=Date.now();e._fadeTo=o,e._interval=setInterval(function(){var r=(Date.now()-l)/t;l=Date.now(),d+=i*r,d=Math.round(100*d)/100,d=i<0?Math.max(o,d):Math.min(o,d),u._webAudio?e._volume=d:u.volume(d,e._id,!0),a&&(u._volume=d),(on&&d>=o)&&(clearInterval(e._interval),e._interval=null,e._fadeTo=null,u.volume(o,e._id),u._emit("fade",e._id))},s)},_stopFade:function(e){var o=this,t=o._soundById(e);return t&&t._interval&&(o._webAudio&&t._node.gain.cancelScheduledValues(n.ctx.currentTime),clearInterval(t._interval),t._interval=null,o.volume(t._fadeTo,e),t._fadeTo=null,o._emit("fade",e)),o},loop:function(){var e,n,o,t=this,r=arguments;if(0===r.length)return t._loop;if(1===r.length){if("boolean"!=typeof r[0])return!!(o=t._soundById(parseInt(r[0],10)))&&o._loop;e=r[0],t._loop=e}else 2===r.length&&(e=r[0],n=parseInt(r[1],10));for(var a=t._getSoundIds(n),u=0;u=0?o=parseInt(r[0],10):e=parseFloat(r[0])}else 2===r.length&&(e=parseFloat(r[0]),o=parseInt(r[1],10));var d;if("number"!=typeof e)return d=t._soundById(o),d?d._rate:t._rate;if("loaded"!==t._state||t._playLock)return t._queue.push({event:"rate",action:function(){t.rate.apply(t,r)}}),t;void 0===o&&(t._rate=e),o=t._getSoundIds(o);for(var i=0;i=0?o=parseInt(r[0],10):t._sounds.length&&(o=t._sounds[0]._id,e=parseFloat(r[0]))}else 2===r.length&&(e=parseFloat(r[0]),o=parseInt(r[1],10));if(void 0===o)return 0;if("number"==typeof e&&("loaded"!==t._state||t._playLock))return t._queue.push({event:"seek",action:function(){t.seek.apply(t,r)}}),t;var d=t._soundById(o);if(d){if(!("number"==typeof e&&e>=0)){if(t._webAudio){var i=t.playing(o)?n.ctx.currentTime-d._playStart:0,_=d._rateSeek?d._rateSeek-d._seek:0;return d._seek+(_+i*Math.abs(d._rate))}return d._node.currentTime}var s=t.playing(o);s&&t.pause(o,!0),d._seek=e,d._ended=!1,t._clearTimer(o),t._webAudio||!d._node||isNaN(d._node.duration)||(d._node.currentTime=e);var l=function(){s&&t.play(o,!0),t._emit("seek",o)};if(s&&!t._webAudio){var c=function(){t._playLock?setTimeout(c,0):l()};setTimeout(c,0)}else l()}return t},playing:function(e){var n=this;if("number"==typeof e){var o=n._soundById(e);return!!o&&!o._paused}for(var t=0;t=0&&n._howls.splice(a,1);var u=!0;for(t=0;t=0){u=!1;break}return r&&u&&delete r[e._src],n.noAudio=!1,e._state="unloaded",e._sounds=[],e=null,null},on:function(e,n,o,t){var r=this,a=r["_on"+e];return"function"==typeof n&&a.push(t?{id:o,fn:n,once:t}:{id:o,fn:n}),r},off:function(e,n,o){var t=this,r=t["_on"+e],a=0;if("number"==typeof n&&(o=n,n=null),n||o)for(a=0;a=0;a--)r[a].id&&r[a].id!==n&&"load"!==e||(setTimeout(function(e){e.call(this,n,o)}.bind(t,r[a].fn),0),r[a].once&&t.off(e,r[a].fn,r[a].id));return t._loadQueue(e),t},_loadQueue:function(e){var n=this;if(n._queue.length>0){var o=n._queue[0];o.event===e&&(n._queue.shift(),n._loadQueue()),e||o.action()}return n},_ended:function(e){var o=this,t=e._sprite;if(!o._webAudio&&e._node&&!e._node.paused&&!e._node.ended&&e._node.currentTime=0;t--){if(o<=n)return;e._sounds[t]._ended&&(e._webAudio&&e._sounds[t]._node&&e._sounds[t]._node.disconnect(0),e._sounds.splice(t,1),o--)}}},_getSoundIds:function(e){var n=this;if(void 0===e){for(var o=[],t=0;t=0;if(!e.bufferSource)return o;if(n._scratchBuffer&&e.bufferSource&&(e.bufferSource.onended=null,e.bufferSource.disconnect(0),t))try{e.bufferSource.buffer=n._scratchBuffer}catch(e){}return e.bufferSource=null,o},_clearSound:function(e){/MSIE |Trident\//.test(n._navigator&&n._navigator.userAgent)||(e.src="data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA")}};var t=function(e){this._parent=e,this.init()};t.prototype={init:function(){var e=this,o=e._parent;return e._muted=o._muted,e._loop=o._loop,e._volume=o._volume,e._rate=o._rate,e._seek=0,e._paused=!0,e._ended=!0,e._sprite="__default",e._id=++n._counter,o._sounds.push(e),e.create(),e},create:function(){var e=this,o=e._parent,t=n._muted||e._muted||e._parent._muted?0:e._volume;return o._webAudio?(e._node=void 0===n.ctx.createGain?n.ctx.createGainNode():n.ctx.createGain(),e._node.gain.setValueAtTime(t,n.ctx.currentTime),e._node.paused=!0,e._node.connect(n.masterGain)):n.noAudio||(e._node=n._obtainHtml5Audio(),e._errorFn=e._errorListener.bind(e),e._node.addEventListener("error",e._errorFn,!1),e._loadFn=e._loadListener.bind(e),e._node.addEventListener(n._canPlayEvent,e._loadFn,!1),e._endFn=e._endListener.bind(e),e._node.addEventListener("ended",e._endFn,!1),e._node.src=o._src,e._node.preload=!0===o._preload?"auto":o._preload,e._node.volume=t*n.volume(),e._node.load()),e},reset:function(){var e=this,o=e._parent;return e._muted=o._muted,e._loop=o._loop,e._volume=o._volume,e._rate=o._rate,e._seek=0,e._rateSeek=0,e._paused=!0,e._ended=!0,e._sprite="__default",e._id=++n._counter,e},_errorListener:function(){var e=this;e._parent._emit("loaderror",e._id,e._node.error?e._node.error.code:0),e._node.removeEventListener("error",e._errorFn,!1)},_loadListener:function(){var e=this,o=e._parent;o._duration=Math.ceil(10*e._node.duration)/10,0===Object.keys(o._sprite).length&&(o._sprite={__default:[0,1e3*o._duration]}),"loaded"!==o._state&&(o._state="loaded",o._emit("load"),o._loadQueue()),e._node.removeEventListener(n._canPlayEvent,e._loadFn,!1)},_endListener:function(){var e=this,n=e._parent;n._duration===1/0&&(n._duration=Math.ceil(10*e._node.duration)/10,n._sprite.__default[1]===1/0&&(n._sprite.__default[1]=1e3*n._duration),n._ended(e)),e._node.removeEventListener("ended",e._endFn,!1)}};var r={},a=function(e){var n=e._src;if(r[n])return e._duration=r[n].duration,void i(e);if(/^data:[^;]+;base64,/.test(n)){for(var o=atob(n.split(",")[1]),t=new Uint8Array(o.length),a=0;a0?(r[o._src]=e,i(o,e)):t()};"undefined"!=typeof Promise&&1===n.ctx.decodeAudioData.length?n.ctx.decodeAudioData(e).then(a).catch(t):n.ctx.decodeAudioData(e,a,t)},i=function(e,n){n&&!e._duration&&(e._duration=n.duration),0===Object.keys(e._sprite).length&&(e._sprite={__default:[0,1e3*e._duration]}),"loaded"!==e._state&&(e._state="loaded",e._emit("load"),e._loadQueue())},_=function(){if(n.usingWebAudio){try{"undefined"!=typeof AudioContext?n.ctx=new AudioContext:"undefined"!=typeof webkitAudioContext?n.ctx=new webkitAudioContext:n.usingWebAudio=!1}catch(e){n.usingWebAudio=!1}n.ctx||(n.usingWebAudio=!1);var e=/iP(hone|od|ad)/.test(n._navigator&&n._navigator.platform),o=n._navigator&&n._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/),t=o?parseInt(o[1],10):null;if(e&&t&&t<9){var r=/safari/.test(n._navigator&&n._navigator.userAgent.toLowerCase());n._navigator&&!r&&(n.usingWebAudio=!1)}n.usingWebAudio&&(n.masterGain=void 0===n.ctx.createGain?n.ctx.createGainNode():n.ctx.createGain(),n.masterGain.gain.setValueAtTime(n._muted?0:n._volume,n.ctx.currentTime),n.masterGain.connect(n.ctx.destination)),n._setup()}};"function"==typeof define&&define.amd&&define([],function(){return{Howler:n,Howl:o}}),"undefined"!=typeof exports&&(exports.Howler=n,exports.Howl=o),"undefined"!=typeof global?(global.HowlerGlobal=e,global.Howler=n,global.Howl=o,global.Sound=t):"undefined"!=typeof window&&(window.HowlerGlobal=e,window.Howler=n,window.Howl=o,window.Sound=t)}(); -/*! Spatial Plugin */ -!function(){"use strict";HowlerGlobal.prototype._pos=[0,0,0],HowlerGlobal.prototype._orientation=[0,0,-1,0,1,0],HowlerGlobal.prototype.stereo=function(e){var n=this;if(!n.ctx||!n.ctx.listener)return n;for(var t=n._howls.length-1;t>=0;t--)n._howls[t].stereo(e);return n},HowlerGlobal.prototype.pos=function(e,n,t){var r=this;return r.ctx&&r.ctx.listener?(n="number"!=typeof n?r._pos[1]:n,t="number"!=typeof t?r._pos[2]:t,"number"!=typeof e?r._pos:(r._pos=[e,n,t],void 0!==r.ctx.listener.positionX?(r.ctx.listener.positionX.setTargetAtTime(r._pos[0],Howler.ctx.currentTime,.1),r.ctx.listener.positionY.setTargetAtTime(r._pos[1],Howler.ctx.currentTime,.1),r.ctx.listener.positionZ.setTargetAtTime(r._pos[2],Howler.ctx.currentTime,.1)):r.ctx.listener.setPosition(r._pos[0],r._pos[1],r._pos[2]),r)):r},HowlerGlobal.prototype.orientation=function(e,n,t,r,o,i){var a=this;if(!a.ctx||!a.ctx.listener)return a;var p=a._orientation;return n="number"!=typeof n?p[1]:n,t="number"!=typeof t?p[2]:t,r="number"!=typeof r?p[3]:r,o="number"!=typeof o?p[4]:o,i="number"!=typeof i?p[5]:i,"number"!=typeof e?p:(a._orientation=[e,n,t,r,o,i],void 0!==a.ctx.listener.forwardX?(a.ctx.listener.forwardX.setTargetAtTime(e,Howler.ctx.currentTime,.1),a.ctx.listener.forwardY.setTargetAtTime(n,Howler.ctx.currentTime,.1),a.ctx.listener.forwardZ.setTargetAtTime(t,Howler.ctx.currentTime,.1),a.ctx.listener.upX.setTargetAtTime(r,Howler.ctx.currentTime,.1),a.ctx.listener.upY.setTargetAtTime(o,Howler.ctx.currentTime,.1),a.ctx.listener.upZ.setTargetAtTime(i,Howler.ctx.currentTime,.1)):a.ctx.listener.setOrientation(e,n,t,r,o,i),a)},Howl.prototype.init=function(e){return function(n){var t=this;return t._orientation=n.orientation||[1,0,0],t._stereo=n.stereo||null,t._pos=n.pos||null,t._pannerAttr={coneInnerAngle:void 0!==n.coneInnerAngle?n.coneInnerAngle:360,coneOuterAngle:void 0!==n.coneOuterAngle?n.coneOuterAngle:360,coneOuterGain:void 0!==n.coneOuterGain?n.coneOuterGain:0,distanceModel:void 0!==n.distanceModel?n.distanceModel:"inverse",maxDistance:void 0!==n.maxDistance?n.maxDistance:1e4,panningModel:void 0!==n.panningModel?n.panningModel:"HRTF",refDistance:void 0!==n.refDistance?n.refDistance:1,rolloffFactor:void 0!==n.rolloffFactor?n.rolloffFactor:1},t._onstereo=n.onstereo?[{fn:n.onstereo}]:[],t._onpos=n.onpos?[{fn:n.onpos}]:[],t._onorientation=n.onorientation?[{fn:n.onorientation}]:[],e.call(this,n)}}(Howl.prototype.init),Howl.prototype.stereo=function(n,t){var r=this;if(!r._webAudio)return r;if("loaded"!==r._state)return r._queue.push({event:"stereo",action:function(){r.stereo(n,t)}}),r;var o=void 0===Howler.ctx.createStereoPanner?"spatial":"stereo";if(void 0===t){if("number"!=typeof n)return r._stereo;r._stereo=n,r._pos=[n,0,0]}for(var i=r._getSoundIds(t),a=0;a this._pool.countActive == 0, 0.1); this.yourScore.string = totalScore.toString(); - SoundManager.instance.playSfx(this._soundScore); + AudioManager.playSfx(this._soundScore); Tween.stopAllByTarget(this.yourScore.node); tween(this.yourScore.node) .set({ scale: Vec3.ONE }) diff --git a/assets/_Game/Scripts/UI/TimeUI.ts b/assets/_Game/Scripts/UI/TimeUI.ts index f394cb6..ab40861 100644 --- a/assets/_Game/Scripts/UI/TimeUI.ts +++ b/assets/_Game/Scripts/UI/TimeUI.ts @@ -1,9 +1,9 @@ import { _decorator, AudioClip, clamp01, Color, Component, Label, lerp, Node, Sprite, Tween, tween, Vec3 } from 'cc'; -import { EventManger } from '../Manager/EventManger'; -import GameEvent from '../Events/GameEvent'; import GameState from '../Enum/GameState'; +import GameEvent from '../Events/GameEvent'; +import AudioManager from '../Manager/AudioManager'; +import { EventManger } from '../Manager/EventManger'; import { GameManager } from '../Manager/GameManager'; -import { SoundManager } from '../Manager/SoundManager'; const { ccclass, property } = _decorator; @ccclass('TimeUI') @@ -41,7 +41,7 @@ export class TimeUI extends Component { case GameState.Playing: break; case GameState.GameOver: - SoundManager.instance.stopSfx(this._countDownSound); + AudioManager.stopSfx(this._countDownSound); break; case GameState.End: break; @@ -57,7 +57,7 @@ export class TimeUI extends Component { private onWarningTime(warning: boolean) { if (warning) { - SoundManager.instance.playSfx(this._countDownSound, { loop: true }); + AudioManager.playSfx(this._countDownSound, { loop: true }); this._fill.color = Color.RED; tween(this._timeIcon) .to(0.05, { position: new Vec3(3.117, 3.177) }) @@ -72,7 +72,7 @@ export class TimeUI extends Component { .start(); this._timeLabel.color = Color.RED; } else { - SoundManager.instance.stopSfx(this._countDownSound); + AudioManager.stopSfx(this._countDownSound); Tween.stopAllByTarget(this._timeIcon); this._fill.color = Color.GREEN; this._timeLabel.color = Color.WHITE; diff --git a/package-lock.json b/package-lock.json index b11a912..20d1e7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,8 @@ "": { "name": "PinBallTCC", "dependencies": { - "crypto-es": "^2.1.0" + "crypto-es": "^2.1.0", + "howler": "^2.2.4" }, "devDependencies": { "@types/howler": "^2.2.11", @@ -91,6 +92,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/howler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.4.tgz", + "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==" + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", diff --git a/package.json b/package.json index 759bd83..301267a 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "version": "3.8.2" }, "dependencies": { - "crypto-es": "^2.1.0" + "crypto-es": "^2.1.0", + "howler": "^2.2.4" }, "devDependencies": { "@types/howler": "^2.2.11", @@ -18,4 +19,4 @@ "pre-commit": "pretty-quick --staged" } } -} +} \ No newline at end of file