新增人物控制器抽象类
This commit is contained in:
parent
eb93577d68
commit
2e6338bcf3
255
Assets/Scenes/Ride/Scripts/AbstractPlayer.cs
Normal file
255
Assets/Scenes/Ride/Scripts/AbstractPlayer.cs
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
using Assets.Scripts.Apis.Models;
|
||||||
|
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;
|
||||||
|
|
||||||
|
namespace Assets.Scenes.Ride.Scripts
|
||||||
|
{
|
||||||
|
public abstract class AbstractPlayer: MonoBehaviour
|
||||||
|
{
|
||||||
|
[Header("Character")]
|
||||||
|
[SerializeField]
|
||||||
|
GameObject character;
|
||||||
|
[SerializeField]
|
||||||
|
Animator characterAnimator;
|
||||||
|
AbstractMap map;
|
||||||
|
|
||||||
|
#region 动画控制参数
|
||||||
|
Vector3 nextPos;
|
||||||
|
Vector3 prePos;
|
||||||
|
float timer = 1.0f;//计时器
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 选手骑行数据
|
||||||
|
protected Vector2d nextlatlong; //下一个点的坐标
|
||||||
|
protected bool isStart;//开始或者暂停
|
||||||
|
protected 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;
|
||||||
|
|
||||||
|
public int UserId { get => userId; }
|
||||||
|
public bool IsStart { get => isStart; }
|
||||||
|
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 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; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 游戏状态控制
|
||||||
|
//开始骑行
|
||||||
|
public void SetStart()
|
||||||
|
{
|
||||||
|
isStart = true;
|
||||||
|
startTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
//继续骑行
|
||||||
|
public void SetContinue()
|
||||||
|
{
|
||||||
|
isStart = true;
|
||||||
|
}
|
||||||
|
//暂停骑行
|
||||||
|
public void SetPause()
|
||||||
|
{
|
||||||
|
isStart = false;
|
||||||
|
}
|
||||||
|
//退出或者完成骑行
|
||||||
|
public void SetQuit()
|
||||||
|
{
|
||||||
|
isQuit = true;
|
||||||
|
endTime.AddSeconds(ticks);//计算结束时间
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
Excute();
|
||||||
|
}
|
||||||
|
#region 骑行逻辑
|
||||||
|
//初始化骑行数据
|
||||||
|
protected virtual void Init()
|
||||||
|
{
|
||||||
|
characterAnimator = GetComponentInChildren<Animator>();
|
||||||
|
var mainController = transform.parent.GetComponent<CyclingController>();
|
||||||
|
map = FindObjectOfType<AbstractMap>();
|
||||||
|
mapData = mainController.GetMapData();//获取路书信息
|
||||||
|
nextlatlong = new Vector2d(mapData.List[0].Point[0], mapData.List[0].Point[1]);//初始化人物位置 TODO加上之前骑行距离
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Excute()
|
||||||
|
{
|
||||||
|
timer -= Time.deltaTime;
|
||||||
|
if (timer <= 0)//定时器 一秒执行一次
|
||||||
|
{
|
||||||
|
Run();
|
||||||
|
timer = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//骑行中
|
||||||
|
protected virtual void Run()
|
||||||
|
{
|
||||||
|
ComputeNextSlope();//计算下一个坡度相关数据
|
||||||
|
if (isStart)
|
||||||
|
{
|
||||||
|
ticks++;
|
||||||
|
Compute();//接受蓝牙设备数据计算
|
||||||
|
characterAnimator.SetBool("IsRide", false);//初始化动画状态
|
||||||
|
if (totalDistance <= mapData.TotalDistance)
|
||||||
|
{
|
||||||
|
//数据处理
|
||||||
|
|
||||||
|
nextlatlong = Along(totalDistance);//下一个坐标
|
||||||
|
nextPos = map.GeoToWorldPosition(nextlatlong);//下一个点
|
||||||
|
nextPos.y += 0.3f;//提高y轴让人物站在地图上面
|
||||||
|
prePos = transform.localPosition;//当前点
|
||||||
|
//动画控制
|
||||||
|
if (distance > 0)
|
||||||
|
{
|
||||||
|
characterAnimator.SetBool("IsRide", true);//开始移动动画
|
||||||
|
StartCoroutine(LookAtNextPos());//转向
|
||||||
|
StartCoroutine(MoveTo());//移动
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
totalDistance = mapData.TotalDistance;
|
||||||
|
characterAnimator.SetBool("ReachEnd", true);//到达终点
|
||||||
|
Task.Run(() => { Upload(); });//异步上传数据
|
||||||
|
isStart = false;
|
||||||
|
isQuit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
characterAnimator.SetBool("IsRide", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//计算功率 速度 当前骑行总里程(M)心率 踏频 等
|
||||||
|
protected virtual void Compute()
|
||||||
|
{
|
||||||
|
//power = 900;//功率
|
||||||
|
//speed = Helper.CalculateSpeed(elevation, 0, power, 65, 7);
|
||||||
|
//distance = Math.Round(speed / 3600, 6);
|
||||||
|
//totalDistance += distance;
|
||||||
|
}
|
||||||
|
//当前用户调用来上传骑行记录
|
||||||
|
protected virtual void Upload()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 工具类
|
||||||
|
public int CurrentIndex;
|
||||||
|
//当前距离所在的海拔/坡度/距离 下一个点的坡度以及剩余距离
|
||||||
|
void ComputeNextSlope()
|
||||||
|
{
|
||||||
|
double sumDistance = 0;
|
||||||
|
var pointList = mapData.List;
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < pointList.Count; i++)
|
||||||
|
{
|
||||||
|
sumDistance += pointList[i].Distance;
|
||||||
|
if (totalDistance * 1000 <= sumDistance)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//计算当前海拔和坡度
|
||||||
|
elevation = pointList[index].Elevation;
|
||||||
|
currentSlope = pointList[index].Grade;
|
||||||
|
//计算下一个点的坡度和距离
|
||||||
|
int nextIndex = index == pointList.Count - 1 ? index : index + 1;
|
||||||
|
CurrentIndex = nextIndex;
|
||||||
|
nextSlope = pointList[nextIndex].Grade;
|
||||||
|
nextSlopeDistance = sumDistance - totalDistance * 1000;
|
||||||
|
currentSlopeDistance = totalDistance * 1000 - (sumDistance - pointList[index].Distance);
|
||||||
|
}
|
||||||
|
//根据距离计算坐标
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return nextlatlong;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 人物移动与转向控制
|
||||||
|
IEnumerator LookAtNextPos()
|
||||||
|
{
|
||||||
|
Quaternion neededRotation = Quaternion.LookRotation(transform.localPosition - nextPos);
|
||||||
|
Quaternion thisRotation = character.transform.localRotation;
|
||||||
|
|
||||||
|
float t = 0;
|
||||||
|
while (t < 1.0f)
|
||||||
|
{
|
||||||
|
t += Time.deltaTime / 0.25f;
|
||||||
|
var rotationValue = Quaternion.Slerp(thisRotation, neededRotation, t);
|
||||||
|
character.transform.rotation = Quaternion.Euler(0, rotationValue.eulerAngles.y, 0);
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//人物移动控制
|
||||||
|
IEnumerator MoveTo()
|
||||||
|
{
|
||||||
|
//让人物移动分点增加动画的流畅度
|
||||||
|
float t = 0;
|
||||||
|
while (t < 1)
|
||||||
|
{
|
||||||
|
t += Time.deltaTime;
|
||||||
|
Vector3 v = Vector3.Lerp(prePos, nextPos, t);
|
||||||
|
transform.localPosition = v;
|
||||||
|
//控制海拔图的位置
|
||||||
|
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Assets/Scenes/Ride/Scripts/AbstractPlayer.cs.meta
Normal file
11
Assets/Scenes/Ride/Scripts/AbstractPlayer.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f01d57cfa983552409f7c9e896892c31
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -193,7 +193,7 @@ public class CyclingController : MonoBehaviour
|
|||||||
if (result != null && result.List.Count > 0)
|
if (result != null && result.List.Count > 0)
|
||||||
{
|
{
|
||||||
mapData = result;
|
mapData = result;
|
||||||
coordiantes = result.List[0].Point;
|
coordiantes = result.List[0].Point;//TODO计算当前用户所处的位置
|
||||||
initComplete = true;
|
initComplete = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@ -1,184 +1,21 @@
|
|||||||
using System.Collections;
|
using System;
|
||||||
using UnityEngine;
|
|
||||||
using Mapbox.Unity.Map;
|
|
||||||
using Mapbox.Utils;
|
|
||||||
using Assets.Scripts.Apis.Models;
|
|
||||||
using static Assets.Scripts.Apis.Models.MapDataModel;
|
|
||||||
using System;
|
|
||||||
using Random = UnityEngine.Random;
|
|
||||||
using Assets.Scripts.Apis;
|
|
||||||
using GeoJSON.Net.Geometry;
|
|
||||||
using TurfCS;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
namespace Assets.Scenes.Ride.Scripts
|
namespace Assets.Scenes.Ride.Scripts
|
||||||
{
|
{
|
||||||
public class OtherPlayerController : MonoBehaviour
|
public class OtherPlayerController : AbstractPlayer
|
||||||
{
|
{
|
||||||
[Header("Character")]
|
protected override void Init()
|
||||||
[SerializeField]
|
{
|
||||||
GameObject character;
|
base.Init();
|
||||||
[SerializeField]
|
SetStart();//自动开始
|
||||||
Animator characterAnimator;
|
}
|
||||||
|
|
||||||
AbstractMap map;
|
protected override void Compute()
|
||||||
|
{
|
||||||
#region 动画控制参数
|
power = 900;//功率
|
||||||
Vector3 nextPos;
|
speed = Helper.CalculateSpeed(elevation, currentSlope, power, weight, bicycleWeight);
|
||||||
Vector3 prePos;
|
distance = Math.Round(speed / 3600, 6);
|
||||||
Vector2d currentlatlong; //当前坐标
|
totalDistance += distance;
|
||||||
Vector2d nextlatlong; //下一个点的坐标
|
}
|
||||||
float timer = 1.0f;//计时器
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 选手骑行数据
|
|
||||||
bool isStart;
|
|
||||||
bool isMajor;//是否是主人公
|
|
||||||
MapDataModel mapData;
|
|
||||||
int userId;
|
|
||||||
DateTime startTime;//开始骑行时间
|
|
||||||
|
|
||||||
double speed;
|
|
||||||
double power;
|
|
||||||
double gradev;
|
|
||||||
double elevation;
|
|
||||||
double cadance;
|
|
||||||
double heartRate;
|
|
||||||
int ticks;
|
|
||||||
double totalDistance;
|
|
||||||
double currentSlope;
|
|
||||||
double nextSlope;
|
|
||||||
double nextSlopeDistance;
|
|
||||||
double distance;
|
|
||||||
|
|
||||||
public int UserId { get => userId; }
|
|
||||||
public bool IsStart { get => isStart; }
|
|
||||||
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 CurrentSlope { get => currentSlope; }
|
|
||||||
public double NextSlope { get => nextSlope; }
|
|
||||||
public double NextSlopeDistance { get => nextSlopeDistance; }
|
|
||||||
public double Gradev { get => gradev; }
|
|
||||||
public double Elevation { get => elevation; }
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
characterAnimator = GetComponentInChildren<Animator>();
|
|
||||||
var mainController = transform.parent.GetComponent<CyclingController>();
|
|
||||||
map = FindObjectOfType<AbstractMap>();
|
|
||||||
mapData = mainController.GetMapData();//获取路书信息
|
|
||||||
isStart = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
timer -= Time.deltaTime;
|
|
||||||
if (timer <= 0)//定时器 一秒执行一次
|
|
||||||
{
|
|
||||||
Run();
|
|
||||||
timer = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 骑行逻辑
|
|
||||||
|
|
||||||
//骑行中
|
|
||||||
void Run()
|
|
||||||
{
|
|
||||||
if (IsStart)
|
|
||||||
{
|
|
||||||
power = 900;//功率
|
|
||||||
speed = Helper.CalculateSpeed(elevation, 0, power, 65, 7);
|
|
||||||
distance = Math.Round(speed / 3600, 6);
|
|
||||||
totalDistance += distance;
|
|
||||||
characterAnimator.SetBool("IsRide", false);//初始化动画状态
|
|
||||||
if (totalDistance <= mapData.TotalDistance)
|
|
||||||
{
|
|
||||||
//数据处理
|
|
||||||
ticks++;
|
|
||||||
nextlatlong = Along(totalDistance);//下一个坐标
|
|
||||||
nextPos = map.GeoToWorldPosition(nextlatlong);//下一个点
|
|
||||||
nextPos.y += 0.3f;
|
|
||||||
prePos = transform.localPosition;//当前点
|
|
||||||
//动画控制
|
|
||||||
if (distance > 0)
|
|
||||||
{
|
|
||||||
characterAnimator.SetBool("IsRide", true);//开始移动动画
|
|
||||||
StartCoroutine(LookAtNextPos());//转向
|
|
||||||
StartCoroutine(MoveTo());//移动
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//TODO保存骑行数据
|
|
||||||
characterAnimator.SetBool("ReachEnd", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
characterAnimator.SetBool("IsRide", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 工具类
|
|
||||||
public int CurrentIndex;
|
|
||||||
//根据距离计算坐标
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
return nextlatlong;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 人物移动与转向控制
|
|
||||||
IEnumerator LookAtNextPos()
|
|
||||||
{
|
|
||||||
Quaternion neededRotation = Quaternion.LookRotation(transform.localPosition - nextPos);
|
|
||||||
Quaternion thisRotation = character.transform.localRotation;
|
|
||||||
|
|
||||||
float t = 0;
|
|
||||||
while (t < 1.0f)
|
|
||||||
{
|
|
||||||
t += Time.deltaTime / 0.25f;
|
|
||||||
var rotationValue = Quaternion.Slerp(thisRotation, neededRotation, t);
|
|
||||||
character.transform.rotation = Quaternion.Euler(0, rotationValue.eulerAngles.y, 0);
|
|
||||||
yield return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//人物移动控制
|
|
||||||
IEnumerator MoveTo()
|
|
||||||
{
|
|
||||||
//让人物移动分点增加动画的流畅度
|
|
||||||
float t = 0;
|
|
||||||
while (t < 1)
|
|
||||||
{
|
|
||||||
t += Time.deltaTime;
|
|
||||||
Vector3 v = Vector3.Lerp(prePos, nextPos, t);
|
|
||||||
transform.localPosition = v;
|
|
||||||
//控制海拔图的位置
|
|
||||||
|
|
||||||
yield return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,225 +1,57 @@
|
|||||||
using System.Collections;
|
using UnityEngine;
|
||||||
using UnityEngine;
|
|
||||||
using Mapbox.Unity.Map;
|
|
||||||
using Mapbox.Utils;
|
|
||||||
using Assets.Scripts.Apis.Models;
|
using Assets.Scripts.Apis.Models;
|
||||||
using static Assets.Scripts.Apis.Models.MapDataModel;
|
|
||||||
using System;
|
using System;
|
||||||
using Random = UnityEngine.Random;
|
|
||||||
using Assets.Scripts.Apis;
|
using Assets.Scripts.Apis;
|
||||||
using GeoJSON.Net.Geometry;
|
|
||||||
using TurfCS;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Assets.Scenes.Ride.Scripts.Model;
|
using Assets.Scenes.Ride.Scripts.Model;
|
||||||
using static CyclingController;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Assets.Scenes.Ride.Scripts.Model.CyclingModels;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Assets.Scenes.Ride.Scripts
|
namespace Assets.Scenes.Ride.Scripts
|
||||||
{
|
{
|
||||||
public class PlayerController : MonoBehaviour
|
public class PlayerController : AbstractPlayer
|
||||||
{
|
{
|
||||||
[Header("Character")]
|
|
||||||
[SerializeField]
|
|
||||||
GameObject character;
|
|
||||||
[SerializeField]
|
|
||||||
Animator characterAnimator;
|
|
||||||
//[SerializeField]
|
|
||||||
AbstractMap map;
|
|
||||||
|
|
||||||
#region 动画控制参数
|
|
||||||
Vector3 nextPos;
|
|
||||||
Vector3 prePos;
|
|
||||||
Vector2d currentlatlong; //当前坐标
|
|
||||||
Vector2d nextlatlong; //下一个点的坐标
|
|
||||||
float timer = 1.0f;//计时器
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 选手骑行数据
|
|
||||||
bool isStart;
|
|
||||||
bool isMajor;//是否是主人公
|
|
||||||
MapDataModel mapData;
|
|
||||||
int userId;
|
|
||||||
int routeId;
|
|
||||||
DateTime startTime;//开始骑行时间
|
|
||||||
BaseCycling baseCycling;
|
|
||||||
|
|
||||||
double speed;
|
|
||||||
double power;
|
|
||||||
double elevation;
|
|
||||||
double cadance;
|
|
||||||
int heartRate;
|
|
||||||
int ticks;
|
|
||||||
double totalDistance;
|
|
||||||
double currentSlope;
|
|
||||||
double nextSlope;
|
|
||||||
double nextSlopeDistance;
|
|
||||||
double currentSlopeDistance;
|
|
||||||
double distance;
|
|
||||||
|
|
||||||
public int UserId { get => userId; }
|
|
||||||
public bool IsStart { get => isStart; }
|
|
||||||
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; }
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
characterAnimator = GetComponentInChildren<Animator>();
|
|
||||||
var mainController = transform.parent.GetComponent<CyclingController>();
|
|
||||||
map = FindObjectOfType<AbstractMap>();
|
|
||||||
mapData = mainController.GetMapData();//获取路书信息
|
|
||||||
routeId = mainController.RouteId;//路数id
|
|
||||||
Initialize(mainController.GetCenterCoordinate());//初始人物
|
|
||||||
baseCycling = mainController.cyclingController;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
timer -= Time.deltaTime;
|
|
||||||
if (timer <= 0)//定时器 一秒执行一次
|
|
||||||
{
|
|
||||||
Run();
|
|
||||||
timer = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 游戏状态控制
|
|
||||||
//开始骑行
|
|
||||||
public void SetStart()
|
|
||||||
{
|
|
||||||
isStart = true;
|
|
||||||
startTime = DateTime.Now;
|
|
||||||
}
|
|
||||||
//继续骑行
|
|
||||||
public void SetContinue()
|
|
||||||
{
|
|
||||||
isStart = true;
|
|
||||||
}
|
|
||||||
//暂停骑行
|
|
||||||
public void SetPause()
|
|
||||||
{
|
|
||||||
isStart = false;
|
|
||||||
Complete();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 骑行逻辑
|
#region 骑行逻辑
|
||||||
|
|
||||||
//初始化玩家距离/朝向
|
|
||||||
void Initialize(double[] coordinates)
|
|
||||||
{
|
|
||||||
ticks = 0;//当前骑行时间
|
|
||||||
//初始化人物位置
|
|
||||||
totalDistance = 0;//TODO:根据骑行模式动态取值 KM
|
|
||||||
currentlatlong = Along(totalDistance);//new Vector2d(coordinates[0], coordinates[1]);//当前坐标
|
|
||||||
nextlatlong = currentlatlong;//下一秒坐标
|
|
||||||
////初始化人物转向
|
|
||||||
//var secondPlace = mapData.List[10].Point;
|
|
||||||
//var secondVect3d = map.GeoToWorldPosition( new Vector2d(secondPlace[0], secondPlace[1]));
|
|
||||||
//Quaternion firstRotation = Quaternion.LookRotation(transform.localPosition - secondVect3d);
|
|
||||||
//character.transform.rotation = Quaternion.Euler(0, firstRotation.eulerAngles.y, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TargetData> RiderDatas = new List<TargetData>();
|
public List<TargetData> RiderDatas = new List<TargetData>();
|
||||||
//骑行中
|
protected override void Init()
|
||||||
void Run()
|
{
|
||||||
{
|
base.Init();
|
||||||
ComputeMapData();//计算海拔&坡度&下一个点信息
|
|
||||||
if (IsStart)
|
|
||||||
{
|
|
||||||
//CamControl();
|
|
||||||
power = 2000;//功率
|
|
||||||
speed = Helper.CalculateSpeed(elevation, currentSlope, power, 65, 7);
|
|
||||||
distance = Math.Round(speed / 3600, 6);
|
|
||||||
totalDistance += distance;
|
|
||||||
|
|
||||||
characterAnimator.SetBool("IsRide", false);//初始化动画状态
|
|
||||||
if (totalDistance <= mapData.TotalDistance)
|
|
||||||
{
|
|
||||||
//数据处理
|
|
||||||
ticks++;
|
|
||||||
nextlatlong = Along(totalDistance);//下一个坐标
|
|
||||||
|
|
||||||
nextPos = map.GeoToWorldPosition(nextlatlong);//下一个点
|
|
||||||
nextPos.y += 0.3f;
|
|
||||||
prePos = transform.localPosition;//当前点
|
|
||||||
//记录骑行数据
|
|
||||||
var recordText = string.Format($"{ ticks },{ power.ToString(CultureInfo.InvariantCulture) },{ speed.ToString(CultureInfo.InvariantCulture) },{ Math.Round(totalDistance, 6).ToString(CultureInfo.InvariantCulture) },{ cadance.ToString(CultureInfo.InvariantCulture) },{ heartRate.ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.x, 6).ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.y, 6).ToString(CultureInfo.InvariantCulture) }");
|
|
||||||
Debug.Log(recordText);
|
|
||||||
|
|
||||||
RiderDatas.Add(new TargetData
|
|
||||||
{
|
|
||||||
Ticks = ticks,
|
|
||||||
_Power = power,
|
|
||||||
_Speed = speed,
|
|
||||||
_Distance = totalDistance,
|
|
||||||
_Cadence = cadance,
|
|
||||||
_HeartRate = heartRate,
|
|
||||||
_Lat = nextlatlong.x,
|
|
||||||
_Lon = nextlatlong.y
|
|
||||||
});
|
|
||||||
|
|
||||||
//动画控制
|
|
||||||
if (distance > 0)
|
|
||||||
{
|
|
||||||
characterAnimator.SetBool("IsRide", true);//开始移动动画
|
|
||||||
StartCoroutine(LookAtNextPos());//转向
|
|
||||||
StartCoroutine(MoveTo());//移动
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
totalDistance = mapData.TotalDistance;
|
|
||||||
characterAnimator.SetBool("ReachEnd", true);
|
|
||||||
|
|
||||||
////记录骑行数据
|
|
||||||
//var recordText = string.Format($"{ ticks },{ power.ToString(CultureInfo.InvariantCulture) },{ speed.ToString(CultureInfo.InvariantCulture) },{ Math.Round(totalDistance, 6).ToString(CultureInfo.InvariantCulture) },{ cadance.ToString(CultureInfo.InvariantCulture) },{ heartRate.ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.x, 6).ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.y, 6).ToString(CultureInfo.InvariantCulture) }");
|
|
||||||
//Debug.Log(recordText);
|
|
||||||
//RiderDatas.Add(new TargetData
|
|
||||||
//{
|
|
||||||
// Ticks = ticks,
|
|
||||||
// _Power = power,
|
|
||||||
// _Speed = speed,
|
|
||||||
// _Distance = totalDistance,
|
|
||||||
// _Cadence = cadance,
|
|
||||||
// _HeartRate = heartRate,
|
|
||||||
// _Lat = nextlatlong.x,
|
|
||||||
// _Lon = nextlatlong.y
|
|
||||||
//});
|
|
||||||
Task.Run(() =>
|
|
||||||
{
|
|
||||||
Complete();
|
|
||||||
});
|
|
||||||
isStart = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
characterAnimator.SetBool("IsRide", false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//发送当前用户位置给UDPs
|
protected override void Compute()
|
||||||
void SendUdp() {
|
{
|
||||||
|
//计算数据
|
||||||
}
|
power = 2000;//功率
|
||||||
//TODO:骑行结束
|
speed = Helper.CalculateSpeed(elevation, currentSlope, power, weight, bicycleWeight);
|
||||||
private int weight = 65;
|
distance = Math.Round(speed / 3600, 6);
|
||||||
private int bicycleWeight = 7;
|
totalDistance += distance;
|
||||||
|
//记录骑行数据
|
||||||
|
var recordText = string.Format($"{ ticks },{ power.ToString(CultureInfo.InvariantCulture) },{ speed.ToString(CultureInfo.InvariantCulture) },{ Math.Round(totalDistance, 6).ToString(CultureInfo.InvariantCulture) },{ cadance.ToString(CultureInfo.InvariantCulture) },{ heartRate.ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.x, 6).ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.y, 6).ToString(CultureInfo.InvariantCulture) }");
|
||||||
|
Debug.Log(recordText);
|
||||||
|
RiderDatas.Add(new TargetData
|
||||||
|
{
|
||||||
|
Ticks = ticks,
|
||||||
|
_Power = power,
|
||||||
|
_Speed = speed,
|
||||||
|
_Distance = totalDistance,
|
||||||
|
_Cadence = cadance,
|
||||||
|
_HeartRate = heartRate,
|
||||||
|
_Lat = nextlatlong.x,
|
||||||
|
_Lon = nextlatlong.y
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//上传数据
|
||||||
|
protected override void Upload()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 保存骑行数据 准备迁移
|
||||||
|
|
||||||
|
|
||||||
private string ContinueMark = "TODO";
|
private string ContinueMark = "TODO";
|
||||||
private int ContinueIndex=0;
|
private int ContinueIndex=0;
|
||||||
private int Competitionid =0;
|
private int Competitionid =0;
|
||||||
@ -245,7 +77,7 @@ namespace Assets.Scenes.Ride.Scripts
|
|||||||
var interruptRecord = new MapInterruptRecord
|
var interruptRecord = new MapInterruptRecord
|
||||||
{
|
{
|
||||||
Id = recordId,
|
Id = recordId,
|
||||||
RouteId = routeId,
|
RouteId = 1,
|
||||||
RouteName = "",
|
RouteName = "",
|
||||||
TotalDistance = mapData.TotalDistance,
|
TotalDistance = mapData.TotalDistance,
|
||||||
UserId = userId,
|
UserId = userId,
|
||||||
@ -310,107 +142,8 @@ namespace Assets.Scenes.Ride.Scripts
|
|||||||
|
|
||||||
var result = api.Add(interruptRecord, files);
|
var result = api.Add(interruptRecord, files);
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 工具类
|
|
||||||
public int CurrentIndex;
|
|
||||||
//当前距离所在的海拔/坡度/距离 下一个点的坡度以及剩余距离
|
|
||||||
void ComputeMapData()
|
|
||||||
{
|
|
||||||
double sumDistance = 0;
|
|
||||||
var pointList = mapData.List;
|
|
||||||
int index = 0;
|
|
||||||
for (int i = 0; i < pointList.Count; i++)
|
|
||||||
{
|
|
||||||
sumDistance += pointList[i].Distance;
|
|
||||||
if (totalDistance * 1000 <= sumDistance)
|
|
||||||
{
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//计算当前海拔和坡度
|
|
||||||
elevation = pointList[index].Elevation;
|
|
||||||
currentSlope = pointList[index].Grade;
|
|
||||||
//计算下一个点的坡度和距离
|
|
||||||
int nextIndex = index == pointList.Count - 1 ? index : index + 1;
|
|
||||||
CurrentIndex = nextIndex;
|
|
||||||
nextSlope = pointList[nextIndex].Grade;
|
|
||||||
nextSlopeDistance = sumDistance - totalDistance*1000;
|
|
||||||
currentSlopeDistance = totalDistance * 1000 - (sumDistance- pointList[index].Distance);
|
|
||||||
}
|
|
||||||
//根据距离计算坐标
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
return nextlatlong;
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 人物移动与转向控制
|
#endregion
|
||||||
IEnumerator LookAtNextPos()
|
}
|
||||||
{
|
|
||||||
Quaternion neededRotation = Quaternion.LookRotation(transform.localPosition - nextPos);
|
|
||||||
Quaternion thisRotation = character.transform.localRotation;
|
|
||||||
|
|
||||||
float t = 0;
|
|
||||||
while (t < 1.0f)
|
|
||||||
{
|
|
||||||
t += Time.deltaTime / 0.25f;
|
|
||||||
var rotationValue = Quaternion.Slerp(thisRotation, neededRotation, t);
|
|
||||||
character.transform.rotation = Quaternion.Euler(0, rotationValue.eulerAngles.y, 0);
|
|
||||||
yield return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//人物移动控制
|
|
||||||
IEnumerator MoveTo()
|
|
||||||
{
|
|
||||||
//让人物移动分点增加动画的流畅度
|
|
||||||
float t = 0;
|
|
||||||
while (t < 1)
|
|
||||||
{
|
|
||||||
t += Time.deltaTime;
|
|
||||||
Vector3 v = Vector3.Lerp(prePos, nextPos, t);
|
|
||||||
transform.localPosition = v;
|
|
||||||
//控制海拔图的位置
|
|
||||||
|
|
||||||
yield return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 相机控制
|
|
||||||
//[Header("CameraSettings")]
|
|
||||||
//[SerializeField]
|
|
||||||
//Camera cam;
|
|
||||||
//Vector3 previousPos = Vector3.zero;
|
|
||||||
//Vector3 deltaPos = Vector3.zero;
|
|
||||||
|
|
||||||
// IEnumerator CamControl()//替换成cinemachine
|
|
||||||
//{
|
|
||||||
// if (cam != null)
|
|
||||||
// {
|
|
||||||
// float t = 0;
|
|
||||||
// while (t < 1.0f)
|
|
||||||
// {
|
|
||||||
// t += Time.deltaTime / 0.5f;
|
|
||||||
// deltaPos = transform.position - previousPos;
|
|
||||||
// //deltaPos.y = 0;
|
|
||||||
// cam.transform.position = Vector3.Lerp(cam.transform.position, cam.transform.position + deltaPos, t);
|
|
||||||
// previousPos = transform.position;
|
|
||||||
// yield return null;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user