1325 lines
48 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.Scripts.Apis;
using Assets.Scripts.Apis.Models;
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
using Assets.Scenes.Ride.Scripts.Model;
using Assets.Scenes.Ride.Scripts.Model.CyclingModels;
using Assets.Scenes.Ride.Scripts;
using Mapbox.Unity.Map;
using UnityEngine;
using GeoJSON.Net.Geometry;
using TurfCS;
using Mapbox.Utils;
using Assets.Scripts;
using System.Threading.Tasks;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using Assets.Scenes.Ride.Scripts.Model.RiderModels;
using System.IO;
using ChartAndGraph;
using UnityEngine.UI;
using System.Diagnostics;
using UnityEngine.SceneManagement;
using DG.Tweening;
using System.Timers;
public class CyclingController : DeviceServiceMonoBase
{
public AbstractMap map;
public GameObject player;
public GameObject UIObject;
public RouteResultParam selectParamModel;
public RouteResult routeResult;
public GameObject minicamera;
public Dictionary<int, SeletedPlayerScript> selectPlayerDic { set; get; } = new Dictionary<int, SeletedPlayerScript>();
public int preticks { get; set; }
#region
public MapRoute mapRoute { get; set; }//当前路书数据
public MapCompetition competition { get; set; }//当前赛事数据
private MapDataModel mapData { get; set; }//当前路书数据
private Route route { get; set; }//当前路书综合数据
public List<MapRouteRanking> mapRouteRankingList { get; set; }
private Vector2d coordiantes;//当前地图中心
public bool isStart { get; set; }//当前游戏是否开始
public CyclingModel cyclingModel { get; set; }//当前骑行模式
public BaseCycling cyclingController { get; set; }
private int routeId;
public int competitionId { get; set; }
private MapApi mapApi;
public DateTime startTime { get; set; }
public DateTime endTime;
public bool isQuit;
public bool isPause;
#endregion
GameObject loadingcanvas;
AbstratctLoadingController loadingController;
private async Task Login()
{
var result = await new UserApi().Login("15261826280", "123456", "");
App.CurrentUser = result.data;
}
GameObject miniMap { get; set; }
GameObject resultPanel;
public ChartDataSourceScript chartDataSourceScript { get; set; }
public GraphChartBase graph { get; set; }
private float activeSeconds { get; set; }//移动端用户进入骑行超过2min界面进入沉浸状态
protected override void Awake()
{
base.Awake();
#if UNITY_EDITOR
if (App.CurrentUser == null)
{
Login();
}
#endif
//获取路书信息
mapApi = ConfigHelper.mapApi;
routeId = App.RouteIdParam > 0 ? App.RouteIdParam : 2633;
competitionId = App.CompetionId;
App.CompetionId = 0;//清空比赛参数
//处理异常中断的骑行
if (App.tempRecordData != null)
{
selectParamModel = App.tempRecordData.selectParam;
competitionId = App.tempRecordData.CompetitionId;
routeId = App.tempRecordData.RouteId;
}
Resources.UnloadUnusedAssets();
}
void OnDestroy()
{
//MapUDPService.Dispose();
TouchKit.removeAllGestureRecognizers();
Resources.UnloadUnusedAssets();
GC.Collect();
}
Transform target;
GameObject watcher;
Transform uiParent;
GameObject uipanel { get; set; }
GameObject onlineUserPrefab3d { get; set; }
GameObject OnlineHeadPanel { get; set; }
public GameObject GetOnlineheadPanel()
{
if (OnlineHeadPanel == null)
{
OnlineHeadPanel = Resources.Load<GameObject>("UI/Prefab/Ride/OnlineHeadPanel");
}
return OnlineHeadPanel;
}
Material Graph3d { get; set; }
Material Graph4 { get; set; }
Material Graph1 { get; set; }
public Material Get3dGraph2()
{
if (Graph3d == null)
{
Graph3d = Resources.Load<Material>("UI/Material/3dGraph2");
}
return Graph3d;
}
public Material GetMaterial4()
{
if (Graph4 == null)
{
Graph4 = Resources.Load<Material>("UI/Material/4");
}
return Graph4;
}
public Material GetMaterial1()
{
if (Graph1 == null)
{
Graph1 = Resources.Load<Material>("UI/Material/1");
}
return Graph1;
}
Image CompetitionArrow { get; set; }
public Image GetCompetitionArrow()
{
if (CompetitionArrow == null)
{
CompetitionArrow = Resources.Load<Image>("UI/Prefab/Match/CompetitionArrow");
}
return CompetitionArrow;
}
Image CompetitionMobileArrow { get; set; }
public Image GetCompetitionMobileArrow()
{
if (CompetitionMobileArrow == null)
{
CompetitionMobileArrow = Resources.Load<Image>("UI/Prefab/Match/Mobile/CompetitionArrow");
}
return CompetitionMobileArrow;
}
public bool RotateLock = true;
private bool touchLock = true;
private void Start()
{
var uicanvasScaler = UIObject.GetComponent<CanvasScaler>();
var loadingcanvasScaler = transform.Find("LoadingCanvas").GetComponent<CanvasScaler>();
#if UNITY_ANDROID || UNITY_IOS
uipanel = Instantiate(Resources.Load<GameObject>("UI/Prefab/Ride/Mobile/Panel"), UIObject.transform);
uicanvasScaler.referenceResolution = App.MobileResolution;
loadingcanvasScaler.referenceResolution = App.MobileResolution;
#else
uipanel = Instantiate(Resources.Load<GameObject>("UI/Prefab/Ride/Panel"), UIObject.transform);
uicanvasScaler.referenceResolution = App.PcResolution;
loadingcanvasScaler.referenceResolution = App.PcResolution;
var modalRect = transform.Find("UI/ModalPanel").GetComponent<RectTransform>();
modalRect.anchorMin = new Vector2(0.5f, 0.5f);
modalRect.anchorMax = new Vector2(0.5f, 0.5f);
modalRect.offsetMin = Vector2.zero;
modalRect.offsetMax = Vector2.zero;
modalRect.sizeDelta = new Vector2(1600, 900);
#endif
uipanel.transform.SetAsFirstSibling();
uiParent = uipanel.transform;
resultPanel = uiParent.Find("ResultPanel").gameObject;
//获取海拔图UI对象
var graphObject = uiParent.Find("GraphChart");
chartDataSourceScript = graphObject.GetComponent<ChartDataSourceScript>();
graph = graphObject.GetComponent<GraphChartBase>();
UIManager.Instance.MainPanel = uipanel.GetComponent<PFUIPanel>();
UIManager.Instance.ModalsPanel = this.transform.Find("UI/ModalPanel").GetComponent<PFUIPanel>();
onlineUserPrefab = Resources.Load<GameObject>("UI/Prefab/Ride/EmptyOnlinePlayer");
onlineUserPrefab3d = Resources.Load<GameObject>("UI/Prefab/Match/onlinePlayerNoScript");
miniMapPlayerPrefab = Resources.Load<GameObject>("UI/Prefab/Ride/MiniMapPlayer");
watcher = Resources.Load<GameObject>("UI/Prefab/Match/Watcher");
target = transform.Find("Target");
miniMap = transform.Find("MiniMap").gameObject;//小地图
minicamera = transform.Find("MiniCamera").gameObject;
//进入倒计时
singleUIManager = UIObject.GetComponent<BaseUIManager>();
TrailRenderer trail = player.GetComponent<TrailRenderer>();
trail.Clear();
playerController = player.GetComponent<PlayerController>();
currentPlayer = playerController;//当前选中用户
if (competitionId > 0)
{
loadingController = transform.Find("LoadingCanvas").gameObject.AddComponent<CompetitionLoadingController>();
}
else
{
loadingController = transform.Find("LoadingCanvas").gameObject.AddComponent<LoadingController>();
}
//loadingController = FindObjectOfType<LoadingController>();
//
loadingController.InjectController(this);
SceneManager.activeSceneChanged += SceneManager_activeSceneChanged;
HandleTouchAndInput();
//进入比赛
if (competitionId > 0)
{
this.cyclingModel = CyclingModel.Competition;
StartCoroutine(InitRace());
return;
}
//进入单人骑行
if (routeId > 0)
{
StartCoroutine(Init());
return;
}
}
float timer = 1f;
bool clearLock = false;
private void SceneManager_activeSceneChanged(Scene arg0, Scene arg1)
{
ClearTempFile();
}
#region &PC鼠标的控制
private void HandleTouchAndInput()
{
var rotationRecognizer = new TKOneFingerRotationRecognizer
{
targetPosition = Camera.main.WorldToScreenPoint(target.position)
};
rotationRecognizer.gestureRecognizedEvent += (r) =>
{
if (Is3dView && IsPointerOverGameObject(r.startTouchLocation()))
{
RotateLock = false;
DOTween.Kill(target);
target.transform.Rotate(new Vector3(0, -1, 0), r.deltaRotation);
}
};
var timer = new Timer
{
Interval = 1000
};
timer.Elapsed += (s, e) =>
{
RotateLock = true;
timer.Stop();
};
rotationRecognizer.gestureCompleteEvent += (r) => {
UnityEngine.Debug.Log("gestureCompleteEvent");
timer.Start();
};
TouchKit.addGestureRecognizer(rotationRecognizer);
////单指
//var touchRecognizer = new TKAnyTouchRecognizer(new TKRect(0, 0, Screen.width, Screen.height));
//DateTime startTimpStamp = DateTime.Now;
//Vector2 touchLocation = Vector2.down;
//touchRecognizer.onEnteredEvent += (r) =>
//{
// touchLocation = r.startTouchLocation();
// startTimpStamp = DateTime.Now;
//};
//touchRecognizer.onExitedEvent += (r) =>
//{
// if (competitionId == 0 && isStart && IsPointerOverGameObject(touchRecognizer.STAR))
// {
// var timespan = DateTime.Now - startTimpStamp;
// UnityEngine.Debug.Log($"{timespan.TotalMilliseconds}");
// if (timespan.TotalMilliseconds <= 120)
// {
// singleUIManager?.ClearPanel(null);
// }
// }
//};
//TouchKit.addGestureRecognizer(touchRecognizer);
//双指
var PinchRecognizer = new TKPinchRecognizer();
PinchRecognizer.gestureRecognizedEvent += (r) =>
{
if (Is3dView && IsPointerOverGameObject(PinchRecognizer.startTouchLocation()))
{
if (cameraList == null)
{
cameraList = new List<Vector3>();
cameraList.Add(neareast);
cameraList.Add(near);
cameraList.Add(plane);
cameraList.Add(medium);
cameraList.Add(far);
}
var prePos = Camera.main.transform.localPosition;
var nextPos = Camera.main.transform.localPosition;
if (r.deltaScale < 0)
{
nextPos = cameraList.Where(c => c.y > Camera.main.transform.localPosition.y).FirstOrDefault();
if (nextPos != Vector3.zero)
Camera.main.transform.DOLocalMove(nextPos, 0.5f);
//StartCoroutine(MoveCamera(prePos, nextPos));
}
if (r.deltaScale > 0)
{
nextPos = cameraList.Where(c => c.y < Camera.main.transform.localPosition.y).LastOrDefault();
if (nextPos != Vector3.zero)
Camera.main.transform.DOLocalMove(nextPos, 0.5f);
//StartCoroutine(MoveCamera(prePos, nextPos));
}
}
};
TouchKit.addGestureRecognizer(PinchRecognizer);
}
/// <summary>
/// 检测是否点击UI
/// </summary>
/// <param name="mousePosition"></param>
/// <returns></returns>
private bool IsPointerOverGameObject(Vector2 mousePosition)
{
//创建一个点击事件
PointerEventData eventData = new PointerEventData(EventSystem.current);
eventData.position = mousePosition;
List<RaycastResult> raycastResults = new List<RaycastResult>();
//向点击位置发射一条射线检测是否点击UI
EventSystem.current.RaycastAll(eventData, raycastResults);
if (raycastResults.Count > 0)
{
return !raycastResults.Where(c => c.gameObject.name == "NearPanel" || c.gameObject.name == "ToolBarPanel" || c.gameObject.name == "SettingPanel" || c.gameObject.name == "QuitPanel").Any();
}
else
{
return false;
}
}
#endregion
bool _dragStartedOnUI = false;
protected override void Update()
{
base.Update();
//CamControl();
timer -= Time.deltaTime;
if (timer <= 0)//定时器 一秒执行一次
{
TcpHandler();
App.CurrentScene = "Ride";
if (competitionId == 0)
{
UIManager.SendCompetitionStartMessage("Ride");
}
#if UNITY_IOS || UNITY_ANDROID
//if (isStart)
//{
// activeSeconds++;
//}
//if (activeSeconds >= App.autoClearTimes && !clearLock)
//{
// if (competitionId == 0)
// {
// clearLock = true;
// singleUIManager?.ClearPanel(null);
// }
//}
#endif
timer += 1.0f;
}
}
float touchTimer = 0.1f;
private void FixedUpdate()
{
HandleTouch();
HandleMouseScrollWheel();
}
public bool isWatch { get; set; }
private Vector3 currentCameraPos { get; set; }
Vector3 far = new Vector3(-17, 52, -48);
Vector3 medium = new Vector3(-14.5f, 45, -40);
Vector3 plane = new Vector3(-10.5f, 35, -30); //new Vector3(-11.4f, 31, -30);
Vector3 near = new Vector3(-7.3f, 24, -20);
Vector3 neareast = new Vector3(-5.4f, 18, -15);
List<Vector3> cameraList { get; set; }
/// <summary>
/// 处理PC端
/// </summary>
private void HandleMouseScrollWheel()
{
var scrollDelta = Input.GetAxis("Mouse ScrollWheel");
if (scrollDelta != 0 && Input.mousePosition != null && !IsPointerOverGameObject(Input.mousePosition))
return;
if (cameraList == null)
{
cameraList = new List<Vector3>();
cameraList.Add(neareast);
cameraList.Add(near);
cameraList.Add(plane);
cameraList.Add(medium);
cameraList.Add(far);
}
var prePos = Camera.main.transform.localPosition;
var nextPos = Camera.main.transform.localPosition;
if (scrollDelta < 0)
{
nextPos = cameraList.Where(c => c.y > Camera.main.transform.localPosition.y).FirstOrDefault();
if (nextPos != Vector3.zero)
Camera.main.transform.DOLocalMove(nextPos, 0.5f);
//StartCoroutine(MoveCamera(prePos, nextPos));
}
if (scrollDelta > 0)
{
nextPos = cameraList.Where(c => c.y < Camera.main.transform.localPosition.y).LastOrDefault();
if (nextPos != Vector3.zero)
Camera.main.transform.DOLocalMove(nextPos, 0.5f);
//StartCoroutine(MoveCamera(prePos, nextPos));
}
}
DateTime startTimpStamp = DateTime.Now;
private void HandleTouch()
{
if (singleUIManager == null)
return;
var touchCount = Input.touchCount;
switch (Input.touchCount)
{
case 1:
{
UnityEngine.Debug.Log(Input.touches[0]);
UnityEngine.Debug.Log($"{Input.touches[0]}{Input.touches[0].phase }");
if (Input.touches[0].tapCount == 1 && Input.touches[0].phase == TouchPhase.Began && isStart && singleUIManager.clearLock && competitionId == 0)
{
startTimpStamp = DateTime.Now;
}
//单击切换极简模式
if (Input.touches[0].tapCount==1 && Input.touches[0].phase == TouchPhase.Ended && isStart && singleUIManager.clearLock && competitionId == 0)
{
var interval = DateTime.Now - startTimpStamp;
UnityEngine.Debug.Log(interval);
if (interval.TotalMilliseconds<=150 && IsPointerOverGameObject(Input.mousePosition))
{
singleUIManager?.ClearPanel(null);
}
}
}
break;
case 2:
{
return;
//双手触摸移动摄像机
// Store both touches.
Touch touchZero = Input.GetTouch(0);
Touch touchOne = Input.GetTouch(1);
// Find the position in the previous frame of each touch.
Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;
// Find the magnitude of the vector (the distance) between the touches in each frame.
float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude;
float touchDeltaMag = (touchZero.position - touchOne.position).magnitude;
var offset = touchDeltaMag - prevTouchDeltaMag;
if (cameraList == null)
{
cameraList = new List<Vector3>();
cameraList.Add(near);
cameraList.Add(plane);
cameraList.Add(far);
}
var prePos = Camera.main.transform.localPosition;
var nextPos = Camera.main.transform.localPosition;
if (offset < 0)
{
nextPos = cameraList.Where(c => c.y > Camera.main.transform.localPosition.y).FirstOrDefault();
if (nextPos != Vector3.zero)
Camera.main.transform.DOLocalMove(nextPos, 0.5f);
//StartCoroutine(MoveCamera(prePos, nextPos));
}
if (offset > 0)
{
nextPos = cameraList.Where(c => c.y < Camera.main.transform.localPosition.y).LastOrDefault();
if (nextPos != Vector3.zero)
Camera.main.transform.DOLocalMove(nextPos, 0.5f);
//StartCoroutine(MoveCamera(prePos, nextPos));
}
}
break;
}
}
/// <summary>
/// 处理中断骑行
/// </summary>
private void TempFileHandler()
{
//处理异常中断的骑行
if (App.tempRecordData != null)
{
recorderData.EndDistance = App.tempRecordData.EndDistance;
recorderData.StartTime = App.tempRecordData.StartTime;
recorderData.RiderDatas = App.tempRecordData.RiderDatas;
coordiantes = Along(App.tempRecordData.EndDistance);
startTime = App.tempRecordData.StartTime;
preticks = recorderData.RiderDatas.Last().Ticks;
App.tempRecordData = null;//清空
}
}
private IEnumerator Init()
{
yield return null; //new WaitForSeconds(1);
mapRoute = mapApi.GetById(routeId).data;
loadingController.Init();//初始化loading页面
loadingController.AddProcess(10);
InitData();//初始化数据
InitGameObject();//初始化场景
MapUDPService.Init();//初始化TCP
loadingController.AddProcess(10);
}
//初始比赛
private IEnumerator InitRace()
{
yield return null;//new WaitForSeconds(1);
UnityEngine.Debug.Log($"TEST:{routeId}");
mapRoute = mapApi.GetById(routeId).data;
var mapCompetitionApi = new MapCompetitionApi();
competition = mapCompetitionApi.GetById(competitionId).data;
loadingController.Init();//初始化loading页面
loadingController.AddProcess(10);
InitRaceData();//初始化比赛数据
InitRaceGameObject();//初始化比赛场景
//MapUDPService.Init(competitionId,isWatch);//初始化比赛TCP
loadingController.AddProcess(10);
}
public void InitTcp()
{
MapUDPService.Init(competitionId, isWatch);//初始化比赛TCP
}
//初始化数据
private void InitData()
{
mapData = mapApi.GetData(routeId);//获取路书地理数据
route = new Route(mapData, mapRoute);
loadingController.AddProcess(10);
#region
//骑行结果
if (App.routeResult != null)
{
routeResult = App.routeResult;
selectParamModel = App.routeResult.ContinueCyclingParam;//继续骑行
preticks = App.routeResult.Ticks;
}
if (selectParamModel == null)
{
selectParamModel = new RouteResultParam
{
CompetitionId = 0,
ContinueIndex = 0,
ContinueMark = "",
GlobalContinue = false,
EndDistance = 0,
RankingsId = new List<string>(),
OnlineUserId = 0,
RouteId = routeId
};
}
App.routeResult = null;
#endregion
double endDistance = selectParamModel.EndDistance;
coordiantes = Along(endDistance);
var shaowList = mapApi.GetShadowList(routeId, "", 0, 10);
if (shaowList.result)
{
mapRouteRankingList = shaowList.data.list;
}
}
private void InitRaceData()
{
mapData = mapApi.GetData(routeId);//获取路书地理数据
route = new Route(mapData, mapRoute);
loadingController.AddProcess(10);
#region
selectParamModel = new RouteResultParam
{
CompetitionId = competitionId,
ContinueIndex = 0,
ContinueMark = "",
GlobalContinue = false,
EndDistance = 0,
RankingsId = new List<string>(),
OnlineUserId = 0,
RouteId = App.RouteIdParam
};
#endregion
double endDistance = selectParamModel.EndDistance;
//计算上次骑行距离调整地图中心点
coordiantes = Along(endDistance);
}
private Vector3 mapPos = Vector3.zero;
//加载人物和地图以及UI界面
private void InitGameObject()
{
#if !(UNITY_IOS || UNITY_ANDROID)
minicamera.SetActive(true);
miniMap.SetActive(true);
#endif
map.gameObject.SetActive(true);
player.SetActive(true);
UIObject.SetActive(true);
singleUIManager = UIObject.AddComponent<SingleUIManager>();
map.OnTileFinished += Map_OnTileFinished;
mapPos = map.transform.position;
}
private void InitRaceGameObject()
{
#if !(UNITY_IOS || UNITY_ANDROID)
minicamera.SetActive(true);
#endif
map.gameObject.SetActive(true);
player.SetActive(true);
UIObject.SetActive(true);
singleUIManager = UIObject.AddComponent<CompetitionUIManager>();
//miniMap.SetActive(true);
map.OnTileFinished += Map_OnTileFinished;
mapPos = map.transform.position;
//为了解决比赛观看模式下,切换观看用户之前跨度过大导致地图海拔信息不完整的问题
RangeAroundTransformTileProviderOptions options = new RangeAroundTransformTileProviderOptions
{
targetTransform = target,
visibleBuffer = 2,
disposeBuffer = 2
};
map.SetExtent(MapExtentType.RangeAroundTransform, options);
map.SetExtentOptions(options);
}
//设置骑行模式
public void SetCyclingModel(CyclingModel mode)
{
this.cyclingModel = mode;
switch (cyclingModel)
{
case CyclingModel.Single:
cyclingController = new SingleModel(route, selectParamModel);
break;
case CyclingModel.Review:
cyclingController = new ReviewModel(route, selectParamModel);
break;
case CyclingModel.Competition:
cyclingController = new CompetitionModel(route, selectParamModel, currentPlayer);
break;
}
GameStart();
InitPlayer();//初始化人物方向等
}
PlayerController playerController;
public AbstractPlayer currentPlayer { get; set; }
private GameObject onlinePlayer { get; set; }
Vector3 MAX_SIZE = new Vector3(3f, 3f, 3f);
Vector3 MIN_SIZE = new Vector3(0.1f, 0.1f, 0.1f);
public void ChangeCurrentPlayer(int userId)
{
var coll = FindObjectsOfType<AbstractPlayer>();
var selectedPlayer = coll.Where(c => c.UserId == userId).FirstOrDefault();
if (selectedPlayer != null)
{
currentPlayer = selectedPlayer;
if (selectedPlayer is PlayerController)
{
selectedPlayer.transform.localScale = Is3dView ? MAX_SIZE : MIN_SIZE;
}
else
{
Utils.DestroyChildren(selectedPlayer.transform);
var ss = Instantiate(onlineUserPrefab3d, selectedPlayer.transform);
ss.transform.localScale = Is3dView ? MAX_SIZE : MIN_SIZE;
selectedPlayer.UpdateAnimator();
}
Vector2d nextLatLon = Along(selectedPlayer.TotalDistance + 0.1);
//设定人物方向
var s = map.GeoToWorldPosition(selectedPlayer.Currentlatlong);
var e = map.GeoToWorldPosition(nextLatLon);
Quaternion neededRotation = Quaternion.LookRotation(s - e);
selectedPlayer.transform.rotation = Quaternion.Euler(0, neededRotation.eulerAngles.y, 0);
selectedPlayer.currentRotation = neededRotation;
}
var unselectedPlayers = coll.Where(c => c.UserId != userId).ToList();
foreach (var item in unselectedPlayers)
{
item.transform.localScale = MIN_SIZE;
if (item.transform.childCount > 0)
{
Utils.DestroyChildren(item.transform);
}
}
//重置海拔图进度
var currentIndex = currentPlayer.CurrentIndex;
graph.HorizontalScrolling = chartDataSourceScript.GetCurrentStart(currentIndex);
}
//初始化人物位置角度
private void InitPlayer()
{
TempFileHandler();//处理中断骑行继续骑的逻辑
lockView = true;
Vector2d lastLatLon = Along(recorderData.EndDistance);
Vector3 currentPos = map.GeoToWorldPosition(lastLatLon);
currentPos.y += 1f;
player.transform.position = currentPos;
playerController.currentPos = currentPos;
var trail = FindObjectOfType<TrailRenderer>();
if (trail != null)
{
trail.enabled = true;
}
Vector2d nextLatLon = Along(recorderData.EndDistance + 0.1);
//设定人物方向
var s = map.GeoToWorldPosition(lastLatLon);
var e = map.GeoToWorldPosition(nextLatLon);
Quaternion neededRotation = Quaternion.LookRotation(s - e);
player.transform.rotation = Quaternion.Euler(0, neededRotation.eulerAngles.y, 0);
playerController.currentRotation = neededRotation;
//初始化海拔图头像位置
var index = GetCurrentIndex(recorderData.EndDistance);
InitGraph(index);
int tick = 0;
if (recorderData.RiderDatas.Count > 0)
{
tick = recorderData.RiderDatas.Last().Ticks;
}
playerController.Init(index, recorderData.EndDistance, tick);
}
public void InitGraph(int index)
{
chartDataSourceScript.InitHorizontalScrolling(index);
}
//SingleUIManager singleUIManager;
public BaseUIManager singleUIManager;
public void GameStart()
{
Camera.main.transform.DOLocalMove(neareast, 1f);
//StartCoroutine(MoveCamera(far, near));//初始摄像头
var check = CheckAnt();
#if UNITY_EDITOR
check = true;
#endif
if (check || isWatch)
{
singleUIManager.StartRide();
transform.Find("UI/Panel(Clone)/ToolBarPanel/StartOrPauseButton").GetComponent<Button>().enabled = true;
transform.Find("UI/Panel(Clone)/ToolBarPanel/SettingButton").GetComponent<Button>().enabled = true;
}
else
{
transform.Find("UI/Panel(Clone)/ToolBarPanel/StartOrPauseButton").GetComponent<Button>().enabled = false;
transform.Find("UI/Panel(Clone)/ToolBarPanel/SettingButton").GetComponent<Button>().enabled = false;
Utils.showToast(null, "Please connect the device!", duration: int.MaxValue, isLowest: true
, stopFunc: () => isWatch || CheckAnt() || transform.Find("UI/Panel(Clone)/SelectPlayer").gameObject.activeInHierarchy
, endCallback: () =>
{
if (!transform.Find("UI/Panel(Clone)/SelectPlayer").gameObject.activeInHierarchy)
{
UIManager.Instance.DevicePanel.Close();
singleUIManager.StartRide();
transform.Find("UI/Panel(Clone)/ToolBarPanel/StartOrPauseButton").GetComponent<Button>().enabled = true;
transform.Find("UI/Panel(Clone)/ToolBarPanel/SettingButton").GetComponent<Button>().enabled = true;
}
});
}
}
public void GoContinueRide()
{
singleUIManager.ContinueRide();
}
#region TCP相关
public void TcpHandler()
{
if (cyclingController != null)
{
////tcp数据传输
//if (competition != null && !cyclingController.recorderData.Saved)
//{
// cyclingController.recorderData.Saved = competition.HasRecord;
//}
cyclingController.Run(null);
//在线人物或比赛人物渲染
ShowOnlineUsers();
}
}
List<OnlinePlayerController> otherList = new List<OnlinePlayerController>();
GameObject onlineUserPrefab;
GameObject miniMapPlayerPrefab;
int messageIndex = 0;
private void ShowOnlineUsers()
{
var onlineRiders = cyclingController.riders;
var currentOnlineUserList = FindObjectsOfType<OnlinePlayerController>();
//新增或者更新
foreach (var item in onlineRiders)
{
var onlineRider = item as OnlineRiderModel;
var currentUser = currentOnlineUserList.Where(c => c.UserId == item.UserId).FirstOrDefault();
var onlineDistance = onlineRider.EndDistance - onlineRider.PreDistance;
var onlineTotalDistance = onlineRider.PreDistance;
var index = GetCurrentIndex(onlineTotalDistance);
if (currentUser == null)
{
//大地图人物
GameObject otherPlayerObj = (GameObject)Instantiate(onlineUserPrefab, transform);
otherPlayerObj.transform.position = map.GeoToWorldPosition(Along(onlineTotalDistance));
var onlinePlayerController = otherPlayerObj.GetComponent<OnlinePlayerController>();
otherList.Add(onlinePlayerController);
onlinePlayerController.UserId = onlineRider.UserId;
onlinePlayerController.SetDataSource(onlineTotalDistance, onlineDistance, onlineRider.Power, onlineRider.HeartRate, onlineRider.Cadence, onlineRider.TotalTicks, onlineRider.NickName, onlineRider.WeightKg, new Vector2d(onlineRider.Point.Latitude, onlineRider.Point.Longitude), index);
onlinePlayerController.SetHead(onlineRider.WxHeadImg);
if (competitionId == 0)
{
//小地图人物
GameObject miniPlayer = (GameObject)Instantiate(miniMapPlayerPrefab, transform);
var miniController = miniPlayer.GetComponent<MiniMapPlayerController>();
miniController.SetController(onlinePlayerController);
}
//发消息xx进入路书
if (messageIndex > 0)
EventQueueSystem.QueueEvent(new JoinMessageEvent(onlineRider.NickName, onlineRider.WxHeadImg));
}
else
{
currentUser.SetDataSource(onlineTotalDistance, onlineDistance, onlineRider.Power, onlineRider.HeartRate, onlineRider.Cadence, onlineRider.TotalTicks, onlineRider.NickName, onlineRider.WeightKg, new Vector2d(onlineRider.Point.Latitude, onlineRider.Point.Longitude), index);
}
if (isWatch && (currentPlayer is PlayerController || currentPlayer == null))
{
var userId = onlineRiders.FirstOrDefault()?.UserId ?? 0;
ChangeCurrentPlayer(userId);
var competitionRankingFactory = FindObjectOfType<CompetitionRankingFactory>();
if (competitionRankingFactory != null)
{
competitionRankingFactory.isInit = false;
}
}
//显示观察者头像
}
if (onlineRiders.Count > 0)
messageIndex++;
//移除
foreach (var item in currentOnlineUserList)
{
var currentItem = onlineRiders.Where(c => c.UserId == item.UserId).FirstOrDefault();
if (currentItem == null)
{
item.RemoveSelf();
}
}
//显示面板信息
var others = FindObjectsOfType<AbstractPlayer>();
foreach (var item in others)
{
item.IsShowInfo = false;
}
var frontPlayer = others.Where(c => c.TotalDistance - currentPlayer.TotalDistance < 0.25 && c.TotalDistance - currentPlayer.TotalDistance >= 0 && c.UserId != currentPlayer.UserId).OrderBy(c => c.TotalDistance).FirstOrDefault();
var bakePlayer = others.Where(c => c.TotalDistance - currentPlayer.TotalDistance > -0.25 && c.TotalDistance - currentPlayer.TotalDistance < 0 && c.UserId != currentPlayer.UserId).OrderByDescending(c => c.TotalDistance).FirstOrDefault();
if (frontPlayer != null)
frontPlayer.IsShowInfo = true;
if (bakePlayer != null)
bakePlayer.IsShowInfo = true;
}
//查询赛事观看者列表(取前5)
public List<OnlineUser> GetWatcherList()
{
return MapUDPService.GetCompetitionWatchers(competitionId);
}
#endregion
public void SetUIManager(PFUIPanel mainPanel, PFUIPanel model)
{
UIManager.Instance.MainPanel = mainPanel;
UIManager.Instance.ModalsPanel = model;
}
public void ReSetUIManager()
{
UIManager.Instance.MainPanel = uipanel.GetComponent<PFUIPanel>();
UIManager.Instance.ModalsPanel = this.transform.Find("UI/ModalPanel").GetComponent<PFUIPanel>();
}
public void AddEvent(GameObject sender, EventTriggerType eventType, UnityAction<BaseEventData> unityAction)
{
UIManager.AddEvent(sender, eventType, unityAction);
}
public void ShowDevice(PFUIPanel pFUIPanel)
{
#if UNITY_IOS || UNITY_ANDROID
UIManager.ShowDevicePanel();
#else
UIManager.Show(UIManager.Instance.DevicePanel,null,true);
#endif
}
public Texture GetCountryImageByCode(string code)
{
return UIManager.Instance.loginRegOptions.GetCountryImage(code);
}
public Texture GetCountryImageByName(string name)
{
return UIManager.Instance.loginRegOptions.GetCountryImageByName(name);
}
#region
public AbstractMap map3d;
public bool Is3dView;
public void ChangeMapImageStyle(GameObject arrowGameObj)
{
var trailRendererList = transform.GetComponentsInChildren<TrailRenderer>();
foreach (var item in trailRendererList)
{
item.time = 0;
}
StartCoroutine(EnableTrailRenderer(trailRendererList.ToList()));
if (!Is3dView)
{
//地图属性变更
map.Terrain.ExaggerationFactor = 1.5f;
map.Terrain.SetElevationType(ElevationLayerType.TerrainWithElevation);
map.ImageLayer.SetLayerSource(ImagerySourceType.Custom);
map.SetCenterLatitudeLongitude(currentPlayer.Currentlatlong);
map.transform.position = mapPos;
//map3d.gameObject.SetActive(true);
//map.gameObject.SetActive(false);
//人物属性变更
var pos = map.GeoToWorldPosition(currentPlayer.Currentlatlong);
playerController.currentPos = pos;
target.position = pos;
player.transform.localScale = new Vector3(3f, 3f, 3f);
player.transform.position = pos;
arrowGameObj.SetActive(false);
Is3dView = true;
}
else
{
//地图属性变更
map.ImageLayer.SetLayerSource(ImagerySourceType.JuzeTest);
map.Terrain.ExaggerationFactor = 0f;
map.Terrain.SetElevationType(ElevationLayerType.FlatTerrain);
map.SetCenterLatitudeLongitude(currentPlayer.Currentlatlong);
map.transform.position = Vector3.zero;
//map.gameObject.SetActive(true);
//map3d.gameObject.SetActive(false);
//人物属性变更
var pos = map.GeoToWorldPosition(currentPlayer.Currentlatlong);
player.transform.position = pos;
player.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f);
target.position = pos;
//playerController.currentPos = Vector3.zero;
arrowGameObj.SetActive(true);
Is3dView = false;
}
if (competitionId > 0)
{
ChangeCurrentPlayer(currentPlayer.UserId);
}
}
private bool lockView = false;
private void Map_OnTileFinished(Mapbox.Unity.MeshGeneration.Data.UnityTile obj)
{
if (!lockView)
{
var playerController = player.GetComponent<PlayerController>();
player.transform.localScale = new Vector3(3f, 3f, 3f);
var locations = playerController.Currentlatlong == null ? playerController.Currentlatlong : new Vector2d(mapData.List[0].Point[0], mapData.List[0].Point[1]);
player.transform.position = map.GeoToWorldPosition(locations);
mapPos = map.transform.position;
if (recorderData != null)
{
var lastLatLon = Along(recorderData.EndDistance);
var nextLatLon = Along(recorderData.EndDistance + 0.1);
player.transform.position = map.GeoToWorldPosition(lastLatLon);
//设定人物方向
var s = map.GeoToWorldPosition(lastLatLon);
var e = map.GeoToWorldPosition(nextLatLon);
Quaternion neededRotation = Quaternion.LookRotation(s - e);
player.transform.rotation = Quaternion.Euler(0, neededRotation.eulerAngles.y, 0);
}
}
}
IEnumerator EnableTrailRenderer(List<TrailRenderer> trailRendererList)
{
yield return new WaitForSeconds(2f);
foreach (var item in trailRendererList)
{
item.Clear();
item.time = 30;
}
}
#endregion
#region
Stopwatch sw { get; set; }
//开始骑行
public void SetStart()
{
if (!isPause && DateTime.MinValue == startTime)
{
isStart = true;
startTime = UIManager.Now.GetDateTime();
////骑行累计毫秒
//sw = new Stopwatch();
//sw.Start();
activeSeconds = 0f;
}
else
{
SetContinue();
}
}
//继续骑行
public void SetContinue()
{
isStart = true;
isPause = false;
}
//暂停骑行
public void SetPause()
{
isStart = false;
isPause = true;
}
//退出或者完成骑行
public void SetQuit()
{
////耗时巨大的代码
//if (sw != null)
//{
// sw.Stop();
// TimeSpan ts2 = (TimeSpan)(sw.Elapsed);
// UnityEngine.Debug.Log(string.Format("Stopwatch总共花费{0}ms.", ts2.TotalMilliseconds));
// //TODO后算接口需要增加累计毫秒字段
//}
isStart = false;
isQuit = true;
}
#endregion
#region
/// <summary>
/// 当前骑行数据的记录器
/// </summary>
private RecorderDataModel recorderData
{
get
{
return cyclingController?.recorderData;
}
}
public Route GetRoute()
{
return route;
}
public GameObject GetUIPanel()
{
return uipanel;
}
public MapDataModel GetMapData()
{
return mapData;
}
/// <summary>
/// 清空临时文件
/// </summary>
public void ClearTempFile()
{
Helper.DelectDir(PFConstants.MapWorkoutRecordTempFolder);
App.tempRecordData = null;
}
TempRecordData tempRecordData { get; set; }
public void SaveRealTime()
{
if (tempRecordData == null)
{
tempRecordData = new TempRecordData();
}
RecorderDataModel recorderData = cyclingController.recorderData;
tempRecordData.RiderDatas = recorderData.RiderDatas;
tempRecordData.selectParam = recorderData.selectParam;
tempRecordData.UserId = App.CurrentUser.Id;
tempRecordData.RouteId = mapRoute.Id;
tempRecordData.CompetitionId = recorderData.Competitionid;
tempRecordData.StartTime = startTime;
tempRecordData.ManufacturerId = recorderData.ManufacturerId;
tempRecordData.ManufacturerName = recorderData.ManufacturerName;
tempRecordData.Mode = cyclingModel.ToString();
tempRecordData.EndDistance = recorderData.EndDistance;
var guid = recorderData.ContinueMark;
var filePath = PFConstants.MapWorkoutRecordTempFolder + "/" + guid.ToString()+".txt";
var tempContent = Newtonsoft.Json.JsonConvert.SerializeObject(tempRecordData);
System.IO.File.WriteAllText(filePath, tempContent);
}
public int RankingId;
public void Save(double totalDistance)
{
ClearTempFile();
cyclingController.recorderData.EndTime = UIManager.Now.GetDateTime();
isQuit = true;
isStart = false;
string recordId = Guid.NewGuid().ToString();
//var path = Helper.GetDataDir("MapWorkoutRecords/"+ recordId);
var path = PFConstants.MapWorkoutRecordFolder + "/" + recordId;
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;
RankingId =cyclingController.recorderData.SaveWithLocalRecordAysnc(cyclingModel, selectParamModel, imageFileName, recordId, path);
//显示骑行结果(如果是比赛模式显示比赛最终排名)
if (cyclingModel != CyclingModel.Competition)
{
resultPanel.SetActive(true);
var rs = resultPanel.GetComponent<ResultPanelScript>();
rs.InjectController(this);
rs.SetDataSource(cyclingController.recorderData);
}
}
public byte[] CaptureCamera()
{
return CaptureCameraReturnByte(Camera.main, new Rect(Screen.width * 0f, Screen.height * 0f, Screen.width * 0.5f, Screen.height * 0.5f));
}
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();
}
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));
}
public Vector2d GetCenterCoordinate()
{
return coordiantes;
}
public int GetCurrentIndex(double endDistance)
{
int index = 0;
var pointList = mapData.List;
double sumDistance = 0;
if (endDistance >= mapData.TotalDistance)
{
return pointList.Count - 1;
}
for (int i = 0; i < pointList.Count; i++)
{
sumDistance += pointList[i].Distance;
decimal left = (decimal)(endDistance * 1000);
decimal right = (decimal)sumDistance;
if (left <= right)
{
index = i;
break;
}
}
index = endDistance >= mapData.TotalDistance ? pointList.Count - 1 : index;
return index;
}
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);
}
}
private double CurrentMaxAp = 0;//当前最大AP
public void ComputeMaxAP(double power,int ticks)
{
//计算当前最大AP
if (power > CurrentMaxAp)
{
CurrentMaxAp = power;
}
//分段记录MaxAp
switch (ticks)
{
case 5: recorderData.FiveSecondsMaxAP = CurrentMaxAp; break;
case 10: recorderData.TenSecondsMaxAP = CurrentMaxAp; break;
case 60: recorderData.OneMinuteMaxAP = CurrentMaxAp; break;
case 300: recorderData.FiveMinutesMaxAp = CurrentMaxAp; break;
case 1200: recorderData.TwentyMinutesMaxAP = CurrentMaxAp; break;
default:
break;
}
}
#endregion
}