Files
powerfun-unity/Assets/Scenes/Ride/Scripts/AbstractPlayer.cs
T

318 lines
8.6 KiB
C#

using Assets.Scenes.Ride.Scripts.Model.CyclingModels;
using Assets.Scripts.Apis.Models;
using ChartAndGraph;
using DG.Tweening;
using GeoJSON.Net.Geometry;
using Mapbox.Unity.Map;
using Mapbox.Utils;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TurfCS;
using UnityEngine;
using UnityEngine.UI;
namespace Assets.Scenes.Ride.Scripts
{
public abstract class AbstractPlayer: MonoBehaviour
{
[Header("Character")]
[SerializeField]
GameObject character;
[SerializeField]
Animator characterAnimator;
protected AbstractMap map;
//AbstractMap map;
public bool IsShowInfo { get; set; }
#region 动画控制参数
public Vector3 nextPos;
Vector3 prePos = Vector3.zero;
float timer = 1.0f;//计时器
#endregion
#region 选手骑行数据
protected Vector2d nextlatlong; //下一个点的坐标
protected Vector2d currentlatlong; //当前坐标
//protected bool isStart;//开始或者暂停
//public bool isQuit;//true 中途退出 或者到达终点
protected bool isMajor;//是否是主人公
protected MapDataModel mapData;
//protected int userId;
protected DateTime startTime;//开始骑行时间
protected DateTime endTime;//结束骑行时间
protected double weight;//体重
protected double bicycleWeight;//车重
protected double speed;
protected double power;
protected double elevation;
protected double cadance;
protected int heartRate;
protected int ticks;
protected double totalDistance;
protected double currentSlope;
protected double nextSlope;
protected double nextSlopeDistance;
protected double distance;
protected double currentSlopeDistance;
protected double lastEndDistance;
protected double totalClimb;
public double TotalClimb { get => totalClimb; }
public int UserId { set; get; }//{ get => userId; }
public double Speed { get => speed; }
public double Power { get => power; }
public double Cadance { get => cadance; }
public double HeartRate { get => heartRate; }
public int TotalTicks { get => ticks; }
public double TotalDistance { get => totalDistance; }
public double Distance { get => distance; }
public double CurrentSlope { get => currentSlope; }
public double NextSlope { get => nextSlope; }
public double NextSlopeDistance { get => nextSlopeDistance; }
public double CurrentSlopeDistance { get => currentSlopeDistance; }
public double Elevation { get => elevation; }
public double LastEndDistance { get => lastEndDistance; }
public Vector2d Currentlatlong { get => currentlatlong; }
#endregion
#region UI对象
//UI对象
protected GameObject headPanel;
protected GraphChartBase graph;
protected ChartDataSourceScript chartDataSourceScript;
#endregion
void Start()
{
Init();
}
void Update()
{
Excute();
AfterExcute();
}
protected virtual void AfterExcute()
{
}
#region 骑行逻辑
//初始化骑行数据
protected CyclingController mainController;
protected BaseCycling cyclingExcutor;
protected virtual void Init()
{
characterAnimator = GetComponentInChildren<Animator>();
mainController = transform.parent.GetComponent<CyclingController>();
map = transform.parent.Find("Map").GetComponent<AbstractMap>();
mapData = mainController.GetMapData();//获取路书信息
//获取海拔图UI对象
var graphObject = transform.parent.Find("SingleUI/Panel/GraphChart");
chartDataSourceScript = graphObject.GetComponent<ChartDataSourceScript>();
graph = graphObject.GetComponent<GraphChartBase>();
}
protected virtual void Excute()
{
//CamControl();
timer -= Time.deltaTime;
if (timer <= 0)//定时器 一秒执行一次
{
BeforeRun();
Run();
timer = 1.0f;
}
}
public bool stopRecord = false;
//骑行中
protected virtual void Run()
{
if (mapData == null)
return;
ComputeNextSlope();//计算下一个坡度相关数据
MoveGraphHead();//移动海拔图头像
//人物动画控制
if (characterAnimator != null)
{
characterAnimator.SetFloat("Speed", (float)speed);
characterAnimator.SetFloat("Slope", (float)currentSlope);
if (currentSlope > 5)
{
characterAnimator.speed = 0.5f;
}
else
{
characterAnimator.speed = 1f;
}
if (totalDistance >= mapData.TotalDistance)
{
characterAnimator.SetBool("ReachEnd", true);//到达终点
}
}
//开始骑行
if (GetStart())
{
ticks++;
Compute();//接受蓝牙设备数据计算
if (totalDistance > mapData.TotalDistance)
{
distance = totalDistance - mapData.TotalDistance;
totalDistance = mapData.TotalDistance;
stopRecord = true;
StartCoroutine("LateUpload");
}
//数据处理
nextPos = map.GeoToWorldPosition(currentlatlong);//下一个点
nextPos.y += 1.35f;//提高y轴让人物站在地图上面
prePos = transform.localPosition;//当前点
thisRotation = transform.localRotation;
//移动动画控制
if (distance > 0)
{
StartCoroutine(MoveTo());//移动
}
}
}
//游戏开始开关
public virtual bool GetStart()
{
return mainController.isStart;
}
protected virtual void BeforeRun()
{
}
//计算功率 速度 当前骑行总里程(M)心率 踏频 等
protected virtual void Compute()
{
}
//当前用户调用来上传骑行记录
public virtual void Upload()
{
}
#endregion
#region 工具类
IEnumerator LateUpload()
{
yield return new WaitForSeconds(1);
Upload();
StopCoroutine("LateUpload");
}
public int CurrentIndex;
private int index;
public double CurrentDistance;//当前所处区间距离
public double NextSlopeTotalDistance;
//当前距离所在的海拔/坡度/距离 下一个点的坡度以及剩余距离
void ComputeNextSlope()
{
double sumDistance = 0;
if (mapData == null)
return;
var pointList = mapData.List;
int preIndex = 0;
for (int i = 0; i < pointList.Count; i++)
{
sumDistance += pointList[i].Distance;
if (totalDistance * 1000 <= sumDistance)
{
index = i;
break;
}
}
preIndex = index > 0 ? index - 1:0;//前一个索引
CurrentIndex = index;//当前索引
int nextIndex = index == pointList.Count - 1 ? index : index + 1; //计算下一个点的坡度和距离
PreElevation = pointList[preIndex].Elevation; //计算上一个海拔
PreSlope = pointList[preIndex].Grade; //计算上一个坡度
//计算当前海拔和坡度&当前区间距离
elevation = pointList[CurrentIndex].Elevation;
currentSlope = pointList[CurrentIndex].Grade;
CurrentDistance = pointList[CurrentIndex].Distance;
//计算下一个海拔和坡度&当前区间距离
nextSlope = pointList[nextIndex].Grade;
nextSlopeDistance = sumDistance - totalDistance * 1000;
NextSlopeTotalDistance = pointList[nextIndex].Distance;
currentSlopeDistance = (totalDistance * 1000 - (sumDistance - pointList[index].Distance));// CurrentDistance-( totalDistance * 1000 - (sumDistance - pointList[index].Distance));
}
public double PreElevation;
public double PreSlope;
#endregion
#region 人物移动与转向控制
Quaternion thisRotation;
public Quaternion currentRotation;
IEnumerator LookAtNextPos()
{
if (prePos != nextPos)
{
Quaternion neededRotation = Quaternion.LookRotation(prePos - nextPos);
float t = 0;
while (t < 1.0f)
{
t += Time.deltaTime / 0.5f;
currentRotation = Quaternion.Slerp(thisRotation, neededRotation, t);
character.transform.rotation = Quaternion.Euler(0, currentRotation.eulerAngles.y, 0);
yield return null;
}
}
}
Vector3 deltaPos = Vector3.zero;
Vector3 previousPos = Vector3.zero;
void CamControl()
{
deltaPos = transform.position - previousPos;
deltaPos.y = 0;
Camera.main.transform.position = Vector3.Lerp(Camera.main.transform.position, Camera.main.transform.position + deltaPos, Time.time);
previousPos = transform.position;
}
public Vector3 currentPos = new Vector3(0,0,0);
//人物移动控制
IEnumerator MoveTo()
{
StartCoroutine(LookAtNextPos());//转向
//让人物移动分点增加动画的流畅度
float t = 0;
while (t < 1)
{
t += Time.deltaTime;
Vector3 v = Vector3.Lerp(prePos, nextPos, t);
currentPos = v;
transform.localPosition = v;
yield return new WaitForEndOfFrame();
}
}
#endregion
#region UI行为
protected virtual void MoveGraphHead()
{
}
#endregion
}
}