using Assets.Scenes.Ride.Scripts; using Assets.Scenes.Ride.Scripts.Model; using Assets.Scenes.Ride.Scripts.Model.CyclingModels; using Assets.Scripts.Apis; 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 System.Threading.Tasks; using TurfCS; using UnityEngine; using DG.Tweening; using Assets.Scenes.Ride.Scripts.Model.RiderModels; namespace Assets.Scripts.Scenes.VideoRide { public class VideoGameManager : DeviceServiceMonoBase { private List videoPointList { get; set; } 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; } private MapRoute mapRoute { get; set; } public RouteResultParam selectParamModel; public RouteResult routeResult; public string recordId { get; set; } public DateTime startTime { get; set; } public CyclingModel cyclingModel; public BaseCycling cyclingController; public Dictionary mockDirection = new Dictionary(); private double endDistance { get; set; } public List slots = new List(); GameObject infoPanel; GameObject OnlinePlayer; private async void Awake() { base.Awake(); mediaPlayer = FindObjectOfType(); //自动登录 if (App.CurrentUser == null) { await Login(); } DeviceCache.Init(PFConstants.DeviceCacheFolder); //var check = CheckAnt();//初始化蓝牙设备 recordId = Guid.NewGuid().ToString(); MapUDPService.Init();//初始化TCP MockDirection(); infoPanel = Resources.Load("UI/Prefab/Ride/OnlineInfoPanel"); OnlinePlayer = Resources.Load("UI/Prefab/OnlineVideoPlayer"); } void Start() { InitSlots(); startTime = DateTime.Now;//UIManager.Now.GetDateTime(); var videoPlayer = FindObjectOfType(); var mapApi = ConfigHelper.mapApi; const int routeId = 12353; mapData = mapApi.GetData(routeId);//获取路书地理数据 mapRoute = mapApi.GetById(routeId).data; route = new Route(mapData, mapRoute); CurrentPlayer = videoPlayer; if (selectParamModel == null) { selectParamModel = new RouteResultParam { CompetitionId = 0, ContinueIndex = 0, ContinueMark = "", GlobalContinue = false, EndDistance = 0, RankingsId = new List(), OnlineUserId = 0, RouteId = routeId }; } endDistance = 0; //倒计时5s开始 SetCyclingModel(CyclingModel.Single); } // Update is called once per frame float timer = 1f; void Update() { timer -= Time.deltaTime; while (timer <= 0) { cyclingController?.Run(null); var onlineRiders = cyclingController.riders; Debug.Log($"当前在线人数:{ MapUDPService.GetAllOnlineUserCount()}"); CreateOnlineUser(onlineRiders); timer += 1f; } } private int offSet = 50; private int currentOnlineCount = 0; //创建当前线路其他选手 private void CreateOnlineUser(List list) { var players = FindObjectsOfType(); var current = FindObjectOfType(); //移除 foreach (var item in players) { var currentItem = list.Where(c => c.UserId == item.UserId).FirstOrDefault(); if (currentItem == null) { item.Destroy(); currentOnlineCount--; } } //新增/更新 var pagedList = list.Take(5).ToList(); foreach (var item in pagedList) { var onlineRider = item as OnlineRiderModel; var exsit = players.Where(c => c.UserId == item.UserId).FirstOrDefault(); if (exsit != null) { var online = exsit.GetComponent(); online.SetPlayer(onlineRider.EndDistance, item.Cadence, item.HeartRate, item.UserId); } else { var diff = item.EndDistance - current.EndDistance; if (diff < offSet) { var obj = Instantiate(OnlinePlayer, transform); var online = obj.GetComponent(); Debug.Log($"{onlineRider.EndDistance}={item.Power}={onlineRider.PreDistance}"); online.SetPlayer(onlineRider.EndDistance, item.Cadence, item.HeartRate,item.UserId); obj.transform.DOMoveX(slots[currentOnlineCount], 1); currentOnlineCount++; } } } } //切换人物 public void ChangePlayer(int userId) { var players = FindObjectsOfType(); if (players != null) { CurrentPlayer = players.Where(c => c.UserId == userId).FirstOrDefault(); if (CurrentPlayer != null) { var currentFrames = DistanceToFrames(CurrentPlayer.totalDistance); //获取当前人物的帧数 SetCurrentFrame(currentFrames); } } } //初始化骑行选手横向插槽 private void InitSlots() { for (float i = -2f; i <= 2; i+=0.5f) { if (i != 0) { slots.Add(i); } } slots = slots.OrderBy(c => Math.Abs(c)).ToList(); } //获取角色头顶信息预制件 public GameObject GetHeadInfo() { return infoPanel; } //骑行记录 public async Task ContinueAsync() { //继续骑行数据 var r = await ConfigHelper.mapInterruptRecordApi.GetMapInterruptRecord("重庆", 0, 20, "routes"); if (r.result) { var first = r.data.FirstOrDefault(); RouteResult routeResult = first.ToObject(); if (routeResult.ContinueCyclingParam != null) { App.RouteIdParam = routeResult.RouteId; App.routeResult = routeResult; //骑行结果 if (App.routeResult != null) { routeResult = App.routeResult; selectParamModel = App.routeResult.ContinueCyclingParam;//继续骑行 SetCyclingModel(CyclingModel.Single); endDistance = routeResult.EndDistance; var ratio = endDistance / routeResult.TotalDistance; var frame = Math.Round(ratio * mediaPlayer.Info.GetMaxFrameNumber()); SetCurrentFrame(routeResult.LastFrame ?? 0); var v = FindObjectOfType(); v.SetEndDistance(endDistance); } } } } private void MockDirection() { var text = Resources.Load("UI/direction"); var arr = text.text.Replace("\r\n", ",").Split(','); foreach (var item in arr) { if (string.IsNullOrEmpty(item)) continue; mockDirection.Add(Convert.ToInt32(item.Split(':')[0]), Convert.ToInt32(item.Split(':')[1])); } } //设置骑行模式 public void SetCyclingModel(CyclingModel mode) { this.cyclingModel = mode; switch (cyclingModel) { case CyclingModel.Single: cyclingController = new SingleModel(route, selectParamModel); break; } } //模拟登录 private async Task Login() { var result = await new UserApi().Login("anyway2019@163.com", "123456", ""); App.CurrentUser = result.data; } //开始游戏 public void StartGame() { 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 void Play(float playbackRate = 1f) { if (mediaPlayer != null) { mediaPlayer.PlaybackRate = 1;//TODO:playbackRate; mediaPlayer.Play(); } } //暂停 public void Pause() { mediaPlayer?.Pause(); } //退出骑行 public void Quit() { mediaPlayer?.Stop(); } //获取当前视频帧数 public int GetCurrentFrame() { return mediaPlayer.Control.GetCurrentTimeFrames(); } //距离换算成视频帧数 public int DistanceToFrames(double distance) { var frames = mediaPlayer.Info.GetMaxFrameNumber(); //视频打开后生效 var TotalDistance = route?.TotalDistance ?? 0; return TotalDistance > 0 ? Convert.ToInt32(frames / TotalDistance * distance) : 0; } //设置当前视频播放进度 public void SetCurrentFrame(int seq) { mediaPlayer?.Control.SeekToFrame(seq); } //获取路书信息 public MapDataModel GetMapData() { return mapData; } //保存骑行记录 public void Save(double totalDistance) { mediaPlayer?.Pause();//暂停视频 cyclingController.recorderData.EndTime = UIManager.Now.GetDateTime(); isStart = false; var path = PFConstants.MapWorkoutRecordFolder + "/" + recordId; Assets.Scenes.Ride.Scripts.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.IsCompleted = totalDistance >= mapData.TotalDistance; cyclingController.recorderData.EndDistance = totalDistance; cyclingController.recorderData.AntModelId = AntModelId; cyclingController.recorderData.ManufacturerId = ManufacturerId; cyclingController.recorderData.ManufacturerName = ManufacturerName; cyclingController.recorderData.DeviceNumber = DeviceNumber; cyclingController.recorderData.LastFrame = GetCurrentFrame(); var RankingId = cyclingController.recorderData.SaveWithLocalRecordAysnc(cyclingModel, selectParamModel, imageFileName, recordId, path); } //截图 protected void CaptureCamera(Camera camera, Rect rect, string fileName) { byte[] bytes = CaptureCameraReturnByte(camera, rect); System.IO.File.WriteAllBytes(fileName, bytes); } private byte[] CaptureCameraReturnByte(Camera camera, Rect rect) { RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 0); camera.targetTexture = rt; camera.Render(); RenderTexture.active = rt; Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false); screenShot.ReadPixels(rect, 0, 0); screenShot.Apply(); camera.targetTexture = null; RenderTexture.active = null; GameObject.Destroy(rt); return screenShot.EncodeToJPG(); } //根据距离计算下一个点坐标 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); } } } }