pinball/assets/_Game/Scripts/Manager/GameManager.ts

170 lines
5.2 KiB
TypeScript

import {
_decorator,
Component,
Node,
Prefab,
Vec2,
Vec3,
randomRangeInt,
CCInteger,
Director,
director,
AudioClip,
Label,
} 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';
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;
}
@property({ type: Prefab, visible: true })
private _ballPrefab: Prefab;
@property({ type: Prefab, visible: true })
private _floatingScoreText: Prefab;
@property({ type: Node, visible: true })
private _floatingTextContainer: Node;
@property({ visible: true })
private _ballSpawnPosition: Vec3;
@property({ type: CCInteger, visible: true })
private readonly _ballsInit = 3;
@property({ type: AudioClip, visible: true })
private _startSound: AudioClip;
@property({ type: AudioClip, visible: true })
private _backgroundMusic: AudioClip;
private _ballPool: ObjectPool;
private _FloatingScorePool: ObjectPool;
private _gameState: GameState;
private _balls: number;
public get balls() {
return this._ballsInit;
}
private _score = 0;
private _isMultiBall = false;
private _currentBallInGame = 0;
public get score() {
return this._score;
}
protected onLoad(): void {
GameManager._instance = this;
this._ballPool = new ObjectPool(this._ballPrefab, 10, true, Ball);
this._FloatingScorePool = new ObjectPool(this._floatingScoreText, 10, true);
}
protected start(): void {
this.changeGameState(GameState.Init);
}
private changeGameState(state: GameState) {
this._gameState = state;
EventManger.instance.emit(GameEvent.GameStateChange, this._gameState);
}
private addScore(score: number, type: ScoreType, position: Vec3) {
this._score += score;
const floatingScore = this._FloatingScorePool.get(this._floatingTextContainer, FloatingText);
floatingScore.show(`+${score}`, position, score >= 100 ? 1.5 : 1, score >= 100 ? 1 : 0.7);
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;
EventManger.instance.emit(GameEvent.MultiBall, false);
}
}
if (this._currentBallInGame <= 0) {
if (this._isMultiBall) {
this._isMultiBall = false;
EventManger.instance.emit(GameEvent.MultiBall, false);
}
}
}
public spawnBall(throwBall: boolean): Ball {
SoundManager.instance.playSfx(this._startSound);
this.setCurrentBallInGame(1);
const ball = this._ballPool.get(this.node, Ball);
ball.node.setPosition(this._ballSpawnPosition);
if (!throwBall) return ball;
let dir = randomRangeInt(-1, 2);
while (dir == 0) {
dir = randomRangeInt(-1, 2);
}
const force = new Vec2(dir, 1);
ball.throwBall(force.multiply2f(1, 40));
return ball;
}
public async ballOut() {
this.setCurrentBallInGame(-1);
if (this._currentBallInGame <= 0) {
this._balls--;
EventManger.instance.emit(GameEvent.BallOut, this._balls);
if (this._balls === 0) {
await Utilities.delay(1000);
this.changeGameState(GameState.GameOver);
return;
}
await Utilities.delay(1000);
this.spawnBall(true);
}
}
public async goal(bonusScore: number, position: Vec3) {
this.setCurrentBallInGame(-1);
this.addScore(this._isMultiBall ? bonusScore * 2 : bonusScore, ScoreType.Goal, position);
if (this._currentBallInGame <= 0) {
await Utilities.delay(2000);
this.spawnBall(true);
}
}
public destroyEnvironmentObject(bonusScore: number, position: Vec3) {
this.addScore(bonusScore, ScoreType.DestroyObject, position);
}
public async play() {
this._balls = this._ballsInit;
SoundManager.instance.playBGM(this._backgroundMusic, 0.5);
this.changeGameState(GameState.Playing);
await Utilities.delay(1000);
this.spawnBall(true);
}
public async restart() {
this._balls = this._ballsInit;
this._score = 0;
this._currentBallInGame = 0;
this._isMultiBall = false;
this.changeGameState(GameState.Playing);
await Utilities.delay(1000);
this.spawnBall(true);
}
public onRevive() {
throw new Error('Method not implemented.');
}
}