powerfun-unity/Assets/Scripts/Scenes/VideoRide/AbstractVideoPlayer.cs

220 lines
7.9 KiB
C#

using Assets.Scripts.Apis.Models;
using DG.Tweening;
using Mapbox.Utils;
using System;
using UnityEngine;
namespace Assets.Scripts.Scenes.VideoRide
{
public abstract class AbstractVideoPlayer : MonoBehaviour
{
protected Animator animator;
protected double weight;//体重
protected double bicycleWeight;//车重
protected double preSpeed;
protected double speed;
protected double power;
protected double elevation;
protected double cadance;
protected int? heartRate { get; set; }
public int ticks;
protected double totalDistance;
protected double currentSlope;
protected double nextSlope;
protected double nextSlopeDistance;
public double distance;
protected double currentSlopeDistance;
protected double lastEndDistance;
protected double totalClimb;
protected Vector2d currentlatLon;
protected int currentIndex;
protected float bearing = 0f;
protected MapDataModel mapData;
float timer = 1f;
protected bool start = true;
protected VideoGameManager manager { get; set; }
Camera camera;
float currenPlayerHeight;
protected virtual void Start()
{
animator = GetComponent<Animator>();
manager = FindObjectOfType<VideoGameManager>();
mapData = manager.GetMapData();
ComputeNextSlope();//初始化坡度等
animator.Play("idle");
camera = Camera.main;
//注解1
//得到模型原始高度
float size_y = GetComponent<Collider>().bounds.size.y;
//得到模型缩放比例
float scal_y = transform.localScale.y;
//它们的乘积就是高度
currenPlayerHeight = (size_y * scal_y);
}
protected virtual void Update()
{
timer -= Time.deltaTime;
ComputeAnimator();//控制动画
while (timer <= 0)
{
try
{
if (manager.IsStart())
{
ticks++;
ComputeNextSlope();//计算下一个坡度
ComputePlayer();//计算人物属性
ComputeRecord();
ComputeVideo();
ComputeRandom();
}
timer += 1f;
}
catch (Exception e)
{
power = 0;
speed = 0;
Debug.Log(e.Message);
}
//获取player的position信息
Vector3 pos = transform.position;
pos.y += 3f;
//射线碰撞物信息接收
RaycastHit hit;
//第二种写法
//我们可以先创建出一条射线
Ray ray = new Ray(pos, new Vector3(0, -5, 22));
//然后用这条射线去做射线检测
//射线,输出碰撞体信息,射线长度,射线在那一层检测,射线不忽略开启触发器(istrigger)的碰撞体
bool isHit = Physics.Raycast(ray, out hit, 15f, 1 << 0, QueryTriggerInteraction.Collide);
//在unity窗口画出射线
Debug.DrawLine(pos, new Vector3(pos.x, pos.y, pos.z + 5), Color.red);
if (isHit)//如果射线检测到物体
{
//打印出被检测物体的名字
print(hit.transform.name);
transform.DOLocalMoveX(-2, 1);
transform.DOLocalMoveZ(27, 1).onComplete+=()=>{
transform.DOLocalMoveX(2, 1);
};
}
}
}
//人物碰撞
void OnCollisionEnter(Collision collision)
{
if (collision.transform.name != "mc_all_animations")
{
var curX = collision.transform.position.x;
if (curX == 0)
{
var preX = manager.GetSlotIndex();
collision.transform.DOLocalMoveX(preX.Value, 1);
}
}
}
void ComputeRandom()
{
var offset = 30;
if (ticks % 9 == 0)
transform.DOMoveZ(transform.position.z - offset, 1f);
if (ticks % 5 == 0)
transform.DOMoveZ(transform.position.z + offset, 2f);
//人物的rotation y
transform.DOLocalRotate(new Vector3(0f, bearing, 0f), 1f);
}
//动画状态机
void ComputeAnimator()
{
if (animator != null)
{
animator.SetFloat("preSpeed", (float)preSpeed);
animator.SetFloat("speed", (float)speed);
animator.SetFloat("grade", (float)currentSlope);
var currentFrame = manager.GetCurrentFrame();
if (manager.mockDirection.ContainsKey(currentFrame))
{
bearing = manager.mockDirection[currentFrame];
}
animator.SetFloat("bearing", bearing);
}
}
//人相对视频不距离不变。 其他人相对视频做前后位移
//人与人之前前后距离按照射线检测 扇形射线
//人与人左右距离按照碰撞检测
//每个人都实时计算前后距离
//其他玩家相对当前主人公做正向或者反向位移,左右
protected virtual void ChangeToFirst()
{
transform.DOLocalMoveZ(-1, 1);
}
protected virtual void ChangeToThird()
{
transform.DOLocalMoveZ(55, 1);
}
//计算人物当前属性
protected abstract void ComputePlayer();
protected virtual void ComputeVideo(){ }
protected virtual void ComputeRecord() { }
//计算当前区段属性下一个区段属性
void ComputeNextSlope()
{
double sumDistance = 0;
var mapData = manager.GetMapData();
if (mapData == null)
return;
var pointList = mapData.List;
int preIndex = 0;
for (int i = 0; i < pointList.Count; i++)
{
sumDistance += pointList[i].Distance;
decimal left = (decimal)totalDistance * 1000;
decimal right = (decimal)sumDistance;
if (left <= right)
{
currentIndex = i;
break;
}
}
var DOUBLE_DELTA = 1E-6;
if (Math.Abs(totalDistance - mapData.TotalDistance) < DOUBLE_DELTA)
{
currentIndex = pointList.Count - 1;
}
preIndex = currentIndex > 0 ? currentIndex - 1 : 0;//前一个索引
int nextIndex = currentIndex == pointList.Count - 1 ? currentIndex : currentIndex + 1; //计算下一个点的坡度和距离
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[currentIndex].Distance));
//计算累计爬升
totalClimb = 0;
for (int i = 1; i <= currentIndex; i++)
{
var diff = mapData.List[i].Elevation - mapData.List[i - 1].Elevation;
if (diff > 0)
{
totalClimb += diff;
}
}
}
}
}