feat: update game event manager
parent
4d97fc35ea
commit
136a898942
|
@ -962,12 +962,16 @@
|
|||
"__prefab": {
|
||||
"__id__": 70
|
||||
},
|
||||
"rigidbody": {
|
||||
"_rigidbody": {
|
||||
"__id__": 67
|
||||
},
|
||||
"collider": {
|
||||
"_collider": {
|
||||
"__id__": 65
|
||||
},
|
||||
"_hitSound": {
|
||||
"__uuid__": "6a432293-3852-4267-be19-c671f36fe9f0",
|
||||
"__expectedType__": "cc.AudioClip"
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,6 @@
|
|||
enum GameEvent {}
|
||||
enum GameEvent {
|
||||
GameStateChange,
|
||||
BallHit,
|
||||
}
|
||||
|
||||
export default GameEvent;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
enum GameState {
|
||||
Init,
|
||||
Playing,
|
||||
GameOver,
|
||||
}
|
||||
|
||||
export default GameState;
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "cf53cc6f-2c88-4312-828e-6edf8bfc7583",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
_decorator,
|
||||
AudioClip,
|
||||
CCFloat,
|
||||
Collider2D,
|
||||
Component,
|
||||
|
@ -9,52 +10,64 @@ import {
|
|||
EventTarget,
|
||||
IPhysics2DContact,
|
||||
RigidBody2D,
|
||||
Vec2,
|
||||
} from 'cc';
|
||||
import IPoolable from '../Pool/IPoolable';
|
||||
import Utilities from '../Utilities/Utilities';
|
||||
import { SoundManager } from '../Manager/SoundManager';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('Ball')
|
||||
export class Ball extends Component implements IPoolable {
|
||||
@property({ visible: true, type: CCFloat })
|
||||
public maxSpeed: number;
|
||||
@property({ visible: true, type: RigidBody2D })
|
||||
public rigidbody: RigidBody2D;
|
||||
@property(Collider2D)
|
||||
public collider: Collider2D;
|
||||
public isActive: boolean;
|
||||
private hitted = false;
|
||||
@property({ type: CCFloat, visible: true })
|
||||
private _maxSpeed: number;
|
||||
@property({ type: RigidBody2D, visible: true })
|
||||
private _rigidbody: RigidBody2D;
|
||||
@property({ type: Collider2D, visible: true })
|
||||
private _collider: Collider2D;
|
||||
@property({ type: AudioClip, visible: true })
|
||||
private _hitSound: AudioClip;
|
||||
|
||||
private _hitted = false;
|
||||
|
||||
public eventHitObstacle = new EventTarget();
|
||||
public eventGoal = new EventTarget();
|
||||
|
||||
protected onLoad(): void {
|
||||
if (this.getComponent(Collider2D)) {
|
||||
this.collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
|
||||
this.collider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
|
||||
if (this._collider) {
|
||||
this._collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
|
||||
this._collider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
|
||||
}
|
||||
|
||||
director.on(Director.EVENT_AFTER_PHYSICS, this.setMaxVelocity, this);
|
||||
}
|
||||
|
||||
private onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {}
|
||||
private onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
|
||||
if (this._hitted) return;
|
||||
this._hitted = true;
|
||||
if (this._rigidbody.linearVelocity.length() >= 3) {
|
||||
SoundManager.instance.playSfx(this._hitSound);
|
||||
}
|
||||
}
|
||||
|
||||
private setMaxVelocity() {
|
||||
if (this.rigidbody.linearVelocity.length() > this.maxSpeed) {
|
||||
this.rigidbody.linearVelocity = this.rigidbody.linearVelocity.normalize().multiplyScalar(this.maxSpeed);
|
||||
if (this._rigidbody.linearVelocity.length() > this._maxSpeed) {
|
||||
this._rigidbody.linearVelocity = this._rigidbody.linearVelocity.normalize().multiplyScalar(this._maxSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
private onEndContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
|
||||
// console.log(otherCollider.tag, otherCollider.node.name);
|
||||
this.hitted = false;
|
||||
this._hitted = false;
|
||||
}
|
||||
|
||||
reuse() {
|
||||
console.log('use');
|
||||
public addFocre(force: Vec2) {
|
||||
const point = this.node.getWorldPosition();
|
||||
this._rigidbody.applyLinearImpulse(force, new Vec2(point.x, point.y), true);
|
||||
}
|
||||
|
||||
reuse() {}
|
||||
|
||||
unuse() {
|
||||
console.log('unuse');
|
||||
this._rigidbody.linearVelocity = Vec2.ZERO.clone();
|
||||
this._rigidbody.angularVelocity = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import { _decorator, Collider2D, Component, Contact2DType, Node } from 'cc';
|
||||
import { GameManager } from '../Manager/GameManager';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('Outer')
|
||||
export class Outer extends Component {
|
||||
@property({ type: Collider2D, visible: true })
|
||||
private _collider: Collider2D;
|
||||
|
||||
protected start(): void {
|
||||
this._collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
|
||||
}
|
||||
|
||||
private onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D) {
|
||||
GameManager.instance.ballOut(otherCollider.node);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "dabd58dc-7708-4931-ad63-cd7875b7b5df",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"ver": "1.1.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "29983e40-308b-4f9e-9e19-104e958a083b",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import GameEvent from '../Enum/GameEvent';
|
||||
import GameState from '../Enum/GameState';
|
||||
|
||||
export interface GameEventCallbackMap {
|
||||
[GameEvent.GameStateChange]: (state: GameState) => void;
|
||||
[GameEvent.BallHit]: () => void;
|
||||
}
|
||||
|
||||
export interface GameEventArgMap {
|
||||
[GameEvent.GameStateChange]: GameState;
|
||||
[GameEvent.BallHit]: null;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "b1eecaf3-413b-4baa-b963-ac905620d203",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import { _decorator, Component, EventTarget, Node } from 'cc';
|
||||
import { __private, _decorator, Component, EventTarget, Node } from 'cc';
|
||||
import GameEvent from '../Enum/GameEvent';
|
||||
import { GameEventArgMap, GameEventCallbackMap } from '../Interface/GameEventMap';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('EventManger')
|
||||
|
@ -21,15 +22,27 @@ export class EventManger extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
public on(eventType: GameEvent, callback?: (...args: any[]) => void, thisArg?: any) {
|
||||
this._eventTarget.on(eventType, callback, thisArg);
|
||||
public on<K extends keyof GameEventCallbackMap>(
|
||||
eventType: K,
|
||||
callback: GameEventCallbackMap[K],
|
||||
target?: any,
|
||||
): GameEventCallbackMap[K] {
|
||||
return this._eventTarget.on(eventType, callback, target);
|
||||
}
|
||||
|
||||
public off(eventType: GameEvent, callback?: (...args: any[]) => void, thisArg?: any) {
|
||||
this._eventTarget.on(eventType, callback, thisArg);
|
||||
public off<K extends keyof GameEventCallbackMap>(
|
||||
eventType: K,
|
||||
callback: GameEventCallbackMap[K],
|
||||
thisArg?: any,
|
||||
): GameEventCallbackMap[K] {
|
||||
return this._eventTarget.on(eventType, callback, thisArg);
|
||||
}
|
||||
|
||||
public emit(eventType: GameEvent, arg0?: any, arg1?: any, arg2?: any, arg3?: any, arg4?: any) {
|
||||
this._eventTarget.emit(eventType, arg0, arg1, arg2, arg3, arg4);
|
||||
public emit<K extends keyof GameEventArgMap>(eventType: K, arg: GameEventArgMap[K]) {
|
||||
if (Array.isArray(arg)) {
|
||||
this._eventTarget.emit(eventType, ...arg);
|
||||
} else {
|
||||
this._eventTarget.emit(eventType, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import { _decorator, Component, Prefab, Node } from 'cc';
|
||||
import { _decorator, Component, Prefab, Node, Vec2, Vec3, randomRangeInt, CCInteger, Input } from 'cc';
|
||||
import ObjectPool from '../Pool/ObjectPool';
|
||||
import { Ball } from '../Gameplay/Ball';
|
||||
import Utilities from '../Utilities/Utilities';
|
||||
import GameState from '../Enum/GameState';
|
||||
import { EventManger } from './EventManger';
|
||||
import GameEvent from '../Enum/GameEvent';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('GameManager')
|
||||
|
@ -13,15 +17,54 @@ export class GameManager extends Component {
|
|||
|
||||
@property({ type: Prefab, visible: true })
|
||||
private _ballPrefab: Prefab;
|
||||
@property({ type: Vec3, visible: true })
|
||||
private _ballSpawnPosition: Vec3;
|
||||
@property({ type: CCInteger, visible: true })
|
||||
private _balls = 3;
|
||||
|
||||
private _ballPool: ObjectPool;
|
||||
private _gameState = GameState.Init;
|
||||
|
||||
public highestStreak: number;
|
||||
public score = 0;
|
||||
|
||||
protected onLoad(): void {
|
||||
GameManager._instance = this;
|
||||
this._ballPool = new ObjectPool(this._ballPrefab, 10, false, Ball);
|
||||
}
|
||||
|
||||
protected async start() {
|
||||
// this.spawnBall();
|
||||
const a = [1, 4, 4, 5];
|
||||
}
|
||||
|
||||
private changeGameState(state: GameState) {
|
||||
this._gameState = state;
|
||||
EventManger.instance.emit(GameEvent.GameStateChange, this._gameState);
|
||||
}
|
||||
|
||||
public spawnBall(): Ball {
|
||||
const ball = this._ballPool.get(this.node, Ball);
|
||||
ball.node.setPosition(this._ballSpawnPosition);
|
||||
let dir = randomRangeInt(-1, 2);
|
||||
while (dir == 0) {
|
||||
dir = randomRangeInt(-1, 2);
|
||||
}
|
||||
const force = new Vec2(dir, 1);
|
||||
ball.addFocre(force.multiply2f(1, 50));
|
||||
return ball;
|
||||
}
|
||||
|
||||
public async ballOut(ball: Node) {
|
||||
this._balls--;
|
||||
if (this._balls === 0) {
|
||||
return;
|
||||
}
|
||||
this._ballPool.release(ball);
|
||||
await Utilities.delay(1000);
|
||||
// this.spawnBall();
|
||||
}
|
||||
|
||||
public onRevive() {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
|
|
@ -38,10 +38,10 @@ export class SoundManager extends Component {
|
|||
//singleton
|
||||
private static _instance: SoundManager;
|
||||
public static get instance(): SoundManager {
|
||||
if (SoundManager._instance) {
|
||||
if (!SoundManager._instance) {
|
||||
SoundManager._instance = new SoundManager('SoundManager');
|
||||
}
|
||||
return SoundManager.instance;
|
||||
return SoundManager._instance;
|
||||
}
|
||||
|
||||
private _audioSourcesSfx: { [key: string]: SoundSource } = {};
|
||||
|
|
|
@ -33,7 +33,6 @@ export default class ObjectPool {
|
|||
|
||||
public get(parent?: Node): Node;
|
||||
public get<T extends Component>(parent?: Node, classConstructor?: new () => T): T;
|
||||
|
||||
public get<T extends Component>(parent?: Node, classConstructor?: new () => T): T | Node {
|
||||
let obj: Node = null;
|
||||
let p = parent || director.getScene();
|
||||
|
|
Loading…
Reference in New Issue