// 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 ConfigManager from "../../../engines/configs/ConfigManager"; import { GUIManager } from "../../../engines/gui/GUIManager"; import JLoader from "../../../engines/loader/JLoader"; import LoadingView from "../../../engines/loadingView/LoadingView"; import MathUtils from "../../../engines/utils/MathUtils"; import ConfigKeys from "../../models/ConfigKeys"; import GameModel from "../../models/GameModel"; import UIKeys from "../../UIKeys"; import InCirclePolygon from "./InCirclePolygon"; import PlayerController from "./PlayerController"; const {ccclass, property} = cc._decorator; @ccclass export default class GameController extends cc.Component { @property(cc.Node) camera: cc.Node = null; @property(cc.Node) polygon: cc.Node = null; @property(PlayerController) player: PlayerController = null; @property(cc.MeshRenderer) background:cc.MeshRenderer=null; /** * 游戏结束 */ isGameOver:boolean; private inCirclePolygon:InCirclePolygon; private isDrop:boolean; private startDropTime:number; /** * 移动向量 */ private moveVec:cc.Vec3=new cc.Vec3(); levelConfig:any; carConfig:any; start () { GameController.__instance=this; //显示进度条 LoadingView.single.Show(); //关卡配置 this.levelConfig=ConfigManager.single.GetConfigItem(ConfigKeys.Levels,GameModel.single.currentLevel); this.carConfig=ConfigManager.single.GetConfigItem(ConfigKeys.Car,GameModel.single.currentCarId); this.LoadPolygon(); } private loader:JLoader; private LoadPolygon():void{ this.loader=new JLoader(); this.loader.AddEvent(JLoader.EVENT_COMPLETE,this,this.PolygonLoaded); this.loader.Load(this.levelConfig.packageName,this.levelConfig.polygonPrefab); } private PolygonLoaded():void{ let prefab:cc.Prefab=this.loader.GetContent(cc.Prefab) as cc.Prefab; let node:cc.Node=cc.instantiate(prefab); this.polygon.addChild(node); this.loader.RemoveAllEvent(); this.loader.AddEvent(JLoader.EVENT_COMPLETE,this,this.CarLoaded); this.loader.Load(this.carConfig.packageName,this.carConfig.prefab); } private CarLoaded():void{ let prefab:cc.Prefab=this.loader.GetContent(cc.Prefab) as cc.Prefab; let node:cc.Node=cc.instantiate(prefab); this.player.node.addChild(node); this.loader.RemoveAllEvent(); this.loader.AddEvent(JLoader.EVENT_COMPLETE,this,this.BackgroundLoaded); this.loader.Load("background",this.levelConfig.background); } private BackgroundLoaded():void{ this.loader.RemoveAllEvent(); let texture:cc.Texture2D=this.loader.GetContent(cc.Texture2D) as cc.Texture2D; let m:cc.Material=this.background.getMaterial(0); m.setProperty("diffuseTexture",texture); this.loader=null; this.InitGame(); LoadingView.single.Hide(); } private InitGame():void{ this.inCirclePolygon=new InCirclePolygon(this.polygon); this.StartGame(); } /** * 开始游戏 */ StartGame():void{ this.isGameOver=false; this.isDrop=false; this.inCirclePolygon.Reset(); this.player.Reset(); } update (dt:number) { if(this.inCirclePolygon==null){ return; } if(this.isGameOver){ return; } cc.Vec3.zero(this.moveVec); //前进的速度 cc.Vec3.add(this.moveVec,this.moveVec,this.player.speed); if(this.isDrop){ cc.Vec3.add(this.moveVec,this.moveVec,this.player.dropSpeed); }else{ if(this.player.isLeft){ cc.Vec3.add(this.moveVec,this.moveVec,this.player.leftSpeed); }else if(this.player.isRight){ cc.Vec3.add(this.moveVec,this.moveVec,this.player.rightSpeed); } //冲刺 if(this.player.isSprint){ cc.Vec3.add(this.moveVec,this.moveVec,this.player.sprintSpeed); } } cc.Vec3.multiplyScalar(this.moveVec,this.moveVec,dt); //角色移动 let pos:cc.Vec3=this.player.logicPosition; pos.add(this.moveVec,pos); //将X轴环形映射 pos.x=MathUtils.CircularMapping(pos.x,this.inCirclePolygon.maxX,this.inCirclePolygon.minX); this.player.logicPosition=pos; //背景跟角色使用保持固定的距离 pos=this.background.node.position; pos.z=0-(this.player.logicPosition.y+1000); this.background.node.position=pos; //摄像机跟随 if(!this.isDrop){ pos=this.camera.position; pos.x=this.player.logicPosition.x; pos.y=this.inCirclePolygon.center.y; pos.z=-this.player.logicPosition.z+50; this.camera.position=pos; // cc.log("摄像机位置:",pos.x,pos.y,pos.z); } //物理计算 if(!this.isDrop&&this.player.isSprint==false){ this.CheckPhysicsPos(); } this.CheckAngle(); //多边形更新 this.inCirclePolygon.Update(dt); //检测游戏是否结束 if(this.isGameOver==false){ if(this.isDrop){ let currentTime:number=cc.sys.now(); if(currentTime-this.startDropTime>2000){ cc.log("游戏结束!"); this.GameOver(); } }else{ if(this.player.logicPosition.z>this.levelConfig.endPos){ cc.log("到达终点"); this.GameOver(); } } } } GameOver():void{ this.isGameOver=true; GUIManager.single.Show(UIKeys.WXS04,true); } private rectsTemp:number[]; private point:cc.Vec3=new cc.Vec3(); private origin:cc.Vec3=new cc.Vec3(); /** * 计算角度 */ private CheckAngle():void{ if(this.rectsTemp==null){ this.rectsTemp=[]; } this.inCirclePolygon.PolygonIntersects(this.player.rect,this.rectsTemp); if(this.rectsTemp.length==0){ return; } if(this.rectsTemp.length>2){ cc.error("主角的大小太大了!"); return; } let angle:number; //在单独的一个块中 if(this.rectsTemp.length==1){ angle=this.inCirclePolygon.GetPolygonTileAngle(this.rectsTemp[0]); let aTile:cc.Rect=this.inCirclePolygon.GetPolygonTile(this.rectsTemp[0]); this.inCirclePolygon.SetAngle(angle); this.background.node.angle=angle; this.inCirclePolygon.SetCenter(aTile.x+aTile.width*0.5,this.inCirclePolygon.centerHeight,0); }else{//跨块了 let aAngle:number=this.inCirclePolygon.GetPolygonTileAngle(this.rectsTemp[0]); let bAngle:number=this.inCirclePolygon.GetPolygonTileAngle(this.rectsTemp[1]); let aTile:cc.Rect=this.inCirclePolygon.GetPolygonTile(this.rectsTemp[0]); //计算出旋转点 let cx:number=aTile.x+aTile.width; let helfWidth:number=this.player.width*0.5; let sx:number=cx-helfWidth; let ex:number=cx+helfWidth; let proportion:number=(this.player.logicPosition.x-sx)/(ex-sx); angle=aAngle+(bAngle-aAngle)*proportion; this.inCirclePolygon.SetAngle(angle); this.background.node.angle=angle; //绕点 this.origin.x=cx; this.origin.y=0; this.origin.z=0; //原始的圆心 this.point.x=aTile.x+(aTile.width*0.5); this.point.y=this.inCirclePolygon.centerHeight; this.point.z=0; angle=0-this.inCirclePolygon.outAngle*proportion; this.inCirclePolygon.RotationCenter(angle,this.point,this.origin); } } //物理坐标 private physicsPos:cc.Vec2=new cc.Vec2(); private CheckPhysicsPos():void{ let list:cc.Vec3[]=this.player.gridView; let count:number=0; let point:cc.Vec3; let state:number for (let index = 0; index < list.length; index++) { point=list[index]; this.inCirclePolygon.GetPhysicsPos(point.x,point.z,this.physicsPos); state=this.inCirclePolygon.GetPhysicsState(this.physicsPos.x,this.physicsPos.y); if(state==0){ count++; } } //超过半数悬空则掉落 if(count>=5){ this.isDrop=true; this.startDropTime=cc.sys.now(); } } onDestroy():void{ let list:string[]=[ this.levelConfig.packageName, this.carConfig.packageName, "background" ] let bundle:cc.AssetManager.Bundle; list.forEach(bundleName => { bundle=cc.assetManager.getBundle(bundleName); bundle.releaseAll(); cc.assetManager.removeBundle(bundle); }); } private static __instance:GameController; public static get single():GameController{ return this.__instance; } }