feat: update gameplay

main
tiendat3699 2024-03-11 18:12:22 +07:00
parent 1c1aa7578e
commit d0f3716a8c
14 changed files with 1647 additions and 209 deletions

View File

@ -0,0 +1,37 @@
{
"__type__": "cc.Material",
"_name": "",
"_objFlags": 0,
"_native": "",
"_effectAsset": {
"__uuid__": "d1346436-ac96-4271-b863-1f4fdead95b0",
"__expectedType__": "cc.EffectAsset"
},
"_techIdx": 0,
"_defines": [
{}
],
"_states": [
{
"stage": 200,
"rasterizerState": {},
"depthStencilState": {},
"blendState": {
"targets": [
{}
]
}
}
],
"_props": [
{
"tintColor": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
}
}
]
}

View File

@ -0,0 +1 @@
{"ver":"1.0.20","importer":"material","imported":true,"uuid":"08b0dafd-3f2c-4d0f-a9ec-edf75ca0a191","files":[".json"],"subMetas":{},"userData":{}}

View File

@ -1082,7 +1082,7 @@
"_density": 1, "_density": 1,
"_sensor": false, "_sensor": false,
"_friction": 2, "_friction": 2,
"_restitution": 0.5, "_restitution": 0.2,
"_offset": { "_offset": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
"x": 0, "x": 0,
@ -1144,7 +1144,7 @@
"__uuid__": "e4f226d3-8b68-42b8-8bf0-490b8d5765c4", "__uuid__": "e4f226d3-8b68-42b8-8bf0-490b8d5765c4",
"__expectedType__": "cc.Prefab" "__expectedType__": "cc.Prefab"
}, },
"_maxSpeed": 100, "_maxSpeed": 70,
"_rigidBody": { "_rigidBody": {
"__id__": 75 "__id__": 75
}, },

View File

@ -0,0 +1,758 @@
[
{
"__type__": "cc.Prefab",
"_name": "Buff Particle",
"_objFlags": 0,
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "Buff Particle",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [],
"_active": true,
"_components": [
{
"__id__": 2
},
{
"__id__": 4
},
{
"__id__": 6
}
],
"_prefab": {
"__id__": 61
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": -1384,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 25,
"y": 25,
"z": 1
},
"_mobility": 0,
"_layer": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UIMeshRenderer",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 3
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "f2H1iPRKtGVaUJQ0ZMk4hY"
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_contentSize": {
"__type__": "cc.Size",
"width": 100,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "5fjDdutO9HkqZsxXhpribt"
},
{
"__type__": "cc.ParticleSystem",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 7
},
"_materials": [
{
"__uuid__": "08b0dafd-3f2c-4d0f-a9ec-edf75ca0a191",
"__expectedType__": "cc.Material"
},
null
],
"_visFlags": 0,
"startColor": {
"__id__": 8
},
"scaleSpace": 1,
"startSize3D": true,
"startSizeX": {
"__id__": 9
},
"startSize": {
"__id__": 9
},
"startSizeY": {
"__id__": 10
},
"startSizeZ": {
"__id__": 11
},
"startSpeed": {
"__id__": 12
},
"startRotation3D": false,
"startRotationX": {
"__id__": 13
},
"startRotationY": {
"__id__": 14
},
"startRotationZ": {
"__id__": 15
},
"startRotation": {
"__id__": 15
},
"startDelay": {
"__id__": 16
},
"startLifetime": {
"__id__": 17
},
"duration": 5,
"loop": true,
"simulationSpeed": 1,
"playOnAwake": false,
"gravityModifier": {
"__id__": 18
},
"rateOverTime": {
"__id__": 19
},
"rateOverDistance": {
"__id__": 20
},
"bursts": [],
"_renderCulling": false,
"_cullingMode": 0,
"_aabbHalfX": 0,
"_aabbHalfY": 0,
"_aabbHalfZ": 0,
"_dataCulling": false,
"enableCulling": false,
"_colorOverLifetimeModule": {
"__id__": 21
},
"_shapeModule": {
"__id__": 23
},
"_sizeOvertimeModule": {
"__id__": 25
},
"_velocityOvertimeModule": {
"__id__": 30
},
"_forceOvertimeModule": {
"__id__": 35
},
"_limitVelocityOvertimeModule": {
"__id__": 39
},
"_rotationOvertimeModule": {
"__id__": 44
},
"_textureAnimationModule": {
"__id__": 48
},
"_noiseModule": {
"__id__": 52
},
"_trailModule": {
"__id__": 53
},
"renderer": {
"__id__": 60
},
"_prewarm": false,
"_capacity": 100,
"_simulationSpace": 1,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "b60TP4ZStBtZthYfiXRT3Q"
},
{
"__type__": "cc.GradientRange",
"_mode": 0,
"color": {
"__type__": "cc.Color",
"r": 255,
"g": 204,
"b": 0,
"a": 50
}
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0.5,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 3,
"constantMin": 1,
"constantMax": 10,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 1,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 2,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": -20,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 50,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.ColorOvertimeModule",
"_enable": false,
"color": {
"__id__": 22
}
},
{
"__type__": "cc.GradientRange",
"_mode": 0,
"color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
}
},
{
"__type__": "cc.ShapeModule",
"_enable": true,
"_shapeType": 0,
"shapeType": 0,
"emitFrom": 3,
"alignToDirection": false,
"randomDirectionAmount": 0,
"sphericalDirectionAmount": 0,
"randomPositionAmount": 0,
"radius": 1,
"radiusThickness": 1,
"arcMode": 0,
"arcSpread": 0,
"arcSpeed": {
"__id__": 24
},
"length": 5,
"boxThickness": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_position": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_rotation": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_scale": {
"__type__": "cc.Vec3",
"x": 80,
"y": 1,
"z": 1
},
"_arc": 6.283185307179586,
"_angle": 0.4363323129985824
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 1,
"multiplier": 1
},
{
"__type__": "cc.SizeOvertimeModule",
"_enable": false,
"separateAxes": false,
"size": {
"__id__": 26
},
"x": {
"__id__": 27
},
"y": {
"__id__": 28
},
"z": {
"__id__": 29
}
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.VelocityOvertimeModule",
"_enable": false,
"x": {
"__id__": 31
},
"y": {
"__id__": 32
},
"z": {
"__id__": 33
},
"speedModifier": {
"__id__": 34
},
"space": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 1,
"multiplier": 1
},
{
"__type__": "cc.ForceOvertimeModule",
"_enable": false,
"x": {
"__id__": 36
},
"y": {
"__id__": 37
},
"z": {
"__id__": 38
},
"space": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.LimitVelocityOvertimeModule",
"_enable": false,
"limitX": {
"__id__": 40
},
"limitY": {
"__id__": 41
},
"limitZ": {
"__id__": 42
},
"limit": {
"__id__": 43
},
"dampen": 3,
"separateAxes": false,
"space": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.RotationOvertimeModule",
"_enable": false,
"_separateAxes": false,
"x": {
"__id__": 45
},
"y": {
"__id__": 46
},
"z": {
"__id__": 47
}
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.TextureAnimationModule",
"_enable": false,
"_numTilesX": 0,
"numTilesX": 0,
"_numTilesY": 0,
"numTilesY": 0,
"_mode": 0,
"animation": 0,
"frameOverTime": {
"__id__": 49
},
"startFrame": {
"__id__": 51
},
"cycleCount": 0,
"_flipU": 0,
"_flipV": 0,
"_uvChannelMask": -1,
"randomRow": false,
"rowIndex": 0
},
{
"__type__": "cc.CurveRange",
"mode": 1,
"spline": {
"__id__": 50
},
"multiplier": 1
},
{
"__type__": "cc.RealCurve",
"_times": [
0,
1
],
"_values": [
{
"__type__": "cc.RealKeyframeValue",
"interpolationMode": 2,
"tangentWeightMode": 0,
"value": 1,
"rightTangent": 0,
"rightTangentWeight": 0,
"leftTangent": 0,
"leftTangentWeight": 0,
"easingMethod": 0,
"__editorExtras__": null
},
{
"__type__": "cc.RealKeyframeValue",
"interpolationMode": 2,
"tangentWeightMode": 0,
"value": 1,
"rightTangent": 0,
"rightTangentWeight": 0,
"leftTangent": 0,
"leftTangentWeight": 0,
"easingMethod": 0,
"__editorExtras__": null
}
],
"preExtrapolation": 1,
"postExtrapolation": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 0,
"multiplier": 1
},
{
"__type__": "cc.NoiseModule",
"_enable": false,
"_strengthX": 10,
"_strengthY": 10,
"_strengthZ": 10,
"_noiseSpeedX": 0,
"_noiseSpeedY": 0,
"_noiseSpeedZ": 0,
"_noiseFrequency": 1,
"_remapX": 0,
"_remapY": 0,
"_remapZ": 0,
"_octaves": 1,
"_octaveMultiplier": 0.5,
"_octaveScale": 2
},
{
"__type__": "cc.TrailModule",
"_enable": false,
"mode": 0,
"lifeTime": {
"__id__": 54
},
"_minParticleDistance": 0.1,
"existWithParticles": true,
"textureMode": 0,
"widthFromParticle": false,
"widthRatio": {
"__id__": 55
},
"colorFromParticle": false,
"colorOverTrail": {
"__id__": 56
},
"colorOvertime": {
"__id__": 57
},
"_space": 0,
"_particleSystem": {
"__id__": 6
}
},
{
"__type__": "cc.CurveRange",
"mode": 3,
"constantMin": 0,
"constantMax": 0.15,
"multiplier": 1
},
{
"__type__": "cc.CurveRange",
"mode": 0,
"constant": 10,
"multiplier": 50
},
{
"__type__": "cc.GradientRange",
"_mode": 0,
"color": {
"__type__": "cc.Color",
"r": 255,
"g": 250,
"b": 134,
"a": 221
}
},
{
"__type__": "cc.GradientRange",
"_mode": 1,
"gradient": {
"__id__": 58
}
},
{
"__type__": "cc.Gradient",
"colorKeys": [],
"alphaKeys": [
{
"__id__": 59
}
],
"mode": 0
},
{
"__type__": "cc.AlphaKey",
"alpha": 255,
"time": 0
},
{
"__type__": "cc.ParticleSystemRenderer",
"_renderMode": 0,
"_velocityScale": 1,
"_lengthScale": 1,
"_mesh": null,
"_cpuMaterial": {
"__uuid__": "08b0dafd-3f2c-4d0f-a9ec-edf75ca0a191",
"__expectedType__": "cc.Material"
},
"_gpuMaterial": null,
"_mainTexture": null,
"_useGPU": false,
"_alignSpace": 2
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "d6MYHCymBFRbEj0OPlLt9v",
"instance": null,
"targetOverrides": null
}
]

View File

@ -0,0 +1,13 @@
{
"ver": "1.1.43",
"importer": "prefab",
"imported": true,
"uuid": "c7549312-ab7b-4974-8863-1a55c119c34f",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "Buff Particle"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@ import {
import { EventManger } from '../Manager/EventManger'; import { EventManger } from '../Manager/EventManger';
import GameEvent from '../Events/GameEvent'; import GameEvent from '../Events/GameEvent';
import ScoreType from '../Enum/ScoreType'; import ScoreType from '../Enum/ScoreType';
import GameState from '../Enum/GameState';
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
@ccclass('Enemy') @ccclass('Enemy')
@ -47,16 +48,25 @@ export class Enemy extends Component {
protected onLoad(): void { protected onLoad(): void {
EventManger.instance.on(GameEvent.Score, this.onScore, this); EventManger.instance.on(GameEvent.Score, this.onScore, this);
EventManger.instance.on(GameEvent.GameStateChange, this.onGameStateChange, this);
this._collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); this._collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
} }
protected async start() { protected start(): void {
this.init();
}
protected async init() {
this._collider.node.setWorldPosition(this._patrolPoint1.worldPosition); this._collider.node.setWorldPosition(this._patrolPoint1.worldPosition);
const pos = this._patrolPoint1.getWorldPosition(); const pos = this._patrolPoint1.getWorldPosition();
this.x = pos.x; this.x = pos.x;
this.y = pos.y; this.y = pos.y;
this._distance = Math.abs(this._patrolPoint2.worldPosition.x - this.x); this._distance = Math.abs(this._patrolPoint2.worldPosition.x - this.x);
this._direction = this._patrolPoint1.worldPosition.x < this._patrolPoint2.worldPosition.x ? 1 : -1; this._direction = this._patrolPoint1.worldPosition.x < this._patrolPoint2.worldPosition.x ? 1 : -1;
this._processDistance = 0;
this._currentGoal = 0;
this._isActive = false;
this._collider.node.active = false; this._collider.node.active = false;
} }
@ -115,4 +125,16 @@ export class Enemy extends Component {
} }
} }
} }
private onGameStateChange(state: GameState) {
switch (state) {
case GameState.Init:
break;
case GameState.Playing:
break;
case GameState.GameOver:
this.init();
break;
}
}
} }

View File

@ -10,6 +10,7 @@ import {
Director, Director,
director, director,
AudioClip, AudioClip,
Label,
} from 'cc'; } from 'cc';
import ObjectPool from '../Pool/ObjectPool'; import ObjectPool from '../Pool/ObjectPool';
import { Ball } from '../GamePlay/Ball'; import { Ball } from '../GamePlay/Ball';
@ -39,7 +40,7 @@ export class GameManager extends Component {
@property({ visible: true }) @property({ visible: true })
private _ballSpawnPosition: Vec3; private _ballSpawnPosition: Vec3;
@property({ type: CCInteger, visible: true }) @property({ type: CCInteger, visible: true })
private _balls = 3; private readonly _ballsInit = 3;
@property({ type: AudioClip, visible: true }) @property({ type: AudioClip, visible: true })
private _startSound: AudioClip; private _startSound: AudioClip;
@property({ type: AudioClip, visible: true }) @property({ type: AudioClip, visible: true })
@ -48,10 +49,12 @@ export class GameManager extends Component {
private _ballPool: ObjectPool; private _ballPool: ObjectPool;
private _FloatingScorePool: ObjectPool; private _FloatingScorePool: ObjectPool;
private _gameState: GameState; private _gameState: GameState;
private _balls: number;
public get balls() { public get balls() {
return this._balls; return this._ballsInit;
} }
private _score = 0; private _score = 0;
private _isMultiBall = false; private _isMultiBall = false;
private _currentBallInGame = 0; private _currentBallInGame = 0;
@ -143,6 +146,7 @@ export class GameManager extends Component {
} }
public async play() { public async play() {
this._balls = this._ballsInit;
SoundManager.instance.playBGM(this._backgroundMusic, 0.5); SoundManager.instance.playBGM(this._backgroundMusic, 0.5);
this.changeGameState(GameState.Playing); this.changeGameState(GameState.Playing);
await Utilities.delay(1000); await Utilities.delay(1000);
@ -150,7 +154,7 @@ export class GameManager extends Component {
} }
public async restart() { public async restart() {
this._balls = 3; this._balls = this._ballsInit;
this._score = 0; this._score = 0;
this._currentBallInGame = 0; this._currentBallInGame = 0;
this._isMultiBall = false; this._isMultiBall = false;

View File

@ -83,9 +83,15 @@ export class SoundManager extends Component {
public playSfx(audioClip: AudioClip, volume = 1, loop = false) { public playSfx(audioClip: AudioClip, volume = 1, loop = false) {
let soundSource = this._audioSourcesSfx[audioClip.uuid]; let soundSource = this._audioSourcesSfx[audioClip.uuid];
if (soundSource) { if (soundSource) {
soundSource.volume = volume; soundSource.volume = volume;
soundSource.source.loop = loop; soundSource.source.loop = loop;
if (loop) return;
if (soundSource.source.playing) {
soundSource.source.playOneShot(audioClip, this.isMute ? 0 : volume);
return;
}
soundSource.play(); soundSource.play();
return; return;
} }

View File

@ -0,0 +1,35 @@
import { AudioClip, AudioSource, Pool } from 'cc';
import Utilities from '../Utilities';
export class SoundSource {
private _pool: Pool<AudioSource>;
public volume = 1;
public mute = false;
public clip: AudioClip;
private _currentAudioSource: AudioSource;
constructor() {
this._pool = new Pool<AudioSource>(
() => {
const source = new AudioSource();
source.playOnAwake = false;
return source;
},
10,
(obj) => obj.destroy(),
);
}
public async play() {
this._currentAudioSource = this._pool.alloc();
this._currentAudioSource.volume = this.mute ? 0 : this.volume;
_currentAudioSource.clip = this.clip;
_currentAudioSource.play();
await Utilities.waitUntil(() => !source.playing);
this._pool.free(source);
}
public stop() {
this._currentAudioSource.stop();
}
}

View File

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "9f4eb11d-f1a9-42b3-a388-5c9e48c87851",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@ -3,6 +3,8 @@ import ObjectPool from '../Pool/ObjectPool';
import { ScoreObject } from '../Environments/ScoreObject'; import { ScoreObject } from '../Environments/ScoreObject';
import { EventManger } from './EventManger'; import { EventManger } from './EventManger';
import GameEvent from '../Events/GameEvent'; import GameEvent from '../Events/GameEvent';
import GameState from '../Enum/GameState';
import Utilities from '../Utilities';
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
@ccclass('SpawnObjectManager') @ccclass('SpawnObjectManager')
@ -23,11 +25,13 @@ export class SpawnObjectManager extends Component {
private _pools: ObjectPool[] = []; private _pools: ObjectPool[] = [];
private _usedPoints: { [key: string]: Node } = {}; private _usedPoints: { [key: string]: Node } = {};
private _playing = false;
private _timer = 0; private _timer = 0;
protected onLoad(): void { protected onLoad(): void {
SpawnObjectManager._instance = this; SpawnObjectManager._instance = this;
EventManger.instance.on(GameEvent.ScoreObjectRelease, this.onObjectRelease, this); EventManger.instance.on(GameEvent.ScoreObjectRelease, this.onObjectRelease, this);
EventManger.instance.on(GameEvent.GameStateChange, this.onGameStateChange, this);
for (let i = 0; i < this._objects.length; i++) { for (let i = 0; i < this._objects.length; i++) {
const prefab = this._objects[i]; const prefab = this._objects[i];
@ -35,13 +39,8 @@ export class SpawnObjectManager extends Component {
} }
} }
protected start(): void {
for (let i = 0; i < randomRangeInt(5, 10); i++) {
this.spawn();
}
}
protected update(dt: number): void { protected update(dt: number): void {
if (!this._playing) return;
this._timer += dt; this._timer += dt;
if (this._timer >= this._spawnTime) { if (this._timer >= this._spawnTime) {
this._timer = 0; this._timer = 0;
@ -63,4 +62,21 @@ export class SpawnObjectManager extends Component {
private onObjectRelease(obj: Node) { private onObjectRelease(obj: Node) {
delete this._usedPoints[obj.uuid]; delete this._usedPoints[obj.uuid];
} }
private onGameStateChange(state: GameState) {
switch (state) {
case GameState.Init:
break;
case GameState.Playing:
this._playing = true;
for (let i = 0; i < randomRangeInt(5, 10); i++) {
this.spawn();
}
break;
case GameState.GameOver:
this._playing = false;
this._pools.forEach((pool) => pool.releaseAll());
break;
}
}
} }

View File

@ -2,14 +2,18 @@ import { Component, Node, Prefab, director, instantiate } from 'cc';
import IPoolable from './IPoolable'; import IPoolable from './IPoolable';
export default class ObjectPool { export default class ObjectPool {
private _inactives: Node[] = []; private _inactive: Node[] = [];
private _actives: Node[] = []; private _actives: Node[] = [];
private _prefab: Prefab; private _prefab: Prefab;
private _expandable; private _expandable;
private _poolHandlerComp: new () => any; private _poolHandlerComp: new () => any;
private get all() {
return [...this._actives, ...this._inactive];
}
public get countInactive() { public get countInactive() {
return this._inactives.length; return this._inactive.length;
} }
public get countActive() { public get countActive() {
@ -27,7 +31,7 @@ export default class ObjectPool {
for (let i = 0; i < size; ++i) { for (let i = 0; i < size; ++i) {
let obj = instantiate(this._prefab); // create node instance let obj = instantiate(this._prefab); // create node instance
obj.removeFromParent(); obj.removeFromParent();
this._inactives.push(obj); this._inactive.push(obj);
ObjectPool._poolLookUp[obj.uuid] = this; ObjectPool._poolLookUp[obj.uuid] = this;
} }
} }
@ -44,9 +48,9 @@ export default class ObjectPool {
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();
if (this._inactives.length > 0) { if (this._inactive.length > 0) {
// Pop the last object in pool // Pop the last object in pool
obj = this._inactives.pop(); obj = this._inactive.pop();
} else if (this._expandable) { } else if (this._expandable) {
// if not enough node in the pool, we call cc.instantiate to create node // if not enough node in the pool, we call cc.instantiate to create node
obj = instantiate(this._prefab); obj = instantiate(this._prefab);
@ -74,10 +78,11 @@ export default class ObjectPool {
public release<T extends Component>(obj: T | Node): void { public release<T extends Component>(obj: T | Node): void {
let node = obj instanceof Node ? obj : obj.node; let node = obj instanceof Node ? obj : obj.node;
const index = this._actives.indexOf(node); const index = this._actives.indexOf(node);
//check obj is belongs to pool //check obj is belongs to pool
if (index === -1) return; if (index === -1) return;
this._actives.splice(index, 1); this._actives.splice(index, 1);
this._inactives.push(node); this._inactive.push(node);
// Invoke pool handler // Invoke pool handler
const handler = this._poolHandlerComp ? node.getComponent(this._poolHandlerComp) : null; const handler = this._poolHandlerComp ? node.getComponent(this._poolHandlerComp) : null;
@ -89,8 +94,8 @@ export default class ObjectPool {
} }
public clear() { public clear() {
this._inactives.forEach((obj) => obj.destroy()); this.all.forEach((obj) => obj.destroy());
this._inactives = []; this._inactive = [];
this._actives = []; this._actives = [];
Object.keys(ObjectPool._poolLookUp).forEach((key) => { Object.keys(ObjectPool._poolLookUp).forEach((key) => {
if (ObjectPool._poolLookUp[key] === this) { if (ObjectPool._poolLookUp[key] === this) {
@ -98,4 +103,8 @@ export default class ObjectPool {
} }
}); });
} }
public releaseAll() {
this.all.forEach((obj) => this.release(obj));
}
} }

View File

@ -1,4 +1,4 @@
import { _decorator, Component, Label, Node, tween } from 'cc'; import { _decorator, Component, Label, Node, ParticleSystem, tween } from 'cc';
import { EventManger } from '../Manager/EventManger'; import { EventManger } from '../Manager/EventManger';
import GameEvent from '../Events/GameEvent'; import GameEvent from '../Events/GameEvent';
import ScoreType from '../Enum/ScoreType'; import ScoreType from '../Enum/ScoreType';
@ -17,18 +17,34 @@ export class UIController extends Component {
private _goalLabel: Label; private _goalLabel: Label;
@property({ type: Label, visible: true }) @property({ type: Label, visible: true })
private _resultLabel: Label; private _resultLabel: Label;
@property({ type: ParticleSystem, visible: true })
private _buffFx: ParticleSystem;
@property({ type: Node, visible: true }) @property({ type: Node, visible: true })
private _startPanel: Node; private _startPanel: Node;
@property({ type: Node, visible: true }) @property({ type: Node, visible: true })
private _overPanel: Node; private _overPanel: Node;
@property({ type: Label, visible: true })
private _timeLabe: Label;
@property({ type: Label, visible: true })
private _timeResult: Label;
private _timer = 0;
private _playing = false;
protected onLoad(): void { protected onLoad(): void {
EventManger.instance.on(GameEvent.Score, this.onScore, this); EventManger.instance.on(GameEvent.Score, this.onScore, this);
EventManger.instance.on(GameEvent.BallOut, this.onBallOut, this); EventManger.instance.on(GameEvent.BallOut, this.onBallOut, this);
EventManger.instance.on(GameEvent.GameStateChange, this.onGameStateChange, this); EventManger.instance.on(GameEvent.GameStateChange, this.onGameStateChange, this);
EventManger.instance.on(GameEvent.MultiBall, this.onMultiBall, this);
this._goalLabel.string = ''; this._goalLabel.string = '';
} }
protected update(dt: number): void {
if (this._playing) {
this._timer += dt;
this._timeLabe.string = this.secondsToTime(this._timer);
}
}
private async onScore(score: number, type: ScoreType) { private async onScore(score: number, type: ScoreType) {
this._scoreLabel.string = `Score: ${score}`; this._scoreLabel.string = `Score: ${score}`;
if (type == ScoreType.Goal) { if (type == ScoreType.Goal) {
@ -51,15 +67,38 @@ export class UIController extends Component {
this._startPanel.active = true; this._startPanel.active = true;
break; break;
case GameState.Playing: case GameState.Playing:
this._playing = true;
this._scoreLabel.string = 'Score: 0'; this._scoreLabel.string = 'Score: 0';
this._ballLabel.string = `Ball: ${GameManager.instance.balls}`; this._ballLabel.string = `Ball: ${GameManager.instance.balls}`;
this._startPanel.active = false; this._startPanel.active = false;
this._overPanel.active = false; this._overPanel.active = false;
break; break;
case GameState.GameOver: case GameState.GameOver:
this._playing = false;
this._overPanel.active = true; this._overPanel.active = true;
this._resultLabel.string = this._scoreLabel.string; this._resultLabel.string = this._scoreLabel.string;
this._timeResult.string = this._timeLabe.string;
this._timer = 0;
break; break;
} }
} }
private onMultiBall(active: boolean) {
if (active) this._buffFx.play();
else this._buffFx.stop();
}
private secondsToTime(second: number) {
const h = Math.floor(second / 3600)
.toString()
.padStart(2, '0'),
m = Math.floor((second % 3600) / 60)
.toString()
.padStart(2, '0'),
s = Math.floor(second % 60)
.toString()
.padStart(2, '0');
return h + ':' + m + ':' + s;
}
} }