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

133 lines
4.3 KiB
TypeScript

import { _decorator, Component, Node, Prefab, Vec2, Vec3, randomRangeInt, CCInteger } 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';
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 _balls = 3;
private _ballPool: ObjectPool;
private _FloatingScorePool: ObjectPool;
private _gameState = GameState.Init;
public highestStreak: number;
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() {
this.spawnBall(true);
this.play();
}
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 {
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, null);
if (this._balls === 0) {
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 destroyEnviromentsObject(bonusScore: number, position: Vec3) {
this.addScore(bonusScore, ScoreType.DestroyObject, position);
}
public play() {
this.changeGameState(GameState.Playing);
}
public onRevive() {
throw new Error('Method not implemented.');
}
}