2024-03-12 01:50:54 -07:00
|
|
|
import { _decorator, Component, Node, Prefab, Vec2, Vec3, randomRangeInt, CCInteger, AudioClip } from 'cc';
|
2024-03-06 03:09:17 -08:00
|
|
|
import ObjectPool from '../Pool/ObjectPool';
|
2024-03-10 03:12:55 -07:00
|
|
|
import { Ball } from '../GamePlay/Ball';
|
|
|
|
import Utilities from '../Utilities';
|
2024-03-06 10:08:30 -08:00
|
|
|
import GameState from '../Enum/GameState';
|
|
|
|
import { EventManger } from './EventManger';
|
2024-03-07 03:15:08 -08:00
|
|
|
import GameEvent from '../Events/GameEvent';
|
|
|
|
import ScoreType from '../Enum/ScoreType';
|
2024-03-08 03:07:41 -08:00
|
|
|
import { FloatingText } from '../Environments/FloatingText';
|
2024-03-10 20:46:50 -07:00
|
|
|
import { SoundManager } from './SoundManager';
|
2024-03-12 01:50:54 -07:00
|
|
|
import TimeConfig from '../Enum/TimeConfig';
|
2024-03-06 01:28:01 -08:00
|
|
|
const { ccclass, property } = _decorator;
|
|
|
|
|
|
|
|
@ccclass('GameManager')
|
|
|
|
export class GameManager extends Component {
|
|
|
|
//singleton
|
|
|
|
private static _instance: GameManager = null;
|
|
|
|
public static get instance(): GameManager {
|
|
|
|
return GameManager._instance;
|
|
|
|
}
|
|
|
|
|
2024-03-06 03:09:17 -08:00
|
|
|
@property({ type: Prefab, visible: true })
|
|
|
|
private _ballPrefab: Prefab;
|
2024-03-08 03:07:41 -08:00
|
|
|
@property({ type: Prefab, visible: true })
|
|
|
|
private _floatingScoreText: Prefab;
|
|
|
|
@property({ type: Node, visible: true })
|
|
|
|
private _floatingTextContainer: Node;
|
2024-03-07 03:15:08 -08:00
|
|
|
@property({ visible: true })
|
2024-03-06 10:08:30 -08:00
|
|
|
private _ballSpawnPosition: Vec3;
|
|
|
|
@property({ type: CCInteger, visible: true })
|
2024-03-12 01:50:54 -07:00
|
|
|
private readonly _timePlay = 3;
|
2024-03-10 20:46:50 -07:00
|
|
|
@property({ type: AudioClip, visible: true })
|
|
|
|
private _startSound: AudioClip;
|
|
|
|
@property({ type: AudioClip, visible: true })
|
|
|
|
private _backgroundMusic: AudioClip;
|
2024-03-06 10:08:30 -08:00
|
|
|
|
2024-03-06 03:09:17 -08:00
|
|
|
private _ballPool: ObjectPool;
|
2024-03-08 03:07:41 -08:00
|
|
|
private _FloatingScorePool: ObjectPool;
|
2024-03-10 20:46:50 -07:00
|
|
|
private _gameState: GameState;
|
2024-03-12 01:50:54 -07:00
|
|
|
private _timer: number;
|
2024-03-11 04:12:22 -07:00
|
|
|
|
2024-03-07 03:15:08 -08:00
|
|
|
private _score = 0;
|
2024-03-10 03:12:55 -07:00
|
|
|
private _isMultiBall = false;
|
|
|
|
private _currentBallInGame = 0;
|
|
|
|
|
|
|
|
public get score() {
|
|
|
|
return this._score;
|
|
|
|
}
|
2024-03-06 01:28:01 -08:00
|
|
|
|
2024-03-06 03:09:17 -08:00
|
|
|
protected onLoad(): void {
|
2024-03-06 10:08:30 -08:00
|
|
|
GameManager._instance = this;
|
2024-03-07 03:15:08 -08:00
|
|
|
this._ballPool = new ObjectPool(this._ballPrefab, 10, true, Ball);
|
2024-03-08 03:07:41 -08:00
|
|
|
this._FloatingScorePool = new ObjectPool(this._floatingScoreText, 10, true);
|
2024-03-06 03:09:17 -08:00
|
|
|
}
|
|
|
|
|
2024-03-10 20:46:50 -07:00
|
|
|
protected start(): void {
|
|
|
|
this.changeGameState(GameState.Init);
|
2024-03-06 10:08:30 -08:00
|
|
|
}
|
|
|
|
|
2024-03-12 01:50:54 -07:00
|
|
|
protected update(dt: number): void {
|
|
|
|
if (this._gameState != GameState.Playing) return;
|
|
|
|
this._timer -= dt;
|
|
|
|
if (this._timer <= 0) {
|
|
|
|
this._timer = 0;
|
|
|
|
this.gameOver();
|
|
|
|
}
|
|
|
|
|
|
|
|
EventManger.instance.emit(GameEvent.TimeUpdate, this._timer);
|
|
|
|
}
|
|
|
|
|
2024-03-06 10:08:30 -08:00
|
|
|
private changeGameState(state: GameState) {
|
|
|
|
this._gameState = state;
|
|
|
|
EventManger.instance.emit(GameEvent.GameStateChange, this._gameState);
|
|
|
|
}
|
|
|
|
|
2024-03-08 03:07:41 -08:00
|
|
|
private addScore(score: number, type: ScoreType, position: Vec3) {
|
2024-03-07 03:15:08 -08:00
|
|
|
this._score += score;
|
2024-03-08 03:07:41 -08:00
|
|
|
const floatingScore = this._FloatingScorePool.get(this._floatingTextContainer, FloatingText);
|
|
|
|
floatingScore.show(`+${score}`, position, score >= 100 ? 1.5 : 1, score >= 100 ? 1 : 0.7);
|
2024-03-10 03:12:55 -07:00
|
|
|
EventManger.instance.emit(GameEvent.Score, [this._score, type]);
|
|
|
|
}
|
|
|
|
|
|
|
|
private setCurrentBallInGame(value: number) {
|
|
|
|
this._currentBallInGame += value;
|
|
|
|
if (this._currentBallInGame >= 2) {
|
|
|
|
if (!this._isMultiBall) {
|
|
|
|
this._isMultiBall = true;
|
2024-03-12 01:50:54 -07:00
|
|
|
EventManger.instance.emit(GameEvent.MultiBall, true);
|
2024-03-10 03:12:55 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._currentBallInGame <= 0) {
|
|
|
|
if (this._isMultiBall) {
|
|
|
|
this._isMultiBall = false;
|
|
|
|
EventManger.instance.emit(GameEvent.MultiBall, false);
|
|
|
|
}
|
|
|
|
}
|
2024-03-07 03:15:08 -08:00
|
|
|
}
|
|
|
|
|
2024-03-10 03:12:55 -07:00
|
|
|
public spawnBall(throwBall: boolean): Ball {
|
2024-03-12 01:50:54 -07:00
|
|
|
if (this._gameState != GameState.Playing) return;
|
2024-03-10 20:46:50 -07:00
|
|
|
SoundManager.instance.playSfx(this._startSound);
|
2024-03-10 03:12:55 -07:00
|
|
|
this.setCurrentBallInGame(1);
|
2024-03-06 10:08:30 -08:00
|
|
|
const ball = this._ballPool.get(this.node, Ball);
|
|
|
|
ball.node.setPosition(this._ballSpawnPosition);
|
2024-03-10 03:12:55 -07:00
|
|
|
if (!throwBall) return ball;
|
2024-03-06 10:08:30 -08:00
|
|
|
let dir = randomRangeInt(-1, 2);
|
|
|
|
while (dir == 0) {
|
|
|
|
dir = randomRangeInt(-1, 2);
|
|
|
|
}
|
|
|
|
const force = new Vec2(dir, 1);
|
2024-03-07 03:15:08 -08:00
|
|
|
ball.throwBall(force.multiply2f(1, 40));
|
2024-03-06 10:08:30 -08:00
|
|
|
return ball;
|
|
|
|
}
|
|
|
|
|
2024-03-07 09:45:13 -08:00
|
|
|
public async ballOut() {
|
2024-03-10 03:12:55 -07:00
|
|
|
this.setCurrentBallInGame(-1);
|
|
|
|
if (this._currentBallInGame <= 0) {
|
2024-03-12 01:50:54 -07:00
|
|
|
EventManger.instance.emit(GameEvent.BallOut, null);
|
|
|
|
await Utilities.delay(TimeConfig.DelayPLay);
|
2024-03-10 03:12:55 -07:00
|
|
|
this.spawnBall(true);
|
2024-03-06 10:08:30 -08:00
|
|
|
}
|
2024-03-07 03:15:08 -08:00
|
|
|
}
|
|
|
|
|
2024-03-08 03:07:41 -08:00
|
|
|
public async goal(bonusScore: number, position: Vec3) {
|
2024-03-12 21:36:19 -07:00
|
|
|
this.addScore(this._isMultiBall ? bonusScore * 2 : bonusScore, ScoreType.Goal, position);
|
2024-03-10 03:12:55 -07:00
|
|
|
this.setCurrentBallInGame(-1);
|
|
|
|
if (this._currentBallInGame <= 0) {
|
2024-03-12 01:50:54 -07:00
|
|
|
await Utilities.delay(TimeConfig.DelayGoal);
|
2024-03-10 03:12:55 -07:00
|
|
|
this.spawnBall(true);
|
|
|
|
}
|
2024-03-07 03:15:08 -08:00
|
|
|
}
|
|
|
|
|
2024-03-12 01:50:54 -07:00
|
|
|
public async destroyEnvironmentObject(bonusScore: number, position: Vec3, bonusTime?: number) {
|
|
|
|
if (bonusScore) {
|
|
|
|
this.addScore(bonusScore, ScoreType.DestroyObject, position);
|
|
|
|
await Utilities.delay(0.3);
|
|
|
|
}
|
|
|
|
if (bonusTime) {
|
|
|
|
this.addTime(bonusTime);
|
|
|
|
const floatingScore = this._FloatingScorePool.get(this._floatingTextContainer, FloatingText);
|
|
|
|
floatingScore.show(`+${bonusTime}⏰`, position, 0.7);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public addTime(time: number) {
|
|
|
|
this._timer += time;
|
2024-03-06 10:08:30 -08:00
|
|
|
}
|
|
|
|
|
2024-03-12 01:50:54 -07:00
|
|
|
private gameOver() {
|
|
|
|
this._ballPool.releaseAll();
|
|
|
|
this.changeGameState(GameState.GameOver);
|
2024-03-10 20:46:50 -07:00
|
|
|
}
|
|
|
|
|
2024-03-12 01:50:54 -07:00
|
|
|
public async play() {
|
|
|
|
this._timer = this._timePlay + TimeConfig.DelayPLay;
|
2024-03-10 20:46:50 -07:00
|
|
|
this._score = 0;
|
|
|
|
this._currentBallInGame = 0;
|
|
|
|
this._isMultiBall = false;
|
2024-03-12 01:50:54 -07:00
|
|
|
SoundManager.instance.playBGM(this._backgroundMusic, 0.5);
|
2024-03-10 20:46:50 -07:00
|
|
|
this.changeGameState(GameState.Playing);
|
2024-03-12 01:50:54 -07:00
|
|
|
await Utilities.delay(TimeConfig.DelayPLay);
|
2024-03-10 20:46:50 -07:00
|
|
|
this.spawnBall(true);
|
2024-03-10 03:12:55 -07:00
|
|
|
}
|
|
|
|
|
2024-03-06 01:28:01 -08:00
|
|
|
public onRevive() {
|
|
|
|
throw new Error('Method not implemented.');
|
|
|
|
}
|
|
|
|
}
|