using Assets.Scenes.Ride.Scripts; using Assets.Scripts.Apis.Models; using Assets.Scenes.Ride.Scripts.Model; using DG.Tweening; using Mapbox.Utils; using System; using System.Collections; using System.Linq; using UnityEngine; using UnityEngine.UI; namespace Assets.Scripts.Scenes.VideoRide { public abstract class AbstractVideoPlayer : MonoBehaviour { protected Animator animator; public GameObject head { get; set; } protected Image ftpImage { get; set; } protected Text headName { get; set; } protected Text headWkg { get; set; } public int UserId; public string UserName; public double weight;//体重 protected double bicycleWeight;//车重 protected double preSpeed; public double speed; public double power; protected double elevation; public double cadance; public double wkg; public int? heartRate { get; set; } public int ticks; public double totalDistance; public double currentSlope; protected double nextSlope; protected double nextSlopeDistance; public double distance; protected double currentSlopeDistance; protected double lastEndDistance; public double totalClimb; public Vector2d currentlatLon { get; set; } public int currentIndex; public float bearing = 0f; protected MapDataModel mapData; protected bool isHit = false; protected RaycastHit hit; float timer = 1f; protected bool start = true; protected Sequence sequence; protected VideoGameManager manager { get; set; } Camera camera; float currenPlayerHeight; Transform bone_bottle_2 { get; set; } protected virtual void Start() { animator = GetComponent(); manager = FindObjectOfType(); mapData = manager.GetMapData(); ComputeNextSlope();//初始化坡度等 if (speed > 0) { animator.Play("rideLoop"); } else { animator.Play("idle"); } camera = Camera.main; //bone_bottle_2 bone_bottle_2 = transform.Find("bone_cable_20"); var config = manager.mockDirection; pre = config[0]; next = config[0]; } //人物状态 public const int HERO_UP = 0; public const int HERO_RIGHT = 1; public const int HERO_DOWN = 2; public const int HERO_LEFT = 3; //人物当前行走的方向状态 public int state = 0; //人物移动速度 public int moveSpeed = 2; protected virtual void Update() { timer -= Time.deltaTime; CreateHeadImage(); Turn(); while (timer <= 0) { try { ComputeNextSlope();//计算下一个坡度 if (GetStart()) { ticks++; ComputePlayer();//计算人物属性 Forward(); ComputeRecord(); ComputeVideo(); RayCastHit(); } ComputeAnimator();//控制动画 timer += 1f; } catch (Exception e) { power = 0; speed = 0; Debug.LogError(e.Message); } } } //人物碰撞 void OnCollisionEnter(Collision collision) { } void RayCastHit() { Vector3 pos = transform.position; Ray ray = new Ray(pos, new Vector3(0, 0, 1)); isHit = Physics.Raycast(ray, out hit, 1f, 1 << 0, QueryTriggerInteraction.Collide); } protected virtual bool GetStart() { return true; } //动画状态机 protected virtual void ComputeAnimator() { if (animator != null) { animator.SetFloat("preSpeed", (float)preSpeed); animator.SetFloat("speed", (float)speed); animator.SetFloat("grade", (float)currentSlope); animator.SetFloat("power", (float)power); //播放喝水和回头的动画 var headBack = ticks % 60 == 0 && speed > 0; var drink = ticks % 125 == 0 && speed > 0; animator.SetBool("headBack", headBack); animator.SetBool("drinking", drink); } } protected virtual int GetCurrentFrame() { return manager.GetCurrentFrame(); } protected CustomRange pre { get; set; } protected CustomRange next { get; set; } protected float t { get; set; } protected virtual void Turn() { //控制人物的转向 var currentFrame = GetCurrentFrame(); var config = manager.mockDirection; if (config.Count == 0) return; for (int i = 0; i < config.Count; i++) { if (config[i].KeyFrame >= currentFrame) { pre = i > 0 ? config[i - 1] : config[i]; next = config[i]; break; } } var p = new Vector3(0, pre.RotationY, pre.RotationZ); var q = new Vector3(0, next.RotationY, next.RotationZ); t = next.KeyFrame - pre.KeyFrame == 0 ? 1 : (float)(currentFrame - pre.KeyFrame) / (float)(next.KeyFrame - pre.KeyFrame); var rt = Vector3.Lerp(p, q, t); transform.DORotate(rt, 0, RotateMode.Fast); } //计算人物当前属性 protected virtual void ComputePlayer() { if (power > 0) { preSpeed = speed; speed = Helper.CalculateSpeed(elevation, currentSlope, power, weight, bicycleWeight); } else { speed = 0; distance = 0; } ////一旦有功率就开始骑行、否则暂停 //if (!manager.IsQuit() && manager.CurrentPlayer.UserId == UserId && !manager.IsQuit() && manager.cyclingModel == CyclingModel.Single) //{ // if (power > 0) // { // manager.StartGame(); // } //} } Vector3 current { get; set; } Vector3 forward { get; set; } //计算当前人物的经纬度 protected virtual void Forward() { try { if (mapData == null) mapData = manager.GetMapData(); currentlatLon = manager.Along(totalDistance % mapData.TotalDistance); } catch (Exception e) { Debug.LogError(e); } } protected float ratio = 1;//视频播放速率 protected virtual void ComputeVideo() { mapData = manager.GetMapData(); if (currentIndex + 1 < mapData.List.Count) { ratio = (float)(speed / mapData.List[currentIndex + 1].Speed); } else { ratio = (float)(speed / mapData.List[currentIndex].Speed); } if (manager.CurrentPlayer != null && manager.CurrentPlayer.UserId != UserId) return; //ratio = (float)Math.Round(ratio, 1); manager.Play(totalDistance); if (ratio > 1) { ratio = Math.Min(ratio, 1.2f); } if (ratio < 1) { ratio = Math.Max(ratio, 0.6f); } var info = animator.GetCurrentAnimatorClipInfo(0); var currentClip = info.FirstOrDefault(); if (currentClip.clip != null && currentClip.clip.isLooping) { animator.speed = ratio; } } protected virtual void ComputeRecord() { } //计算当前区段属性下一个区段属性 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) { Debug.Log($"当前索引{i}"); 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; } } } //显示人物海拔图的头像 protected 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(); } } if (head != null) { //它们的乘积就是高度 Vector3 worldPosition = new Vector3(bone_bottle_2.position.x, bone_bottle_2.position.y+0.8f, bone_bottle_2.position.z); var playerScreenPos = Camera.main.WorldToScreenPoint(worldPosition); head.transform.position = playerScreenPos; ftpImage.fillAmount = (float)(wkg / 6); headName.text = UserName; headWkg.text = $"{wkg}W/KG"; } } public void Destroy() { if (manager.CurrentPlayer != null && manager.CurrentPlayer.UserId == UserId) { manager.Pause(); } head?.Destroy(); gameObject.Destroy(); } } }