powerfun-unity/Assets/Scripts/Scenes/AR/VideoGameManager.cs
2023-05-15 19:02:41 +08:00

524 lines
19 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.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<IRider, PlayerRenderer> rideObjs = new Dictionary<IRider, PlayerRenderer>();
private VideoUIManager _uiManager { get; set; }
private ARTrainingController _trainingController { get; set; }
public List<AbstractVideoPlayer> visibleRiders = new List<AbstractVideoPlayer>();//当前线路上的人
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<VideoUIManager>();
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");
_trainingController = GetComponent<ARTrainingController>();
StartCoroutine(Init());
}
private 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
};
}
Debug.Log("start");
endDistance = 0;
videoLoading = FindObjectOfType<VideoLoading>();
}
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<OnlineVideoPlayer>();
foreach (var rider in riders)
{
rider.StartAction();
}
//解决当前用户setActivefalse时仍能计算数据
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<BaseRider> 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<BaseRider> 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<BaseRider> 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<OnlineVideoPlayer>();
var rideObj = obj.GetComponentInChildren<PlayerRenderer>();
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<AbstractVideoPlayer>();
var vp = videoPlayer.GetComponent<VideoPlayer>();
vp.SetEndDistance(item.EndDistance);
CurrentPlayer.SetStartDistance(item.EndDistance);
var rideObj = videoPlayer.GetComponent<PlayerRenderer>();
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<BaseRider> list)
{
var players = FindObjectsOfType<OnlineVideoPlayer>();
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<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);
}
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,
}
}
}