using Assets.Scripts.Apis; using Assets.Scripts.Apis.Models; using System; using System.Linq; using System.Collections; using System.Collections.Generic; using UnityEngine.Networking; using Assets.Scenes.Ride.Scripts.Model; using Assets.Scenes.Ride.Scripts.Model.CyclingModels; using Assets.Scenes.Ride.Scripts; using Mapbox.Unity.Map; using UnityEngine; using GeoJSON.Net.Geometry; using TurfCS; using Mapbox.Utils; using Assets.Scripts; using System.Threading.Tasks; using UnityEngine.EventSystems; using UnityEngine.Events; using Assets.Scenes.Ride.Scripts.Model.RiderModels; using System.IO; public class CyclingController : DeviceServiceMonoBase { public AbstractMap map; public GameObject player; public GameObject UIObject; public RouteResultParam selectParamModel; public RouteResult routeResult; public Dictionary selectPlayerDic { set; get; } = new Dictionary(); public int preticks; #region 参数 private MapRoute mapRoute;//当前路书数据 private MapDataModel mapData;//当前路书数据 private Route route;//当前路书综合数据 public List mapRouteRankingList { get; set; } private Vector2d coordiantes;//当前地图中心 public bool isStart;//当前游戏是否开始 public CyclingModel cyclingModel;//当前骑行模式 public BaseCycling cyclingController { get; set; } private int routeId; private MapApi mapApi; public DateTime startTime; public DateTime endTime; public bool isQuit; public bool isPause; #endregion GameObject loadingcanvas; LoadingController loadingController; private async Task Login() { var result = await new UserApi().Login("15261826280", "123456", ""); App.CurrentUser = result.data; } GameObject miniMap; GameObject resultPanel; void Awake() { #if UNITY_EDITOR if (App.CurrentUser == null) { Login(); } #endif //获取路书信息 mapApi = ConfigHelper.mapApi; routeId = App.RouteIdParam > 0? App.RouteIdParam : 2633; //mapRoute = mapApi.GetById(routeId).data; //miniMap = transform.Find("MiniMap").gameObject;//小地图 resultPanel = transform.Find("SingleUI/Panel/ResultPanel").gameObject; } void OnDestroy() { App.TextureCache.Clear(); } Transform target; private void Start() { UIManager.Instance.MainPanel = this.transform.Find("SingleUI/Panel").GetComponent(); UIManager.Instance.ModalsPanel = this.transform.Find("SingleUI/ModalPanel").GetComponent(); onlineUserPrefab = Resources.Load("UI/Prefab/Ride/OnlinePlayer"); miniMapPlayerPrefab = Resources.Load("UI/Prefab/Ride/MiniMapPlayer"); target = transform.Find("Target"); //进入倒计时 singleUIManager = UIObject.GetComponent(); loadingController = FindObjectOfType(); loadingController.InjectController(this); //开始loading StartCoroutine(Init()); } public void SetUIManager(PFUIPanel mainPanel, PFUIPanel model) { UIManager.Instance.MainPanel = mainPanel;//this.transform.Find("SingleUI/Panel").GetComponent(); UIManager.Instance.ModalsPanel = model;// this.transform.Find("SingleUI/ModalPanel").GetComponent(); } public void ReSetUIManager() { UIManager.Instance.MainPanel = this.transform.Find("SingleUI/Panel").GetComponent(); UIManager.Instance.ModalsPanel = this.transform.Find("SingleUI/ModalPanel").GetComponent(); } public void AddEvent(GameObject sender, EventTriggerType eventType,UnityAction unityAction) { UIManager.AddEvent(sender, eventType, unityAction); } public void ShowDevice(PFUIPanel pFUIPanel) { UIManager.Show(UIManager.Instance.DevicePanel, pFUIPanel); } public Texture GetCountryImageByCode(string code) { return UIManager.Instance.loginRegOptions.GetCountryImage(code); } public Texture GetCountryImageByName(string name) { return UIManager.Instance.loginRegOptions.GetCountryImageByName(name); } private IEnumerator Init() { yield return new WaitForSeconds(1); mapRoute = mapApi.GetById(routeId).data; miniMap = transform.Find("MiniMap").gameObject;//小地图 loadingController.Init(mapRoute);//初始化loading页面 loadingController.AddProcess(10); InitData();//初始化数据 InitGameObject();//初始化场景 MapUDPService.Init();//初始化TCP loadingController.AddProcess(10); } //初始化数据 private void InitData() { mapData = mapApi.GetData(routeId);//获取路书地理数据 route = new Route(mapData, mapRoute); loadingController.AddProcess(10); #region 其他场景传参处理 //骑行结果 if (App.routeResult != null ) { routeResult = App.routeResult; selectParamModel = App.routeResult.ContinueCyclingParam;//继续骑行 preticks = App.routeResult.Ticks; } if (selectParamModel == null) { selectParamModel = new RouteResultParam { CompetitionId = 0, ContinueIndex = 0, ContinueMark = "", GlobalContinue = false, EndDistance = 0, RankingsId = new List(), OnlineUserId = 0, RouteId = App.RouteIdParam }; } App.routeResult = null; #endregion //异步请求mapbox画出当前路书路线图 loadingController.DrawMapRoute(mapData); //计算上次骑行距离调整地图中心点 double endDistance = selectParamModel.EndDistance; coordiantes = Along(endDistance); loadingController.AddProcess(10); //查询排行榜 var list = mapApi.GetRouteRanking(App.RouteIdParam, "1", 0, 10, ""); if (list.result) { loadingController.CreateRankingList(list.data.list); loadingController.AddProcess(10); } var shaowList = mapApi.GetShadowList(App.RouteIdParam, "", 0, 10); if (shaowList.result) { mapRouteRankingList = shaowList.data.list; } } //加载人物和地图以及UI界面 private void InitGameObject() { map.gameObject.SetActive(true); player.SetActive(true); UIObject.SetActive(true); miniMap.SetActive(true); map.OnTileFinished += Map_OnTileFinished; } //private void Map_OnTileFinished(Mapbox.Unity.MeshGeneration.Data.UnityTile obj) //{ // var playerController = player.GetComponent(); // player.transform.position = map.GeoToWorldPosition(playerController.Currentlatlong); //} //设置骑行模式 public void SetCyclingModel(CyclingModel mode) { this.cyclingModel = mode; switch (cyclingModel) { case CyclingModel.Single: cyclingController = new SingleModel(route, selectParamModel); break; case CyclingModel.Review: cyclingController = new ReviewModel(route, selectParamModel); break; } AutoStart(); InitPlayer(); } PlayerController playerController; //初始化人物位置角度 private void InitPlayer() { lockView = true; TrailRenderer trail = player.GetComponent(); playerController = player.GetComponent(); Vector2d lastLatLon = Along(recorderData.EndDistance); Vector3 currentPos = map.GeoToWorldPosition(lastLatLon); currentPos.y += 1f; player.transform.position = currentPos; playerController.currentPos = currentPos; trail.Clear(); Vector2d nextLatLon = Along(recorderData.EndDistance + 0.1); //设定人物方向 var s = map.GeoToWorldPosition(lastLatLon); var e = map.GeoToWorldPosition(nextLatLon); Quaternion neededRotation = Quaternion.LookRotation(s - e); player.transform.rotation = Quaternion.Euler(0, neededRotation.eulerAngles.y, 0); playerController.currentRotation = neededRotation; //初始化海拔图头像位置 var index = GetCurrentIndex(recorderData.EndDistance); playerController.InitGraph(index); } SingleUIManager singleUIManager; public void AutoStart() { singleUIManager.StartRide(null); } public void GoContinueRide() { singleUIManager.ContinueRide(); } #region TCP相关 public void TcpHandler() { if (cyclingController != null) { //tcp数据传输 cyclingController.Run(null); //在线人物或比赛人物渲染 ShowOnlineUsers(); } } List otherList = new List(); GameObject onlineUserPrefab; GameObject miniMapPlayerPrefab; int messageIndex = 0; private void ShowOnlineUsers() { var onlineRiders = cyclingController.riders; var currentOnlineUserList = FindObjectsOfType(); //新增或者更新 foreach (var item in onlineRiders) { var onlineRider = item as OnlineRiderModel; var currentUser = currentOnlineUserList.Where(c => c.UserId == item.UserId).FirstOrDefault(); var onlineDistance = onlineRider.EndDistance - onlineRider.PreDistance; var onlineTotalDistance = onlineRider.EndDistance; var index = GetCurrentIndex(onlineTotalDistance); if (currentUser == null) { //大地图人物 GameObject otherPlayerObj = (GameObject)Instantiate(onlineUserPrefab, transform); otherPlayerObj.transform.position = map.GeoToWorldPosition(Along(onlineTotalDistance)); var onlinePlayerController = otherPlayerObj.GetComponent(); otherList.Add(onlinePlayerController); onlinePlayerController.UserId = onlineRider.UserId; onlinePlayerController.SetDataSource(onlineTotalDistance, onlineDistance, onlineRider.NickName, onlineRider.WeightKg, index); onlinePlayerController.SetHead(onlineRider.WxHeadImg); //小地图人物 GameObject miniPlayer = (GameObject)Instantiate(miniMapPlayerPrefab, transform); var miniController = miniPlayer.GetComponent(); miniController.SetController(onlinePlayerController); //发消息xx进入路书 if(messageIndex > 0) EventQueueSystem.QueueEvent(new JoinMessageEvent(onlineRider.NickName, onlineRider.WxHeadImg)); } else { currentUser.SetDataSource(onlineTotalDistance, onlineDistance, onlineRider.NickName, onlineRider.WeightKg, index); } } if(onlineRiders.Count > 0) messageIndex++; //移除 foreach (var item in currentOnlineUserList) { var currentItem = onlineRiders.Where(c => c.UserId == item.UserId).FirstOrDefault(); if (currentItem == null) { item.RemoveSelf(); } var s = playerController.TotalDistance - item.TotalDistance; } //显示面板信息 var others = FindObjectsOfType(); foreach (var item in others) { item.IsShowInfo = false; } var frontPlayer = others.Where(c => c.TotalDistance - playerController.TotalDistance < 0.25 && c.TotalDistance - playerController.TotalDistance >= 0 && !(c is PlayerController)).OrderBy(c=>c.TotalDistance).FirstOrDefault(); var bakePlayer = others.Where(c => c.TotalDistance - playerController.TotalDistance >-0.25 && c.TotalDistance - playerController.TotalDistance < 0 && !(c is PlayerController)).OrderByDescending(c=>c.TotalDistance).FirstOrDefault(); if(frontPlayer != null) frontPlayer.IsShowInfo = true; if (bakePlayer != null) bakePlayer.IsShowInfo = true; } #endregion #region 视角切换 public AbstractMap map3d; public bool Is3dView; public void ChangeMapImageStyle(GameObject arrowGameObj) { var playerController = player.GetComponent(); var trailRenderer = player.GetComponent(); trailRenderer.time = 0; StartCoroutine(EnableTrailRenderer(trailRenderer)); if (!Is3dView) { //地图属性变更 map.Terrain.ExaggerationFactor = 1.5f; map.Terrain.SetElevationType(ElevationLayerType.TerrainWithElevation); map.ImageLayer.SetLayerSource(ImagerySourceType.Custom); map.SetCenterLatitudeLongitude(playerController.Currentlatlong); //map3d.gameObject.SetActive(true); //map.gameObject.SetActive(false); //人物属性变更 var pos = map.GeoToWorldPosition(playerController.Currentlatlong); playerController.currentPos = pos; target.position = pos; player.transform.localScale = new Vector3(3f, 3f, 3f); player.transform.position = pos; arrowGameObj.SetActive(false); Is3dView = true; } else { //地图属性变更 map.ImageLayer.SetLayerSource(ImagerySourceType.JuzeTest); map.Terrain.ExaggerationFactor = 0f; map.Terrain.SetElevationType(ElevationLayerType.FlatTerrain); map.SetCenterLatitudeLongitude(playerController.Currentlatlong); //map.gameObject.SetActive(true); //map3d.gameObject.SetActive(false); //人物属性变更 var pos = map.GeoToWorldPosition(playerController.Currentlatlong); player.transform.position = pos; player.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); target.position = pos; playerController.currentPos = Vector3.zero; arrowGameObj.SetActive(true); Is3dView = false; } } private bool lockView = false; private void Map_OnTileFinished(Mapbox.Unity.MeshGeneration.Data.UnityTile obj) { if (!lockView) { var playerController = player.GetComponent(); player.transform.localScale = new Vector3(3f, 3f, 3f); var locations = playerController.Currentlatlong == null ? playerController.Currentlatlong : new Vector2d(mapData.List[0].Point[0], mapData.List[0].Point[1]); player.transform.position = map.GeoToWorldPosition(locations); if (recorderData != null) { var lastLatLon = Along(recorderData.EndDistance); var nextLatLon = Along(recorderData.EndDistance+0.1); player.transform.position = map.GeoToWorldPosition(lastLatLon); //设定人物方向 var s = map.GeoToWorldPosition(lastLatLon); var e = map.GeoToWorldPosition(nextLatLon); Quaternion neededRotation = Quaternion.LookRotation(s - e); player.transform.rotation = Quaternion.Euler(0, neededRotation.eulerAngles.y, 0); } } } IEnumerator EnableTrailRenderer(TrailRenderer trailRenderer) { yield return new WaitForSeconds(2f); trailRenderer.Clear(); trailRenderer.time = 30; } #endregion #region 游戏状态控制 //开始骑行 public void SetStart() { if (!isPause || DateTime.MinValue == startTime) { isStart = true; startTime = UIManager.Now.GetDateTime(); } else { SetContinue(); } } //继续骑行 public void SetContinue() { isStart = true; isPause = false; } //暂停骑行 public void SetPause() { isStart = false; isPause = true; } //退出或者完成骑行 public void SetQuit() { isStart = false; isQuit = true; } #endregion #region 数据处理 /// /// 当前骑行数据的记录器 /// private RecorderDataModel recorderData { get { return cyclingController?.recorderData; } } public Route GetRoute() { return route; } public MapDataModel GetMapData() { return mapData; } public void Save(double totalDistance) { isQuit = true; isStart = false; string recordId = Guid.NewGuid().ToString(); //var path = Helper.GetDataDir("MapWorkoutRecords/"+ recordId); var path = PFConstants.MapWorkoutRecordFolder + "/" + recordId; Helper.CreateDirectoryIfNotExsit(path); string imageFileName = path +"/"+ Guid.NewGuid().ToString() + ".png"; CaptureCamera(Camera.main, new Rect(Screen.width * 0f, Screen.height * 0f, Screen.width * 0.5f, Screen.height * 0.5f), imageFileName); cyclingController.recorderData.StartTime = startTime; cyclingController.recorderData.EndTime = UIManager.Now.GetDateTime(); cyclingController.recorderData.IsCompleted = totalDistance == mapData.TotalDistance; cyclingController.recorderData.EndDistance = totalDistance; cyclingController.recorderData.AntModelId = AntModelId; cyclingController.recorderData.ManufacturerId = ManufacturerId; cyclingController.recorderData.DeviceNumber = DeviceNumber; //显示骑行结果 resultPanel.SetActive(true); var rs = resultPanel.GetComponent(); rs.InjectController(this); rs.SetDataSource(cyclingController.recorderData); cyclingController.recorderData.SaveWithLocalRecordAysnc(cyclingModel, selectParamModel, imageFileName, recordId, path); } protected void CaptureCamera(Camera camera, Rect rect,string fileName) { // 创建一个RenderTexture对象 RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 0); // 临时设置相关相机的targetTexture为rt, 并手动渲染相关相机 camera.targetTexture = rt; camera.Render(); //ps: --- 如果这样加上第二个相机,可以实现只截图某几个指定的相机一起看到的图像。 //ps: camera2.targetTexture = rt; //ps: camera2.Render(); //ps: ------------------------------------------------------------------- // 激活这个rt, 并从中中读取像素。 RenderTexture.active = rt; Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false); screenShot.ReadPixels(rect, 0, 0);// 注:这个时候,它是从RenderTexture.active中读取像素 screenShot.Apply(); // 重置相关参数,以使用camera继续在屏幕上显示 camera.targetTexture = null; //ps: camera2.targetTexture = null; RenderTexture.active = null; // JC: added to avoid errors GameObject.Destroy(rt); // 最后将这些纹理数据,成一个图片文件 byte[] bytes = screenShot.EncodeToPNG(); //var path = Helper.GetDataDir("MapWorkoutRecords/images"); //string filename = path + "/" + Guid.NewGuid().ToString() + ".png"; System.IO.File.WriteAllBytes(fileName, bytes); //Debug.Log(string.Format("截屏了一张照片: {0}", filename)); } public Vector2d GetCenterCoordinate() { return coordiantes; } public int GetCurrentIndex(double endDistance) { int index = 0; var pointList = mapData.List; double sumDistance = 0; for (int i = 0; i < pointList.Count; i++) { sumDistance += pointList[i].Distance; if (endDistance * 1000 <= sumDistance) { index = i; break; } } index = endDistance >= mapData.TotalDistance ? index + 1 : index; return index; } public Vector2d Along(double endDistance) { if (mapData != null) { var list = mapData.List.Select(p => new GeoJSON.Net.Geometry.GeographicPosition(p.Point[0], p.Point[1])); LineString lineString = new LineString(list); var pt1 = Turf.Along(lineString, endDistance); var ll = ((GeographicPosition)((GeoJSON.Net.Geometry.Point)pt1.Geometry).Coordinates); return new Vector2d(ll.Latitude, ll.Longitude); } else { return new Vector2d(0,0); } } /// /// 海拔图数据 /// public float[] GetRealTimeLineChartData(int index) { List dist = new List(); var list = mapData.List.Select(c => (float) c.Elevation ).ToArray(); var count = list.Count(); for (int i = 0; i < count; i++) { if (i > index) { dist.Add(list[i]); } } return dist.ToArray(); } public float[] GetLineChartData() { var list = mapData.List.Select(c => (float)c.Elevation).ToArray(); return list; } #endregion private void OnApplicationQuit() { App.MainDeviceAdapter.Dispose(); } }