powerfun-unity/Assets/Scenes/Ride/Scripts/PlayerController.cs

249 lines
6.7 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 System.Collections;
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;
namespace Assets.Scenes.Ride.Scripts
{
public class PlayerController : MonoBehaviour
{
[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;
MapDataModel mapData;
int userId;
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<MainController>();
mapData = mainController.GetMapData();//获取路书信息
InitializePlayer(mainController.GetCenterCoordinate());//初始人物
}
void Update()
{
timer -= Time.deltaTime;
if (timer <= 0)//定时器 一秒执行一次
{
Run();
timer = 1.0f;
}
}
#region
//当前人物骑行状态 true 开始 false 暂停
public void SetStart(bool start)
{
isStart = start;
}
//初始化玩家距离/朝向
void InitializePlayer(double[] coordinates)
{
ticks = 0;//当前骑行时间
//初始化人物位置
totalDistance = 10;//TODO:根据骑行模式动态取值
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);
}
//骑行中
void Run()
{
if (IsStart)
{
//CamControl();
ComputeMapData();//计算海拔&坡度&下一个点信息
power = 300;//功率
speed = Helper.CalculateSpeed(elevation, gradev, power, 65, 7);
distance = Math.Round(speed / 3600, 5);
totalDistance += distance;
characterAnimator.SetBool("IsRide", false);//初始化动画状态
if (totalDistance <= mapData.TotalDistance)
{
ticks++;
if (distance > 0)
{
characterAnimator.SetBool("IsRide", true);//开始移动动画
nextlatlong = Along(totalDistance);//下一个坐标
nextPos = map.GeoToWorldPosition(nextlatlong);//下一个点
prePos = transform.localPosition;//当前点
StartCoroutine(LookAtNextPos());//转向
StartCoroutine(MoveTo());//移动
}
}
else
{
//TODO保存骑行数据
}
}
else
{
characterAnimator.SetBool("IsRide", false);
}
}
//TODO骑行结束
void Finish()
{
//MapInterruptRecordApi api = new MapInterruptRecordApi();
//api.Add(null, null);
}
#endregion
#region
//当前距离所在的海拔/坡度/距离 下一个点的坡度以及剩余距离
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 >= sumDistance)
{
index = i;
break;
}
}
//计算当前海拔和坡度
elevation = pointList[index].Elevation;
gradev = pointList[index].Grade;
//计算下一个点的坡度和距离
int nextIndex = index == pointList.Count - 1 ? index : index + 1;
nextSlope = pointList[nextIndex].Grade;
nextSlopeDistance = sumDistance + pointList[nextIndex].Distance - totalDistance;
}
//根据距离计算坐标
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
#region
[Header("CameraSettings")]
[SerializeField]
Camera cam;
Vector3 previousPos = Vector3.zero;
Vector3 deltaPos = Vector3.zero;
IEnumerator CamControl()//TODO 替换成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
}
}