// Learn TypeScript: // - https://docs.cocos.com/creator/manual/en/scripting/typescript.html // Learn Attribute: // - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html // Learn life-cycle callbacks: // - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html import { SaveDataManager } from "../component/SaveDataManager"; import { GlobalEvent, tMgr, WindowName } from "../Global"; import { BattleEvent, getGlobalNode, UserSkill } from "../kernel/battle/BattleConst"; import { BattleManager } from "../kernel/battle/BattleManager"; import { MapView } from "../kernel/battle/map/MapView"; import { PhysicsControl } from "../kernel/physics/PhysicsControl"; import { IntroTableMgr } from "../kernel/table/IntroTableMgr"; import { GamePlayTable, TableName } from "../kernel/table/TableDefine"; import Ball from "../prefabs/Ball"; import { UIManager } from "../ui/UIManager"; import UIBattle from "../ui/uiView/UIBattle"; import { UITitleData } from "../ui/uiView/UITitleData"; const { ccclass, property } = cc._decorator; @ccclass export default class BattleScene extends cc.Component { @property(cc.Prefab) prefabCollection: cc.Prefab = null; // private _diagonal: number = 0; private _gameRoot: cc.Node; private _mapView: MapView; get mapView(): MapView { return this._mapView; } private _pointerVec: cc.Vec2 = cc.v2(); private _ballWorldP: cc.Vec2 = cc.v2(); // private _endP: cc.Vec2 = cc.v2(); private _pointerNode: cc.Node; /**分裂炮节点 */ private _spliterNode: cc.Node; private _ballNumNode: cc.Node; private _hitPList: cc.Vec2[] = []; private _hitBallList: cc.Node[] = []; private _minShootDeg: number = 1; //#region LIFE-CYCLE CALLBACKS: onLoad() { this._gameRoot = this.node.getChildByName('GameRoot'); BattleManager.ins.eventNode.on(BattleEvent.ROUND_END, this.onRoundEnd, this); BattleManager.ins.eventNode.on(BattleEvent.SKILL_START, this.onSkillStart, this); BattleManager.ins.eventNode.on(BattleEvent.SKILL_END, this.onSkillEnd, this); BattleManager.ins.eventNode.on(BattleEvent.BORN_POS_CHANGE, this.onBornPosChange, this); this._minShootDeg = (tMgr.getConfig(TableName.GAME_PLAY, 10) as GamePlayTable).Value; } protected onEnable(): void { this._gameRoot.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this); UIManager.ins.widgetLayer.active = false; this.schedule(this.onLazyUpdate, 1 / 20); //预加载弹窗 cc.resources.preload([WindowName.BATTLE_RESULT, WindowName.USER_SKILL_INFO, WindowName.BATTLE_RESULT_PRE_ANI], cc.Prefab); getGlobalNode().on(GlobalEvent.SHAKE, this.onShake, this); } protected onDisable(): void { this._gameRoot.off(cc.Node.EventType.TOUCH_START, this.onTouchStart, this); this.unschedule(this.onLazyUpdate); } protected onDestroy(): void { BattleManager.ins.eventNode.targetOff(this); getGlobalNode().targetOff(this); // BattleManager.ins.eventNode.on(BattleEvent.SKILL_START, this.onSkillStart, this); } start() { this._gameRoot.getComponent(cc.Widget).updateAlignment(); //第二次进场景时 widiget没有更新,手动更新下 // this._diagonal = Math.sqrt(this._gameRoot.width * this._gameRoot.width + this._gameRoot.height * this._gameRoot.height); //对角线长 if (UITitleData.id == 0) { BattleManager.ins.startBattle(0, this.onMapLoaded, this, this.prefabCollection); } else { BattleManager.ins.startBattle(UITitleData.id, this.onMapLoaded, this, this.prefabCollection); } let introConfig = IntroTableMgr.ins.getTableByLevel(UITitleData.id); if (introConfig) { //需要弹提示 UIManager.ins.openWindow(WindowName.INTRO, introConfig.Level); } else { //不需要弹提示,且未使用黄金瞄准期间,概率弹出黄金瞄准 if (Date.now() > SaveDataManager.ins.runtimeData.goldenAimEndTime) { let rate = (tMgr.getConfig(TableName.GAME_PLAY, 30) as GamePlayTable).Value; if (slib.MathUtil.getRandom(0, 100) < rate) { UIManager.ins.openWindow(WindowName.GOLDEN_AIM); } } } this._gameRoot.getChildByName('tips1').active = false; this._gameRoot.getChildByName('tips2').active = false; this._gameRoot.getChildByName('guideAim').active = false; if (UITitleData.id == 1 || UITitleData.id == 2) { //提示 this._gameRoot.getChildByName('tips1').active = true; this._gameRoot.getChildByName('tips2').active = true; this._gameRoot.getChildByName('guideAim').active = true; this._gameRoot.getChildByName('tips1').getComponent(cc.Label).string = (tMgr.getConfig(TableName.GAME_PLAY, 28) as GamePlayTable).Comment; this._gameRoot.getChildByName('tips2').getComponent(cc.Label).string = (tMgr.getConfig(TableName.GAME_PLAY, 29) as GamePlayTable).Comment; } } onLazyUpdate() { if (BattleManager.ins.curBattle) { if (BattleManager.ins.curBattle.roundRunning) { this._ballNumNode.getComponentInChildren(cc.Label).string = BattleManager.ins.curBattle.marblesCollectCount.toString(); } else { let rate = (BattleManager.ins.curBattle.doubleShoot ? 2 : 1); this._ballNumNode.getComponentInChildren(cc.Label).string = (BattleManager.ins.curBattle.marblesNum * rate).toString(); } } } // update (dt) {} //#endregion //#region public method //#endregion //#region private method private onMapLoaded() { this._mapView = BattleManager.ins.curBattle.mapView; let scale = this._gameRoot.width / this._mapView.width; this._mapView.setScale(scale, scale); // 按宽度缩放 this._mapView.setPosition(0, - this._gameRoot.height / 2 + this._mapView.height * scale / 2); //将 mapView和gameRoot底端对齐 BattleManager.ins.curBattle.scale = scale; this._gameRoot.addChild(this._mapView); this._spliterNode = this._gameRoot.getChildByName('spliter'); this._spliterNode.removeFromParent(); this._mapView.addChild(this._spliterNode); this._pointerNode = this._gameRoot.getChildByName('imgPointer'); this._pointerNode.removeFromParent(); this._mapView.addChild(this._pointerNode); this._ballNumNode = this._pointerNode.getChildByName('numNode'); if (UITitleData.id == 1 || UITitleData.id == 2) { //提示 let tips = this._gameRoot.getChildByName('tips1'); let gridPos = (UITitleData.id == 1 ? cc.v2(4, 5) : cc.v2(5, 7)); let pos = BattleManager.ins.curBattle.mapData.getPixelPosByGridPos(gridPos); this.mapView.convertToWorldSpaceAR(pos, pos); this._gameRoot.convertToNodeSpaceAR(pos, pos); tips.setPosition(pos); gridPos = (UITitleData.id == 1 ? cc.v2(7, 4) : cc.v2(10, 6)); pos = BattleManager.ins.curBattle.mapData.getPixelPosByGridPos(gridPos); this.mapView.convertToWorldSpaceAR(pos, pos); this._gameRoot.convertToNodeSpaceAR(pos, pos); this._gameRoot.getChildByName('guideAim').active = true; this._gameRoot.getChildByName('guideAim').setPosition(pos); } this.onRoundEnd(); } private testRayLineNew(vec: cc.Vec2) { this._hitPList.length = 0; let v = cc.v2(); vec.normalize(v); // let speed = (tMgr.getConfig(TableName.GAME_PLAY, 3) as GamePlayTable).Value v.multiplyScalar(200); //速度固定为200,避免高速带来的误差,避免速度太慢带来的性能开销 PhysicsControl.ins.setPhysicsEnable(true); this._mapView.testBall.setPosition(BattleManager.ins.curBattle.marblesBornPos); this._mapView.testBall.getComponent(cc.RigidBody).linearVelocity = v; // let len = (tMgr.getConfig(TableName.GAME_PLAY, 9) as GamePlayTable).Value // let time = len / speed; // for (let i = 0; i < 10; ++i) { // PhysicsControl.ins.update(time); // } // PhysicsControl.ins.setPhysicsEnable(false); let goldenAim: boolean = (SaveDataManager.ins.runtimeData.goldenAimTry || Date.now() <= SaveDataManager.ins.runtimeData.goldenAimEndTime); let hitCount = (goldenAim ? 3 : 1); while (this._hitPList.length < hitCount) { PhysicsControl.ins.update(1 / 60); } PhysicsControl.ins.update(2 / 60); PhysicsControl.ins.setPhysicsEnable(false); this._hitPList = this._hitPList.slice(0, hitCount); let i = 0; for (i; i < this._hitPList.length; ++i) { if (i == 0) { this.drawLine(this._ballWorldP, this._hitPList[i]); } else { this.drawLine(this._hitPList[i - 1], this._hitPList[i]); } let ball: cc.Node; if (i < this._hitBallList.length) { ball = this._hitBallList[i]; } else { ball = cc.instantiate(BattleManager.ins.curBattle.prefabCollection.getChildByName('ball')); ball.getComponent(Ball).scaleEnable = false; ball.getComponent(cc.Collider).enabled = false; ball.getChildByName('img').getComponent(cc.Sprite).sizeMode = cc.Sprite.SizeMode.CUSTOM; let colliderSize = ball.getComponent(cc.PhysicsCircleCollider).radius * 2; ball.getChildByName('img').setContentSize(colliderSize, colliderSize); ball.getChildByName('img').scale = 1; // ball.scale = 0.5; this._hitBallList.push(ball); this._gameRoot.addChild(ball); } ball.active = true; let pos = this._gameRoot.convertToNodeSpaceAR(this._hitPList[i]); ball.setPosition(pos); } for (i; i < this._hitBallList.length; ++i) { this._hitBallList[i].active = false; } // let t = this._mapView.convertToWorldSpaceAR(this._mapView.testBall.position); // let tt = cc.v2(t.x, t.y); // if (this._hitPList.length == 0) { // this.drawLine(this._ballWorldP, tt); // } // else { // this.drawLine(this._hitPList[this._hitPList.length - 1], tt); // } // this._lastCollisionV.normalizeSelf(); // this._lastCollisionV.multiplyScalar(100); let lastPoint = this._hitPList[this._hitPList.length - 1]; let t = this._mapView.convertToWorldSpaceAR(this._mapView.testBall.position); let tt = cc.v2(t.x - lastPoint.x, t.y - lastPoint.y); //从终点指向小球的向量 tt.normalizeSelf(); tt.multiplyScalar((tMgr.getConfig(TableName.GAME_PLAY, 9) as GamePlayTable).Value); tt.x = lastPoint.x + tt.x; tt.y = lastPoint.y + tt.y; this.drawLine(this._hitPList[this._hitPList.length - 1], tt); } // private _lastCollisionV: cc.Vec2 = new cc.Vec2(); onTestBallCollision(contact: cc.PhysicsContact, selfCollider: cc.Collider, otherCollider: cc.Collider) { // let manifold = contact.getWorldManifold(); // if (manifold.points.length > 0) { // this._hitPList.push(cc.v2(manifold.points[0].x, manifold.points[0].y)); // } this._hitPList.push(selfCollider.node.convertToWorldSpaceAR(cc.Vec2.ZERO)); } private drawLine(worldStart: cc.Vec2, worldEnd: cc.Vec2) { let goldenAim: boolean = (SaveDataManager.ins.runtimeData.goldenAimTry || Date.now() <= SaveDataManager.ins.runtimeData.goldenAimEndTime); let g = this._gameRoot.getComponent(cc.Graphics); g.fillColor.fromHEX(goldenAim ? '#FFFF00' : '#FFFFFF'); let gStart = this._gameRoot.convertToNodeSpaceAR(worldStart); let gEnd = this._gameRoot.convertToNodeSpaceAR(worldEnd); let vec = cc.v2(); cc.Vec2.subtract(vec, gEnd, gStart); let len = vec.mag(); let step = 0; let lerpVec = cc.v2(); while (true) { let ratio = step / len; let end: boolean = false; if (ratio > 1) { ratio = 1; end = true; } gEnd.lerp(gStart, ratio, lerpVec); // g.moveTo(); g.circle(lerpVec.x, lerpVec.y, 3); g.fill(); step += 20; if (end) { break; } } } private changePointer(double: boolean): void { // let ballNode = this._pointerNode.getChildByName('ball'); // ballNode.active = !double; this._spliterNode.active = double; if (double) { BattleManager.ins.shootTouchEnable = false; this._spliterNode.getComponent(cc.Animation).once('finished', () => { BattleManager.ins.shootTouchEnable = true }, this); this._spliterNode.getComponent(cc.Animation).play('ani_gun001'); this._spliterNode.setPosition(BattleManager.ins.curBattle.marblesBornPos); } } //#endregion //#region event private onTouchStart(e: cc.Event.EventTouch) { if (!BattleManager.ins.shootTouchEnable) { return; } this.node.getChildByName('UIBattle').getComponent(UIBattle).setCancelNodeVisible(true); this._gameRoot.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this); this._gameRoot.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this); this._gameRoot.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this); this._mapView.testBall.active = true; this.onTouchMove(e); let chargingNode = this._pointerNode.getChildByName('chargingNode'); chargingNode.active = true; chargingNode.getComponent(cc.Animation).play('fx_xuli_001'); } private onTouchMove(e: cc.Event.EventTouch) { let touchP = e.getLocation(); // cc.Vec2.subtract(this._pointerVec, touchP, this._ballWorldP); let deg = slib.MathUtil.get360DegByVec(touchP.x - this._ballWorldP.x, touchP.y - this._ballWorldP.y); if (deg < this._minShootDeg || deg > 180 - this._minShootDeg) { this.node.getChildByName('UIBattle').getComponent(UIBattle).setCancelNodeHit(true); return; } this.node.getChildByName('UIBattle').getComponent(UIBattle).setCancelNodeHit(false); cc.Vec2.subtract(this._pointerVec, touchP, this._ballWorldP); this._gameRoot.getComponent(cc.Graphics).clear(); this.testRayLineNew(this._pointerVec); //旋转指针 if (BattleManager.ins.curBattle.doubleShoot) { let deg = slib.MathUtil.get360DegByVec(this._pointerVec.x, this._pointerVec.y); let nodeA = this._spliterNode.getChildByName('ani_guna'); let nodeB = this._spliterNode.getChildByName('ani_gunb'); nodeA.angle = deg - 90; //指向正上方 nodeB.angle = (90 - deg); let otherPointer = cc.v2(-this._pointerVec.x, this._pointerVec.y); this.testRayLineNew(otherPointer); } } private onTouchCancel() { let pointer = this._mapView.getChildByName('imgPointer'); pointer.angle = 0; // let g = this._gameRoot.getComponent(cc.Graphics); // g.clear(); this._gameRoot.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this); this._gameRoot.off(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this); this._gameRoot.off(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this); this.node.getChildByName('UIBattle').getComponent(UIBattle).setCancelNodeVisible(false); let chargingNode = this._pointerNode.getChildByName('chargingNode'); chargingNode.getComponent(cc.Animation).stop('fx_xuli_001'); chargingNode.active = false; this._mapView.testBall.active = false; this._gameRoot.getComponent(cc.Graphics).clear(); for (let i = 0; i < this._hitBallList.length; ++i) { this._hitBallList[i].active = false; } } private onTouchEnd() { this.onTouchCancel(); BattleManager.ins.curBattle.shoot(this._pointerVec); this._gameRoot.getChildByName('tips1').active = false; this._gameRoot.getChildByName('guideAim').active = false; } private onSkillStart(skillId: UserSkill) { if (skillId == UserSkill.DOUBLE_SHOOT) { this.changePointer(true); } else if (skillId == UserSkill.SHIELD) { this.setShieldEnable(true); } } private onSkillEnd(skillId: UserSkill) { if (skillId == UserSkill.SHIELD) { this.setShieldEnable(false); } } private onBornPosChange() { this._pointerNode.getChildByName('ball').active = true; this._pointerNode.setPosition(BattleManager.ins.curBattle.marblesBornPosNextRound); } private onRoundEnd() { this._ballWorldP = this._mapView.convertToWorldSpaceAR(BattleManager.ins.curBattle.marblesBornPos); this._pointerNode.setPosition(BattleManager.ins.curBattle.marblesBornPos); this.changePointer(false); } private setShieldEnable(value: boolean) { let effectNode = cc.find('GameRoot/borderCollector/effect', this.node); effectNode.active = value; if (value) { let duration = effectNode.getComponent(cc.Animation).play('fx_gl_chzd_001').duration; this.schedule(() => { effectNode.getComponent(cc.Animation).play('fx_gl_chzd_002') }, duration, 1); } else { // this.unscheduleAllCallbacks(); } } onShake(value: boolean) { let ani = this.node.getChildByName('Main Camera').getComponent(cc.Animation); if (value) { ani.stop('ani_shake'); ani.play('ani_shake'); } else { this.node.getChildByName('Main Camera').setPosition(0, 0, 0); // let state = ani.getAnimationState('ani_shake'); // state.time = 0; // state.stop(); ani.stop('ani_shake'); } // ani.play('ani_shake'); } //#endregion }