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; namespace Assets.Scripts.Scenes.VideoRide { public class VideoGameManager : DeviceServiceMonoBase { private List videoPointList { get; set; } private VideoPlayer currentVideoPlayer { 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 Dictionary slots = new Dictionary(); Transform cube; private async void Awake() { base.Awake(); //自动登录 if (App.CurrentUser == null) { await Login(); } DeviceCache.Init(PFConstants.DeviceCacheFolder); //var check = CheckAnt(); recordId = Guid.NewGuid().ToString(); startTime = UIManager.Now.GetDateTime(); MapUDPService.Init();//初始化TCP MockDirection(); InitSlots(); } void Start() { cube = transform.Find("Cube"); //获取媒体播放器 mediaPlayer = FindObjectOfType(); var mapApi = ConfigHelper.mapApi; const int routeId = 12353; mapData = mapApi.GetData(routeId);//获取路书地理数据 mapRoute = mapApi.GetById(routeId).data; 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 }; } 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; timer += 1f; } var p = FindObjectOfType(); if (p.distance > 0) { preFrame = currentFrame; currentFrame = GetCurrentFrame(); var dd = (currentFrame - preFrame) / 200f * cube.position.z; cube.DOMoveZ((float)(cube.position.z - dd), 0f); } } private void InitSlots() { slots.Add(2, true); slots.Add(4, true); slots.Add(-2, true); slots.Add(-6, true); slots.Add(-4, true); slots.Add(-8, true); } public int? GetSlotIndex() { foreach (var item in slots) { if (item.Value) { slots[item.Key] = false; return item.Key; } } return 0; } 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("15261826280", "123456", ""); App.CurrentUser = result.data; } //开始游戏 public void StartGame() { startTime = UIManager.Now.GetDateTime(); isStart = true; } public bool IsStart() { return isStart; } //按照某种速度播放视频 public void Play(float playbackRate = 1f) { if (mediaPlayer != null) { mediaPlayer.PlaybackRate = playbackRate; mediaPlayer.Play(); } } //暂停游戏 public void Pause() { mediaPlayer?.Pause(); } public void Quit() { mediaPlayer?.Stop(); } int preFrame = 0; int currentFrame = 0; public int GetCurrentFrame() { return mediaPlayer.Control.GetCurrentTimeFrames(); } public void SetCurrentFrame(int seq) { mediaPlayer?.Control.SeekToFrame(seq); } 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); //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)); } private byte[] CaptureCameraReturnByte(Camera camera, Rect rect) { // 创建一个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); // 最后将这些纹理数据,成一个图片文件 return screenShot.EncodeToJPG(); } //两个坐标之间的距离 public double Distance(Vector2d from, Vector2d to) { var pt1 = Turf.Point(new double[] { from.x, from.y }); var pt2 = Turf.Point(new double[] { to.x, to.y }); return Turf.Distance(pt1, pt2); } //根据距离计算下一个点坐标 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 MapDataModel GetMapData() { return mapData; } public float GetPlayRatio() { return mediaPlayer.Control.GetPlaybackRate(); } public List getVideoPointList() { return videoPointList; } } }