2022-12-05 18:29:49 +08:00

507 lines
20 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using Helper = Assets.Scenes.Ride.Scripts.Helper;
using System.Collections;
using FluffyUnderware.Curvy.Examples;
using FluffyUnderware.Curvy.Controllers;
using FluffyUnderware.Curvy;
using System.Reflection;
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;
public RouteResult routeResult;
public string recordId { get; set; }
public DateTime startTime { get; set; }
public CyclingModel cyclingModel;
public BaseCycling cyclingController { get; set; }
private double endDistance { get; set; }
GameObject infoPanel;
GameObject Player;
GameObject Player_NV;
GameObject OnlinePlayer;
GameObject OnlinePlayer_NV;
private bool isStop { get; set; }
public enum ARMode
{
RIDE,
INSPECT
}
public enum ViewMode
{
THIRD,
FIRST,
}
VideoLoading videoLoading { get; set; }
//当前是第一人称还是第三人称
public ViewMode _viewMode { get; set; }
//当前是观察者视角还是骑行者视角
public ARMode _aRMode { get; set; }
public int RankingId { get; set; }
public Dictionary<IRider,RiderRenderer> rideObjs = new Dictionary<IRider, RiderRenderer>();
protected override void Awake()
{
base.Awake();
trainingController = GetComponent<ARTrainingController>();
mediaPlayer = FindObjectOfType<MediaPlayer>();
DeviceCache.Init(PFConstants.DeviceCacheFolder);
var check = CheckAnt();//初始化蓝牙设备
recordId = Guid.NewGuid().ToString();
infoPanel = Resources.Load<GameObject>("UI/Prefab/AR/VideoPlayerHead");
OnlinePlayer = Resources.Load<GameObject>("UI/Prefab/AR/OnlineVideoPlayer");
OnlinePlayer_NV = Resources.Load<GameObject>("UI/Prefab/AR/OnlineVideoPlayer_NV");
Player = Resources.Load<GameObject>("UI/Prefab/AR/VidePlayer");
Player_NV = Resources.Load<GameObject>("UI/Prefab/AR/VidePlayer_NV");
StartCoroutine(Init());
}
void Start()
{
UIManager.Instance.MainPanel = GetCanvasTransform().GetComponent<PFUIPanel>();
UIManager.Instance.ModalsPanel = this.transform.Find("Canvas/ModalPanel").GetComponent<PFUIPanel>();
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<string>(),
OnlineUserId = 0,
RouteId = routeId
};
}
endDistance = 0;
videoLoading = FindObjectOfType<VideoLoading>();
}
private IEnumerator Init()
{
yield return null;
videoLoading.Init();//初始化loading页面
}
float timer = 0f;
protected override void Update()
{
timer -= Time.deltaTime;
while (timer <= 0)
{
if (cyclingController == null)
return;
cyclingController.Run(null);
var onlineRiders = cyclingController.riders;
try
{
CreateOnlineUser(onlineRiders);
}
catch (Exception e)
{
Debug.Log(e.Message);
}
timer += 1f;
}
}
MapRouteRankingList rankingList;
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;
}
List<AbstractVideoPlayer> visibleRiders = new List<AbstractVideoPlayer>();//当前线路上的人
private const int limits = 5;//在线的其他人数
private double MaxVisibleDistance = 200d;//最大显示距离
//创建当前线路其他选手
private void CreateOnlineUser(List<BaseRider> list)
{
if (list == null || list.Count == 0)
{
return;
}
CreateCurrentPlayer(list);//如果是观察者模式创建观察主人工
var onlinelist = MapUDPService.GetOnlineUsers(App.RouteIdParam);//最新列表
var currentPlayerInfo = onlinelist.Where(c => c.Id == CurrentPlayer.UserId).FirstOrDefault();
//移除退出的选手
var players = FindObjectsOfType<OnlineVideoPlayer>();
foreach (var item in players)
{
var currentItem = list.Where(c => c.UserId == item.UserId).FirstOrDefault();
if (currentItem == null)
{
rideObjs.Remove(item);
visibleRiders.Remove(item);
//item.Destroy();//TODO:
}
}
var needUpdateList = list.Where(c=>Math.Abs(c.EndDistance-CurrentPlayer.totalDistance)*1000 <= MaxVisibleDistance).Take(limits).ToList();
foreach (var item in needUpdateList)
{
var onlineRider = item as OnlineRiderModel;
var visibleItem = visibleRiders.Where(c => c.UserId == item.UserId).FirstOrDefault();
//更新
if (visibleItem != null)
{
var online = visibleItem as OnlineVideoPlayer;
online.SetPlayer(onlineRider.NickName, onlineRider.EndDistance - onlineRider.PreDistance, onlineRider.EndDistance, item.Cadence, item.HeartRate, onlineRider.WeightKg, item.UserId, onlineRider.Power, currentPlayerInfo.EndDistance, onlineRider.FrameRate.Value);
}
else
{
if (currentPlayerInfo != null)
{
var diff = item.EndDistance % mapData.TotalDistance - currentPlayerInfo.EndDistance % mapData.TotalDistance;
if (Math.Abs(diff * 1000) <= MaxVisibleDistance)
{
GameObject obj;
if (onlineRider.Sex == 1)
{
obj = Instantiate(OnlinePlayer, transform);
}
else
{
obj = Instantiate(OnlinePlayer_NV, transform);
}
var online = obj.GetComponentInChildren<OnlineVideoPlayer>();
var rideObj = obj.GetComponentInChildren<RiderRenderer>();
rideObjs.Add(online,rideObj);
visibleRiders.Add(online);
online.SetPlayer(onlineRider.NickName, onlineRider.EndDistance - onlineRider.PreDistance, onlineRider.EndDistance, item.Cadence, item.HeartRate, onlineRider.WeightKg, item.UserId, onlineRider.Power, currentPlayerInfo.EndDistance, onlineRider.FrameRate.Value);
}
}
}
}
}
//观察者模式随机选择当前骑行的人作为观察对象
private void CreateCurrentPlayer(List<BaseRider> list)
{
if (_aRMode == ARMode.INSPECT && CurrentPlayer == null)
{
var currentPlayer = list.FirstOrDefault();
if (currentPlayer != null)
{
var onlineRider = currentPlayer as OnlineRiderModel;
GameObject obj;
if (onlineRider.Sex == 1)
{
obj = Instantiate(OnlinePlayer, transform);
}
else
{
obj = Instantiate(OnlinePlayer_NV, transform);
}
var online = obj.GetComponent<OnlineVideoPlayer>();
online.SetPlayer(onlineRider.NickName, onlineRider.EndDistance - onlineRider.PreDistance, onlineRider.EndDistance, onlineRider.Cadence, onlineRider.HeartRate, onlineRider.TotalTicks, onlineRider.UserId, onlineRider.Power, onlineRider.EndDistance, onlineRider.FrameRate.Value);
obj.transform.DOMoveX(0, 1);
ChangePlayer(currentPlayer.UserId);
CurrentPlayer = online;
}
}
}
//设置当前是骑行模式还是观察模式
public void SetCurrentMode(ARMode aRMode)
{
_aRMode = aRMode;
var uimanager = FindObjectOfType<VideoUIManager>();
uimanager.SetCurrentMode(aRMode);
if (_aRMode != ARMode.INSPECT)
{
InitCurrentPlayer();
ContinueAsync();
}
else
{
SetCyclingModel(CyclingModel.Single);
}
}
public GameObject videoPlayer;
public GameObject target;
//初始化人物模型
public void InitCurrentPlayer()
{
if (App.CurrentUser.Sex == 1)
{
var playerprefab = Resources.Load<GameObject>("UI/Prefab/AR/VidePlayer");
videoPlayer = Instantiate(playerprefab, transform);
}
else
{
var playerprefabNV = Resources.Load<GameObject>("UI/Prefab/AR/VidePlayer_NV");
videoPlayer = Instantiate(playerprefabNV, transform);
}
CurrentPlayer = videoPlayer.GetComponent<AbstractVideoPlayer>();
}
//切换人物 TODO:替换写法
public void ChangePlayer(int userId)
{
var players = FindObjectsOfType<OnlineVideoPlayer>();
if (players != null)
{
CurrentPlayer = players.Where(c => c.UserId == userId).FirstOrDefault();
if (CurrentPlayer == null)
{
var onlineRiders = cyclingController.riders;
var currentPlayer = onlineRiders.Where(c => c.UserId == userId).FirstOrDefault();
if (currentPlayer != null)
{
var onlineRider = currentPlayer as OnlineRiderModel;
var obj = Instantiate(OnlinePlayer, transform);
var online = obj.GetComponent<OnlineVideoPlayer>();
online.SetPlayer(onlineRider.NickName, onlineRider.EndDistance-onlineRider.PreDistance, onlineRider.EndDistance, onlineRider.Cadence, onlineRider.HeartRate, 0, onlineRider.UserId, onlineRider.Power, onlineRider.EndDistance, onlineRider.FrameRate.Value);
CurrentPlayer = online;
}
var clearList = players.Where(c => c.UserId != userId);
foreach (var item in clearList)
{
item.Destroy();
}
}
}
}
//获取角色头顶信息预制件
public GameObject GetHeadInfo()
{
return infoPanel;
}
//骑行记录
public void ContinueAsync()
{
//骑行结果
if (App.routeResult != null)
{
routeResult = App.routeResult;
selectParamModel = App.routeResult.ContinueCyclingParam;
SetCyclingModel(CyclingModel.Single);
endDistance = routeResult.EndDistance;
//TODO继续骑行
mediaPlayer.Control.SeekToFrame(routeResult.LastFrame ?? 0);
var v = FindObjectOfType<VideoPlayer>();
v.SetEndDistance(endDistance);
}
}
//设置骑行模式
public void SetCyclingModel(CyclingModel mode)
{
startTime = UIManager.Now.GetDateTime();
this.cyclingModel = mode;
switch (cyclingModel)
{
case CyclingModel.Single:
cyclingController = new SingleModel(route, selectParamModel);
break;
case CyclingModel.GameRoom:
cyclingController = new GameModel(route, selectParamModel);
break;
}
}
//开始游戏
public void StartGame()
{
if (startTime == null)
{
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)
{
return;
if (mediaPlayer != null)
{
mediaPlayer.OpenMedia(new MediaPath(path,MediaPathType.AbsolutePathOrURL),false);
}
}
//是否停止
public bool IsQuit()
{
return isStop;
}
double preframe = 0;
double preDistance = 0;
//暂停
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();
}
Vector3 currentCameraRotation = Vector3.zero;
Vector3 mVelocity;
float prePos = 0f;
public float ratio = 111.676f;
public float startOffset = 0f;
//获取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 Save(double totalDistance)
{
Quit();
cyclingController.recorderData.EndTime = UIManager.Now.GetDateTime();
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();
RankingId = cyclingController.recorderData.SaveWithLocalRecordAysnc(cyclingModel, selectParamModel, imageFileName, recordId, path);
}
public void AddEvent(GameObject sender, EventTriggerType eventType, UnityAction<BaseEventData> 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);
}
//截图
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);
}
}
private void OnDestroy()
{
App.gameRoomDetail = null;
}
}
}