import { _decorator, assetManager, Component, director, Label, Node, PhysicsSystem, Vec3, Animation, Prefab, instantiate, tween } from 'cc'; import { RoundBall } from './RoundBall'; import { PlayerController } from './PlayerController'; import { resLoader } from 'db://assets/core_tgx/base/utils/ResLoader'; import { ModuleDef } from 'db://assets/scripts/ModuleDef'; import { tgxUIAlert } from 'db://assets/core_tgx/tgx'; import { AreanNetMgr } from '../../scripts/AreanNetMgr'; const { ccclass, property } = _decorator; enum GameState { Playing, Paused, GameOver } @ccclass('BallGame') export class BallGame extends Component { /** * 游戏结束 */ private _isGameOver: boolean = false; @property({ type: Node }) guiNode: Node | null = null; public get isGameOver(): boolean { return this._isGameOver; } myBallNum: number = 10; opBallNum: number = 10; deadBallNum: number = 0; rndBallNum: number = 0; @property({ type: PlayerController, displayName: "角色控制" }) playerCtrl: PlayerController | null = null; @property({ type: RoundBall, displayName: "球控制" }) ballCtrl: RoundBall | null = null; @property({ type: Node, displayName: "游戏结束界面" }) gameOverScreen: Node | null = null; @property({ type: Label, displayName: "我方弹珠数量" }) myBallNumLabel: Label | null = null; @property({ type: Label, displayName: "对方弹珠数量" }) opBallNumLabel: Label | null = null; @property({ type: Label, displayName: "放置弹珠数量" }) rndBallNumLabel: Label | null = null; @property({ type: Label, displayName: "击中弹珠数量" }) deadBallNumLabel: Label | null = null; @property(Node) PlaneNode: Node = null; @property(Animation) startAnim: Animation = null!; private gameState: GameState = GameState.Playing; start() { this.initPhysics(); this.initGameState(); this.playStartAnimation(); } private initPhysics() { const physics = PhysicsSystem.instance; physics.enable = true; physics.gravity = new Vec3(0, -10, 0); physics.allowSleep = false; } private initGameState() { this.myBallNum = 10; this.opBallNum = 10; this.deadBallNum = 0; this.rndBallNum = 0; this.gameOverScreen!.active = false; this.PlaneNode.active = false; } private playStartAnimation() { if (this.startAnim) { this.startAnim.play("camera1"); this.startAnim.once(Animation.EventType.FINISHED, this.onStartAnimFinished, this); } } private onStartAnimFinished() { this.PlaneNode.active = true; } AddBall() { console.log("添加球"); if (this.playerCtrl) { this.playerCtrl.AddBall(); } } public setGameOver(isWin: boolean) { if (!isWin) { resLoader.load(ModuleDef.Arean, 'common/prefabs/settlement', (err: Error | null, prefab: Prefab) => { if (!err && prefab) { const n = instantiate(prefab); this.guiNode.addChild(n); n.getComponent(Animation).play("showLose"); } }); } else { resLoader.load(ModuleDef.Arean, 'common/prefabs/settlement', (err: Error | null, prefab: Prefab) => { if (!err && prefab) { const n = instantiate(prefab); this.guiNode.addChild(n); n.getComponent(Animation).play("showWin"); } }); } this.scheduleOnce(() => { resLoader.load(ModuleDef.Arean, 'common/prefabs/settlement', (err: Error | null, prefab: Prefab) => { if (!err && prefab) { const n = instantiate(prefab); this.guiNode.addChild(n); n.getComponent(Animation).play("showSettlement"); // Lives从10滚动到8 const livesLabel = n.getChildByPath("settlementNode/Node/lives").getComponent(Label); let lives = { value: 36 }; tween(lives) .to(1, { value: 10 }, { easing: 'linear', onUpdate: () => { livesLabel.string = Math.floor(lives.value).toString(); } }) .start(); // Money从400w滚动到480w const moneyLabel = n.getChildByPath("settlementNode/Node/money").getComponent(Label); let money = { value: 300 }; tween(money) .to(1, { value: 400 }, { easing: 'linear', onUpdate: () => { moneyLabel.string = Math.floor(money.value) + "w"; } }) .start(); n.getChildByPath("settlementNode/btnOK/label").getComponent(Label).string = isWin ? "NEXT" : "QUIT"; n.getChildByPath("settlementNode/btnOK").on(Node.EventType.TOUCH_START, () => { if (isWin) { director.loadScene("lobby_arean"); } else { director.loadScene("lobby_arean"); } }); } }); }, 3); } public RestartGame() { this.myBallNum = 10; this.opBallNum = 10; this.deadBallNum = 0; this.rndBallNum = 0; this.refreshBallNum(); if (this.playerCtrl) { this.playerCtrl.resetGame(); } if (this.ballCtrl) { this.ballCtrl.resetGame(); } this.gameOverScreen!.active = false; } // update(deltaTime: number) { // if (this.playerCtrl) { // if (this.playerCtrl.IsMoveEnd()) { // if (this.ballCtrl && this.ballCtrl.isMoveEnd()) { // console.log("球移动结束"); // if (this.playerCtrl.AddBallEnd()) { // this.setGameOver(this.ballCtrl.isbegin); // this.RestGame(); // } else { // if (this.ballCtrl.isbegin) { // this.setGameOver(this.ballCtrl.isbegin); // this.RestGame(); // } // } // } // } // } // } public refreshBallNum() { scrollLabelToNumber(this.myBallNumLabel!, this.myBallNum); scrollLabelToNumber(this.opBallNumLabel!, this.opBallNum); scrollLabelToNumber(this.deadBallNumLabel!, this.deadBallNum); scrollLabelToNumber(this.rndBallNumLabel!, this.rndBallNum); } changeGameScene() { var bundle = assetManager.getBundle('level1'); if (bundle) { director.loadScene("scene/level1Scene"); } else { assetManager.loadBundle("level1", () => { director.loadScene("scene/level1Scene"); }) } } onClickBtnQuit() { tgxUIAlert.show(`是否确认退出 ? `, true).onClick(async b => { if (b) { AreanNetMgr.inst.sendMsg_exit(); } }); } } function scrollLabelToNumber(label: Label, targetNumber: number, duration: number = 0.3) { const startNumber = parseInt(label.string); // 获取当前 Label 上的数字 const startTime = Date.now(); // 记录开始时间 const updateNumber = () => { // 计算已经过去的时间比例 const elapsedTime = (Date.now() - startTime) / (duration * 1000); const progress = Math.min(elapsedTime, 1); // 限制在 [0, 1] 范围内 // 计算当前数字 const currentNumber = Math.round(startNumber + (targetNumber - startNumber) * progress); // 更新显示的数字 label.string = currentNumber.toString(); // 如果动画未结束,继续更新数字 if (progress < 1) { requestAnimationFrame(updateNumber); } }; // 开始更新数字 updateNumber(); }