using System; using System.Linq; using UnityEngine; using UnityEngine.UI; using Assets.Core; using Assets.Scripts.Apis.Models; using DG.Tweening; using Mapbox.Utils; using Assets.Scenes.Ride.Scripts; using UnityEngine.Assertions; namespace Assets.Scripts.Scenes.VideoRide { public abstract class AbstractVideoPlayer : MonoBehaviour, IRider { public double Diff { get;set; } protected int currentFrame { get; set; } protected Animator animator { get; set; } public GameObject head { get; set; } protected Image ftpImage { get; set; } protected Text headName { get; set; } protected Text headWkg { get; set; } public int userId { get; set; } public string userName { get; set; } public double weight;//体重 protected double bicycleWeight;//车重 protected double preSpeed; public double speed; public double distance; public double power; public double elevation { get; set; } public double cadance { get; set; } public double wkg { get; set; } public int? heartRate { get; set; } public double totalDistance { get; set; } public double currentSlope { get; set; } protected double nextSlope { get; set; } protected double nextSlopeDistance { get; set; } protected double currentSlopeDistance { get; set; } public double totalClimb { get; set; } public Vector2d currentlatLon { get; set; } public int currentIndex { get; set; } public int ticks { get; set; } protected MapDataModel mapData; protected bool start = true; protected VideoGameManager manager { get; set; } Transform bone_bottle_2 { get; set; } public double Speed { get; set; } public double StartDistance { get; set; } public double PreDistance { get; set; } public double EndDistance { get; set; } public double OnlineSpeed { get; set; } public int UserId => this.userId; public string UserName => this.userName; public double mockpower { get; set; } protected float ratio = 1; private static readonly int PreSpeed = Animator.StringToHash("preSpeed"); private static readonly int AnimatorSpeed = Animator.StringToHash("speed"); private static readonly int Grade = Animator.StringToHash("grade"); private static readonly int Power = Animator.StringToHash("power"); private Camera mainCamera; protected virtual void Start() { animator = GetComponent(); manager = FindObjectOfType(); mapData = manager.GetMapData(); ComputeNextSlope();//初始化坡度等 bone_bottle_2 = transform.Find("bone_cable_20"); mainCamera = Camera.main; } protected virtual void Update() { CreateHeadImage(); ComputeAnimator();//控制动画 ComputeAnimatorSpeed();//控制动画速度 } public void StartAction() { try { if (manager.IsStart()) { ComputeTimerTick(); ComputeNextSlope();//计算下一个坡度 ComputePlayer();//计算人物属性 Forward(); ComputeRecord(); } else { power = 0; OnlineSpeed = 0; PreDistance = EndDistance; speed = 0; distance = 0; } } catch (Exception e) { power = 0; speed = 0; Debug.LogError(e.Message); } } private void ComputeTimerTick() { ticks++; } public virtual void ComputeAnimator() { if (animator != null) { animator.SetFloat(PreSpeed, (float)preSpeed); animator.SetFloat(AnimatorSpeed, (float)OnlineSpeed); animator.SetFloat(Grade, (float)currentSlope); animator.SetFloat(Power, (float)power); } } //计算人物当前属性 public virtual void ComputePlayer() { if (power > 0) { preSpeed = speed; speed = Helper.CalculateSpeed(elevation, currentSlope, power, weight, bicycleWeight); } else { speed = 0; distance = 0; } } //计算当前人物的经纬度 public virtual void Forward() { try { if (mapData == null) mapData = manager.GetMapData(); currentlatLon = manager.Along(totalDistance % mapData.TotalDistance); } catch (Exception e) { Debug.LogError(e); } } public virtual void ComputeAnimatorSpeed() { Assert.IsNotNull(manager); mapData = manager.GetMapData(); var safeIndex = currentIndex + 1 < mapData.List.Count ? currentIndex + 1 : currentIndex; var num = speed == 0 ? 1f : (float)(speed / mapData.List[safeIndex].Distance); ratio = Mathf.Clamp(num, 0.3f, 1.2f); var info = animator.GetCurrentAnimatorClipInfo(0); if (info == null) return; var currentClip = info.FirstOrDefault(); if (currentClip.clip != null) { animator.speed = ratio; } } public virtual void ComputeRecord() { } private const double DoubleDelta = 1E-6; private const double GradeFactor = 0.5f; //计算当前区段属性下一个区段属性 public void ComputeNextSlope() { double sumDistance = 0; 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 left = (decimal)totalDistance % (decimal)mapData.TotalDistance;//处理多圈的情况 left *= 1000; decimal right = (decimal)sumDistance; if (left <= right) { currentIndex = i; break; } } if (Math.Abs(totalDistance - mapData.TotalDistance) < DoubleDelta) { currentIndex = pointList.Count - 1; } Debug.Log(currentIndex); preIndex = currentIndex > 0 ? currentIndex - 1 : 0;//前一个索引 int nextIndex = currentIndex == pointList.Count - 1 ? currentIndex : currentIndex + 1; //计算下一个点的坡度和距离 elevation = pointList[currentIndex].Elevation; currentSlope = pointList[currentIndex].Grade * GradeFactor; //CurrentDistance = pointList[currentIndex].Distance; //计算下一个海拔和坡度&当前区间距离 nextSlope = pointList[nextIndex].Grade * GradeFactor; 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; } } } private void OnDisable() { head?.SetActive(false); } private void OnEnable() { head?.SetActive(true); } //显示人物头顶的名字 public virtual void CreateHeadImage() { if (head == null) { if (manager.GetHeadInfo() != null) { head = Instantiate(manager.GetHeadInfo(), manager.GetCanvasTransform()); ftpImage = head.transform.Find("ftp").GetComponent(); headName = head.transform.Find("name").GetComponent(); headWkg = head.transform.Find("wkg").GetComponent(); } } UpdateHead(); } private void UpdateHead() { if (head == null) return; //update position var position = bone_bottle_2.position; var worldPosition = new Vector3(position.x, position.y + transform.localScale.y, position.z); var playerScreenPos = mainCamera.WorldToScreenPoint(worldPosition); playerScreenPos.y += 16f; head.transform.position = playerScreenPos; //update info ftpImage.fillAmount = (float)(wkg / 6); headName.text = UserName; headWkg.text = $"{wkg}W/KG"; } private void OnBecameInvisible() { head.SetActive(false); } private void OnBecameVisible() { head.SetActive(true); } public void SetStartDistance(double distance) { this.StartDistance = distance *1000; } public void Destroy() { if (manager.CurrentPlayer != null && manager.CurrentPlayer.UserId == UserId) { manager.Pause(); } head?.Destroy(); gameObject.Destroy(); } //设置当前玩家属性 public abstract void SetPlayer(string name, double speed, double preDistance, double endDistance, double cadance, double heartRate, double wkg, int userId, double power, double currentPlayerDistance, int frame); } }