using Assets.Scenes.Ride.Scripts; using Assets.Scenes.Ride.Scripts.Model; using Assets.Scenes.Ride.Scripts.Model.CyclingModels; using Assets.Scripts.Apis.Models; using Assets.Scripts.UI.Prefab.Device; using GeoJSON.Net.Geometry; using Mapbox.Utils; using RenderHeads.Media.AVProVideo; using System; using System.Collections.Generic; using System.Linq; using TurfCS; using UnityEngine; using Assets.Scenes.Ride.Scripts.Model.RiderModels; using UnityEngine.EventSystems; using UnityEngine.Events; using Helper = Assets.Scenes.Ride.Scripts.Helper; using System.Collections; using Assets.AR; using Assets.Core; namespace Assets.Scripts.Scenes.VideoRide { public class VideoGameManager : DeviceServiceMonoBase { public ARTrainingController trainingController; public AbstractVideoPlayer CurrentPlayer { get; set; } private MapDataModel mapData { get; set; } private MediaPlayer mediaPlayer { get; set; } private bool isStart { get; set; } private Route route { get; set; } public MapRoute mapRoute { get; set; } public RouteResultParam selectParamModel { get; set; } public RouteResult routeResult; public string recordId { get; set; } public DateTime startTime { get; set; } public CyclingModel cyclingModel { get; set; } public BaseCycling cyclingController { get; set; } private double endDistance { get; set; } private GameObject infoPanel; private GameObject Player; private GameObject Player_NV; private GameObject OnlinePlayer; private GameObject OnlinePlayer_NV; private bool isStop { get; set; } VideoLoading videoLoading { get; set; } //当前是第一人称还是第三人称 public ViewMode _viewMode { get; set; } //当前是观察者视角还是骑行者视角 public ARMode _aRMode { get; set; } public int RankingId { get; set; } public Dictionary rideObjs = new Dictionary(); private VideoUIManager _uiManager { get; set; } private ARTrainingController _trainingController { get; set; } public List visibleRiders = new List();//当前线路上的人 private const int limits = 5;//在线的其他人数 private double MaxVisibleDistance = 200d;//最大显示距离 float timer = 0f; int ticks = 0; MapRouteRankingList rankingList; public GameObject videoPlayer; public GameObject target; public int CurrentUserId { get; set; } protected override void Awake() { base.Awake(); _uiManager = FindObjectOfType(); trainingController = GetComponent(); mediaPlayer = FindObjectOfType(); DeviceCache.Init(PFConstants.DeviceCacheFolder); var check = CheckAnt();//初始化蓝牙设备 recordId = Guid.NewGuid().ToString(); infoPanel = Resources.Load("UI/Prefab/AR/VideoPlayerHead"); OnlinePlayer = Resources.Load("UI/Prefab/AR/OnlineVideoPlayer"); OnlinePlayer_NV = Resources.Load("UI/Prefab/AR/OnlineVideoPlayer_NV"); Player = Resources.Load("UI/Prefab/AR/VidePlayer"); Player_NV = Resources.Load("UI/Prefab/AR/VidePlayer_NV"); _trainingController = GetComponent(); StartCoroutine(Init()); } private void Start() { UIManager.Instance.MainPanel = GetCanvasTransform().GetComponent(); UIManager.Instance.ModalsPanel = this.transform.Find("Canvas/ModalPanel").GetComponent(); var routeId = App.RouteIdParam; //获取路书 GetMapRoute(); GetMapData(); route = new Route(mapData, mapRoute); if (selectParamModel == null) { selectParamModel = new RouteResultParam { CompetitionId = 0, ContinueIndex = 0, ContinueMark = "", GlobalContinue = false, EndDistance = 0, RankingsId = new List(), OnlineUserId = 0, RouteId = routeId }; } Debug.Log("start"); endDistance = 0; videoLoading = FindObjectOfType(); } private IEnumerator Init() { yield return null; videoLoading.Init();//初始化loading页面 } protected override void Update() { timer -= Time.deltaTime; while (timer <= 0) { if (cyclingController == null) return; try { cyclingController.Run(null);//发送数据到tcp var onlineRiders = cyclingController.riders; CreateOnlineUser(onlineRiders); //解析tcp返回数据 if (isStart) { ComputePlayerRuntimeData(); ticks++; } } catch (Exception e) { Debug.Log(e.Message); } timer += 1f; } } //计算骑手的数据 private void ComputePlayerRuntimeData() { var riders = FindObjectsOfType(); foreach (var rider in riders) { rider.StartAction(); } //解决当前用户setActive(false)时仍能计算数据 if (CurrentPlayer != null && CurrentPlayer is VideoPlayer) { CurrentPlayer.StartAction(); } } public MapRouteRankingList GetRankingList(string type = "month") { var endTime = UIManager.Now == null ? DateTime.Now : UIManager.Now.GetDateTime(); var startTime = Helper.GetStartTime(endTime, type); var list = ConfigHelper.mapApi.GetRouteRanking(App.RouteIdParam, "1", 0, 10, "", startTime, endTime); if (list.result) { rankingList = list.data; } return rankingList; } //创建当前线路其他选手 private void CreateOnlineUser(List list) { list = list.Where(c => ((OnlineRiderModel)c).IsWatcher == false).OrderByDescending(c => c.IsSelf).ToList(); //断网移除所有用户 if (list.Count == 0) { ClearRiders(); return; } //删除离开的用户 RemovePlayers(list); //如果当前为观察者模式且currentPlayerInfo为null随机选择以为用户观察 var current = DefaultCurrentPlayer(list); //更新和新增用户 UpdateRiders(list, current); } //断网清空当前线路所有用户 private void ClearRiders() { foreach (var item in visibleRiders) { DestroyImmediate(item.gameObject); } rideObjs.Clear(); visibleRiders.Clear(); CurrentPlayer = null; } //默认当前用户1.当前骑行模式下是当前用户 2.观察者模式下随机第一个用户 private BaseRider DefaultCurrentPlayer(List list) { var current = CurrentUserId == 0 ? list.FirstOrDefault() : list.FirstOrDefault(c => c.UserId == CurrentUserId); if(CurrentUserId == 0 && current != null) CurrentUserId = current.UserId; return current; } private void UpdateRiders(List list,BaseRider current) { //更新和新增用户 foreach (var item in list) { var onlineRider = item as OnlineRiderModel; var visibleItem = visibleRiders.FirstOrDefault(c => c.UserId == item.UserId); if (visibleItem != null) { visibleItem.SetPlayer(onlineRider.NickName, onlineRider.Speed, onlineRider.PreDistance, onlineRider.EndDistance, item.Cadence, item.HeartRate, onlineRider.WeightKg, item.UserId, onlineRider.Power, current.EndDistance, onlineRider.FrameRate.Value); if (visibleItem.userId == CurrentUserId) { CurrentPlayer = visibleItem; } } else { var distance = item.EndDistance % mapData.TotalDistance - current.EndDistance % mapData.TotalDistance; if (!(Math.Abs(distance * 1000) <= MaxVisibleDistance)) continue; if (item.IsSelf) { CreateVideoPlayer(onlineRider,item,current); } else { CreateOnlinePlayer(onlineRider,item,visibleItem,current); } } } } private void CreateOnlinePlayer(OnlineRiderModel onlineRider,BaseRider item,AbstractVideoPlayer visibleItem,BaseRider current) { var obj = CreatePlayerGameObject(false, onlineRider.Sex == 1); var online = obj.GetComponentInChildren(); var rideObj = obj.GetComponentInChildren(); online.SetStartDistance(item.EndDistance); rideObj.Distance = (float)online.StartDistance; rideObj.RouteDistance = rideObj.Distance; rideObj.UserId = item.UserId; rideObjs.Add(online, rideObj); visibleRiders.Add(online); _trainingController.AddRider(onlineRider); online.SetPlayer(onlineRider.NickName, onlineRider.Speed, onlineRider.PreDistance, onlineRider.EndDistance, item.Cadence, item.HeartRate, onlineRider.WeightKg, item.UserId, onlineRider.Power, current.EndDistance, onlineRider.FrameRate.Value); if (online.userId == CurrentUserId) { CurrentPlayer = visibleItem; } } private void CreateVideoPlayer(OnlineRiderModel onlineRider,BaseRider item,BaseRider current) { videoPlayer = CreatePlayerGameObject(true, App.CurrentUser.Sex == 1); CurrentUserId = App.CurrentUser.Id; CurrentPlayer = videoPlayer.GetComponent(); var vp = videoPlayer.GetComponent(); vp.SetEndDistance(item.EndDistance); CurrentPlayer.SetStartDistance(item.EndDistance); var rideObj = videoPlayer.GetComponent(); rideObj.Distance = (float)CurrentPlayer.StartDistance; rideObj.RouteDistance = rideObj.Distance; rideObj.IsMain = true; rideObj.UserId = item.UserId; rideObjs.Add(CurrentPlayer, rideObj); visibleRiders.Add(CurrentPlayer); CurrentPlayer.SetPlayer(onlineRider.NickName, onlineRider.Speed, onlineRider.PreDistance, onlineRider.EndDistance, item.Cadence, item.HeartRate, onlineRider.WeightKg, item.UserId, onlineRider.Power, current.EndDistance, onlineRider.FrameRate.Value); } private GameObject CreatePlayerGameObject(bool self,bool isMale) { return self ? Instantiate(isMale ? Player : Player_NV, transform) : Instantiate(isMale ? OnlinePlayer : OnlinePlayer_NV, transform); } //移除退出的选手 private void RemovePlayers(List list) { var players = FindObjectsOfType(); foreach (var item in players) { var currentItem = list.FirstOrDefault(c => c.UserId == item.UserId); if (currentItem != null) continue; rideObjs.Remove(item); visibleRiders.Remove(item); } } //设置当前是骑行模式还是观察模式 public void SetCurrentMode(ARMode aRMode) { _aRMode = aRMode; _uiManager.SetCurrentMode(aRMode); if (_aRMode != ARMode.INSPECT) { CurrentUserId = App.CurrentUser.Id; ContinueAsync(); } else { SetCyclingModel(CyclingModel.Single); } } //切换人物 public void ChangePlayer(int userId) { Debug.Log($"切换到{userId}"); CurrentUserId = userId; } //获取角色头顶信息预制件 public GameObject GetHeadInfo() { return infoPanel; } //继续骑行 public void ContinueAsync() { //骑行结果 if (App.routeResult != null) { routeResult = App.routeResult; selectParamModel = App.routeResult.ContinueCyclingParam; Debug.Log("selectParamModel"+ selectParamModel.ContinueMark); SetCyclingModel(CyclingModel.Single); endDistance = routeResult.EndDistance; App.routeResult = null; //mediaPlayer.Control.SeekToFrame(routeResult.LastFrame ?? 0); } } //设置骑行模式 public void SetCyclingModel(CyclingModel mode) { this.cyclingModel = mode; switch (cyclingModel) { case CyclingModel.Single: cyclingController = new ARSingleModel(route, selectParamModel); break; case CyclingModel.GameRoom: cyclingController = new GameModel(route, selectParamModel); break; } } //开始游戏 public void StartGame() { //if (startTime != DateTime.MinValue) { startTime = UIManager.Now.GetDateTime(); } isStart = true; } //骑行是否开始 public bool IsStart() { return isStart; } //获取UI public Transform GetCanvasTransform() { return transform.Find("Canvas/Panel"); } //设置视频源文件 public void SetMedia(string path) { if (mediaPlayer != null) { mediaPlayer.OpenMedia(new MediaPath(path,MediaPathType.AbsolutePathOrURL),false); } } //是否停止 public bool IsQuit() { return isStop; } //暂停 public void Pause() { isStart = !isStart; isStop = !isStop; } //退出骑行 public void Quit() { mediaPlayer?.Pause();//暂停视频 isStart = false; isStop = true; mediaPlayer?.Stop(); } //获取当前视频帧数 public int GetCurrentFrame() { return mediaPlayer.Control.GetCurrentTimeFrames(); } //获取AR骑行配置信息 //获取路书gps信息 public MapDataModel GetMapData() { if (mapData == null) { var mapApi = ConfigHelper.mapApi; int routeId = App.RouteIdParam; if(routeId > 0) mapData = mapApi.GetData(routeId,0);//获取路书地理数据 } return mapData; } //获取路书信息 public MapRoute GetMapRoute() { if (mapRoute == null) { var mapApi = ConfigHelper.mapApi; int routeId = App.RouteIdParam; mapRoute = mapApi.GetById(routeId).data; } return mapRoute; } public void ShowUpRemainTime(double remain) { _uiManager.ShowUpRemainTime(remain); } //保存骑行记录 public void SaveData(double totalDistance) { if (cyclingController.recorderData == null || cyclingController.recorderData.Saved) return; Quit(); cyclingController.recorderData.EndTime = UIManager.Now.GetDateTime(); var path = PFConstants.MapWorkoutRecordFolder + "/" + recordId; Helper.CreateDirectoryIfNotExsit(path); var imageFileName = path + "/" + Guid.NewGuid().ToString() + ".png"; Helper.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.IsCompleted = totalDistance >= mapData.TotalDistance; cyclingController.recorderData.EndDistance = cyclingController.recorderData.IsCompleted ? mapData.TotalDistance : totalDistance; cyclingController.recorderData.AntModelId = AntModelId; cyclingController.recorderData.ManufacturerId = ManufacturerId; cyclingController.recorderData.ManufacturerName = ManufacturerName; cyclingController.recorderData.DeviceNumber = DeviceNumber; cyclingController.recorderData.LastFrame = GetCurrentFrame(); RankingId = cyclingController.recorderData.SaveWithLocalRecordAysnc(cyclingModel, selectParamModel, imageFileName, recordId, path); } public void AddEvent(GameObject sender, EventTriggerType eventType, UnityAction unityAction) { UIManager.AddEvent(sender, eventType, unityAction); } public Texture GetCountryImageByCode(string code) { return UIManager.Instance.loginRegOptions.GetCountryImage(code); } public Texture GetCountryImageByName(string name) { return UIManager.Instance.loginRegOptions.GetCountryImageByName(name); } 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); } } private void OnDestroy() { App.gameRoomDetail = null; } public enum ARMode { RIDE, INSPECT } public enum ViewMode { THIRD, FIRST, } } }