feat: update game event manager
parent
4d97fc35ea
commit
136a898942
|
@ -962,12 +962,16 @@
|
||||||
"__prefab": {
|
"__prefab": {
|
||||||
"__id__": 70
|
"__id__": 70
|
||||||
},
|
},
|
||||||
"rigidbody": {
|
"_rigidbody": {
|
||||||
"__id__": 67
|
"__id__": 67
|
||||||
},
|
},
|
||||||
"collider": {
|
"_collider": {
|
||||||
"__id__": 65
|
"__id__": 65
|
||||||
},
|
},
|
||||||
|
"_hitSound": {
|
||||||
|
"__uuid__": "6a432293-3852-4267-be19-c671f36fe9f0",
|
||||||
|
"__expectedType__": "cc.AudioClip"
|
||||||
|
},
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,6 @@
|
||||||
enum GameEvent {}
|
enum GameEvent {
|
||||||
|
GameStateChange,
|
||||||
|
BallHit,
|
||||||
|
}
|
||||||
|
|
||||||
export default GameEvent;
|
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 {
|
import {
|
||||||
_decorator,
|
_decorator,
|
||||||
|
AudioClip,
|
||||||
CCFloat,
|
CCFloat,
|
||||||
Collider2D,
|
Collider2D,
|
||||||
Component,
|
Component,
|
||||||
|
@ -9,52 +10,64 @@ import {
|
||||||
EventTarget,
|
EventTarget,
|
||||||
IPhysics2DContact,
|
IPhysics2DContact,
|
||||||
RigidBody2D,
|
RigidBody2D,
|
||||||
|
Vec2,
|
||||||
} from 'cc';
|
} from 'cc';
|
||||||
import IPoolable from '../Pool/IPoolable';
|
import IPoolable from '../Pool/IPoolable';
|
||||||
import Utilities from '../Utilities/Utilities';
|
import { SoundManager } from '../Manager/SoundManager';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ccclass('Ball')
|
@ccclass('Ball')
|
||||||
export class Ball extends Component implements IPoolable {
|
export class Ball extends Component implements IPoolable {
|
||||||
@property({ visible: true, type: CCFloat })
|
@property({ type: CCFloat, visible: true })
|
||||||
public maxSpeed: number;
|
private _maxSpeed: number;
|
||||||
@property({ visible: true, type: RigidBody2D })
|
@property({ type: RigidBody2D, visible: true })
|
||||||
public rigidbody: RigidBody2D;
|
private _rigidbody: RigidBody2D;
|
||||||
@property(Collider2D)
|
@property({ type: Collider2D, visible: true })
|
||||||
public collider: Collider2D;
|
private _collider: Collider2D;
|
||||||
public isActive: boolean;
|
@property({ type: AudioClip, visible: true })
|
||||||
private hitted = false;
|
private _hitSound: AudioClip;
|
||||||
|
|
||||||
|
private _hitted = false;
|
||||||
|
|
||||||
public eventHitObstacle = new EventTarget();
|
public eventHitObstacle = new EventTarget();
|
||||||
public eventGoal = new EventTarget();
|
public eventGoal = new EventTarget();
|
||||||
|
|
||||||
protected onLoad(): void {
|
protected onLoad(): void {
|
||||||
if (this.getComponent(Collider2D)) {
|
if (this._collider) {
|
||||||
this.collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
|
this._collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
|
||||||
this.collider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
|
this._collider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
director.on(Director.EVENT_AFTER_PHYSICS, this.setMaxVelocity, 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() {
|
private setMaxVelocity() {
|
||||||
if (this.rigidbody.linearVelocity.length() > this.maxSpeed) {
|
if (this._rigidbody.linearVelocity.length() > this._maxSpeed) {
|
||||||
this.rigidbody.linearVelocity = this.rigidbody.linearVelocity.normalize().multiplyScalar(this.maxSpeed);
|
this._rigidbody.linearVelocity = this._rigidbody.linearVelocity.normalize().multiplyScalar(this._maxSpeed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onEndContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
|
private onEndContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
|
||||||
// console.log(otherCollider.tag, otherCollider.node.name);
|
// console.log(otherCollider.tag, otherCollider.node.name);
|
||||||
this.hitted = false;
|
this._hitted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
reuse() {
|
public addFocre(force: Vec2) {
|
||||||
console.log('use');
|
const point = this.node.getWorldPosition();
|
||||||
|
this._rigidbody.applyLinearImpulse(force, new Vec2(point.x, point.y), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reuse() {}
|
||||||
|
|
||||||
unuse() {
|
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 GameEvent from '../Enum/GameEvent';
|
||||||
|
import { GameEventArgMap, GameEventCallbackMap } from '../Interface/GameEventMap';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ccclass('EventManger')
|
@ccclass('EventManger')
|
||||||
|
@ -21,15 +22,27 @@ export class EventManger extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public on(eventType: GameEvent, callback?: (...args: any[]) => void, thisArg?: any) {
|
public on<K extends keyof GameEventCallbackMap>(
|
||||||
this._eventTarget.on(eventType, callback, thisArg);
|
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) {
|
public off<K extends keyof GameEventCallbackMap>(
|
||||||
this._eventTarget.on(eventType, callback, thisArg);
|
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) {
|
public emit<K extends keyof GameEventArgMap>(eventType: K, arg: GameEventArgMap[K]) {
|
||||||
this._eventTarget.emit(eventType, arg0, arg1, arg2, arg3, arg4);
|
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 ObjectPool from '../Pool/ObjectPool';
|
||||||
import { Ball } from '../Gameplay/Ball';
|
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;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ccclass('GameManager')
|
@ccclass('GameManager')
|
||||||
|
@ -13,15 +17,54 @@ export class GameManager extends Component {
|
||||||
|
|
||||||
@property({ type: Prefab, visible: true })
|
@property({ type: Prefab, visible: true })
|
||||||
private _ballPrefab: Prefab;
|
private _ballPrefab: Prefab;
|
||||||
|
@property({ type: Vec3, visible: true })
|
||||||
|
private _ballSpawnPosition: Vec3;
|
||||||
|
@property({ type: CCInteger, visible: true })
|
||||||
|
private _balls = 3;
|
||||||
|
|
||||||
private _ballPool: ObjectPool;
|
private _ballPool: ObjectPool;
|
||||||
|
private _gameState = GameState.Init;
|
||||||
|
|
||||||
public highestStreak: number;
|
public highestStreak: number;
|
||||||
public score = 0;
|
public score = 0;
|
||||||
|
|
||||||
protected onLoad(): void {
|
protected onLoad(): void {
|
||||||
|
GameManager._instance = this;
|
||||||
this._ballPool = new ObjectPool(this._ballPrefab, 10, false, Ball);
|
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() {
|
public onRevive() {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,10 +38,10 @@ export class SoundManager extends Component {
|
||||||
//singleton
|
//singleton
|
||||||
private static _instance: SoundManager;
|
private static _instance: SoundManager;
|
||||||
public static get instance(): SoundManager {
|
public static get instance(): SoundManager {
|
||||||
if (SoundManager._instance) {
|
if (!SoundManager._instance) {
|
||||||
SoundManager._instance = new SoundManager('SoundManager');
|
SoundManager._instance = new SoundManager('SoundManager');
|
||||||
}
|
}
|
||||||
return SoundManager.instance;
|
return SoundManager._instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _audioSourcesSfx: { [key: string]: SoundSource } = {};
|
private _audioSourcesSfx: { [key: string]: SoundSource } = {};
|
||||||
|
|
|
@ -33,7 +33,6 @@ export default class ObjectPool {
|
||||||
|
|
||||||
public get(parent?: Node): Node;
|
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;
|
||||||
|
|
||||||
public get<T extends Component>(parent?: Node, classConstructor?: new () => T): T | Node {
|
public get<T extends Component>(parent?: Node, classConstructor?: new () => T): T | Node {
|
||||||
let obj: Node = null;
|
let obj: Node = null;
|
||||||
let p = parent || director.getScene();
|
let p = parent || director.getScene();
|
||||||
|
|
Loading…
Reference in New Issue