feat: add timer class

feature/ads-smart-display
tiendat3699 2024-05-27 16:19:31 +07:00
parent 715cea87f9
commit 6e1dd2f415
29 changed files with 319 additions and 298 deletions

View File

@ -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"

View File

@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "94327d15-4016-4b65-9832-dba77c986128",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@ -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;
}
}

View File

@ -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": {}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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,

View File

@ -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);

View File

@ -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)

View File

@ -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';

View File

@ -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);

View File

@ -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);

View File

@ -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 {

View File

@ -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<AudioClip, SfxSource> = 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);
}
}

View File

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "acb93341-6e50-4b28-bb35-5403f1340145",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@ -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<GameManager>() {
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<GameManager>() {
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<GameManager>() {
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<GameManager>() {
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<GameManager>() {
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<GameManager>() {
}
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<GameManager>() {
}
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<GameManager>() {
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<GameManager>() {
}
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);
}
}

View File

@ -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>('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];
}
}

View File

@ -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<StickerManager>() {
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)

View File

@ -1,12 +0,0 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "6ae044bb-dbd0-486b-83a1-ca4fbefbd254",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,17 +0,0 @@
{
"ver": "4.0.23",
"importer": "javascript",
"imported": true,
"uuid": "8bd3776f-9ce5-4924-b348-3fbada6f0239",
"files": [
".js"
],
"subMetas": {},
"userData": {
"isPlugin": true,
"executionScope": "global",
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": true
}
}

View File

@ -1,5 +1,5 @@
import { _decorator, Button, Component, Node } from 'cc';
import { SoundManager } from '../Manager/SoundManager';
import AudioManager from '../Manager/AudioManager';
const { ccclass, property } = _decorator;
@ccclass('ButonSound')
@ -10,7 +10,7 @@ export class ButonSound extends Component {
private _mute: Node;
public clickBtn() {
const mute = SoundManager.instance.toggleMute();
const mute = AudioManager.toggleMute();
this._mute.active = mute;
this._unMute.active = !mute;
}

View File

@ -1,12 +1,12 @@
import { _decorator, AudioClip, Component, geometry, Label, Node, Prefab, Tween, tween, Vec3 } from 'cc';
import BEConnector from '../API/BEConnector';
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 ObjectPool from '../Pool/ObjectPool';
import Utilities from '../Utilities';
import { EventManger } from '../Manager/EventManger';
import GameEvent from '../Events/GameEvent';
import GameState from '../Enum/GameState';
import { SoundManager } from '../Manager/SoundManager';
const { ccclass, property } = _decorator;
@ccclass('GameOverPanel')
@ -155,13 +155,13 @@ export class GameOverPanel extends Component {
.start();
})
.start();
SoundManager.instance.playSfx(this._soundCollectCoinFx);
AudioManager.playSfx(this._soundCollectCoinFx);
await Utilities.delay(duration / 3);
}
await Utilities.waitUntil(() => 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 })

View File

@ -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;

8
package-lock.json generated
View File

@ -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",

View File

@ -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"
}
}
}
}