AR多人骑行研究

This commit is contained in:
lishuo committed 2022-03-10 18:32:53 +08:00
1 parent 448b6d7798
commit 16e416332d
49 files changed
+5956 -1167

No files matched your search

+1 -1
View File
@@ -24,7 +24,7 @@ namespace Assets.Scripts.Apis
return jsonResult;
}
public async Task<JsonResult<List<JObject>>> GetMapInterruptRecord(string keyword, int pageIndex, int pageSize, string type)
public async Task<JsonResult<List<JObject>>> GetMapInterruptRecord(string keyword, int pageIndex, int pageSize, string type= "routes")
{
//RouteResult
return await GetAsync<JsonResult<List<JObject>>>($"MapRecord/v1/GetList?keyword={keyword}&pageIndex={pageIndex}&pageSize={pageSize}&type={type}");
@@ -168,6 +168,7 @@ namespace Assets.Scripts.Apis.Models
public double Grade { get; set; }
public double Bearing { get; set; }
public double Speed { get; set; }
}
public override string ToString()
@@ -106,5 +106,7 @@ namespace Assets.Scripts.Apis.Models
public int GlobalCyclingId { get; set; }
public string Source { get; set; }
public int? LastFrame { get; set; }
}
}
@@ -165,5 +165,7 @@ namespace Assets.Scripts.Apis.Models
public string CanShareOnStrava { get; set; }
public string ViewUrl { get; set; }
public int? LastFrame { get; set; }
}
}
+4 -4
View File
@@ -20,7 +20,7 @@ public delegate void ChangeLanguageDelegate();
public static class App
{
public static string Host = "http://192.168.0.101:5083/";
public static string Host = "http://192.168.0.102:5082/";
public static string AppVersion = Application.version;
@@ -201,9 +201,9 @@ public static class App
static App()
{
InitLanguage();
Host = "https://wx.powerfun.com.cn/";
UdpAddress = new IPEndPoint(IPAddress.Parse("47.97.84.8"), 11000);
TcpAddress = new IPEndPoint(IPAddress.Parse("47.97.84.8"), 11001);
//Host = "https://wx.powerfun.com.cn/";
//UdpAddress = new IPEndPoint(IPAddress.Parse("47.97.84.8"), 11000);
//TcpAddress = new IPEndPoint(IPAddress.Parse("47.97.84.8"), 11001);
//#if !UNITY_EDITOR
// //测试服务器
// Host = "http://pf.juze.pro/";
+1 -1
View File
@@ -345,7 +345,7 @@ namespace Assets.Scripts.Devices.Ant
case SensorType.None:
break;
case SensorType.Cadence:
Debug.LogError("发现踏频设备"+id);
Debug.Log("发现踏频设备"+id);
device = new CadenceDevice(id);
break;
case SensorType.HeartRate:
+1 -1
View File
@@ -65,7 +65,7 @@ public static class PFConstants
{
get
{
return Application.persistentDataPath+@"/video";
return Application.streamingAssetsPath+ @"/AVProVideoSamples";
}
}
@@ -19,15 +19,15 @@ namespace Assets.Scenes.Ride.Scripts.Model.CyclingModels
{
CurrentUser = App.CurrentUser,
Competitionid = 0,
ContinueIndex = 0,
ContinueMark = Guid.NewGuid().ToString(),
ContinueIndex = 0,
ContinueMark = Guid.NewGuid().ToString(),
EndDistance = 0,
IsCompleted = false,
IsNeedRanking = true,
CyclingState = CyclingStateEnum.Prepare,
CurrentRoute = route,
CurrentRouteStartDistance = 0,
StartTime = UIManager.Now.GetDateTime(),//DateTime.Now
StartTime = DateTime.Now,//UIManager.Now.GetDateTime(),//DateTime.Now
selectParam = param
};
@@ -8,6 +8,12 @@ using System.Threading.Tasks;
namespace Assets.Scenes.Ride.Scripts.Model
{
public class VideoMapModel {
public double x { get; set; }
public double y { get; set; }
public double speed { get; set; }
public int position { get; set; }
}
/// <summary>
/// 排名
/// </summary>
@@ -24,7 +24,7 @@ namespace Assets.Scenes.Ride.Scripts.Model
{
get
{
return CurrentUser.Id;
return App.CurrentUser.Id;
}
}
/// <summary>
@@ -104,6 +104,8 @@ namespace Assets.Scenes.Ride.Scripts.Model
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public int? LastFrame { get; set; }
/// <summary>
/// 是否已经保存成功
/// </summary>
@@ -178,6 +180,7 @@ namespace Assets.Scenes.Ride.Scripts.Model
Param = Newtonsoft.Json.JsonConvert.SerializeObject(selectParam),
GlobalCyclingId = 0,
Source = "",
LastFrame = LastFrame
};
//var range = new MapSpeedRange().GetSpeedRange(RiderDatas, CurrentRoute.RouteInstance.Distance);
interruptRecord.SpeedRange = null; //JsonConvert.SerializeObject(range);
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9e12ee4de0a244145b7d08a49220dfc2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,158 @@
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;
protected 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; }
protected virtual void Start()
{
animator = GetComponent<Animator>();
manager = FindObjectOfType<VideoGameManager>();
mapData = manager.GetMapData();
ComputeNextSlope();//初始化坡度等
animator.Play("idle");
}
void Update()
{
timer -= Time.deltaTime;
ComputeAnimator();//控制动画
while (timer <= 0)
{
try
{
if (manager.IsStart())
{
ticks++;
ComputeNextSlope();//计算下一个坡度
ComputePlayer();//计算人物属性
ComputeRecord();
ComputeVideo();
}
timer += 1f;
}
catch (Exception e)
{
power = 0;
speed = 0;
Debug.Log(e.Message);
}
}
}
//人物碰撞
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 ComputeAnimator()
{
if (animator != null)
{
animator.SetFloat("preSpeed", (float)preSpeed);
animator.SetFloat("speed", (float)speed);
animator.SetFloat("grade", (float)currentSlope);
var currentFrame = manager.GetCurrentFrame() ?? 0;
if (manager.mockDirection.ContainsKey(currentFrame))
{
bearing = manager.mockDirection[currentFrame];
}
animator.SetFloat("bearing", bearing);
}
}
//计算人物当前属性
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;
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7fecc58cd22dcfb4b87afc96b5be9d2e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DG.Tweening;
namespace Assets.Scripts.Scenes.VideoRide
{
public class OnlineVideoPlayer : AbstractVideoPlayer
{
public double diff { get; set; }
//计算
protected override void ComputePlayer()
{
diff = 10;
}
//设置当前玩家属性
public void SetPlayer(double power,double distance)
{
transform.DOLocalMoveZ(25, 1);
this.power = power;
this.distance = distance;
this.speed = 20;
this.totalDistance += distance;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a56584ff2ae65dd43af5e8299544f32f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,110 @@
using Assets.Scenes.Ride.Scripts;
using Assets.Scenes.Ride.Scripts.Model;
using Assets.Scripts;
using Assets.Scripts.Apis.Models;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using DG.Tweening;
using UnityEngine.Video;
namespace Assets.Scripts.Scenes.VideoRide
{
public class TestPlayerController : MonoBehaviour
{
UnityWebRequest request = null;
MapDataModel mapData;
MapRoute mapRoute;
int ticks = 0;
float timer = 1f;
double heartRate = 0;
public double power = 800;
double weight = 60;
double bicycleWeight = 10;
double elevation = 0f;
double currentSlope = 0f;
double speed = 0f;
double distance = 0f;
double totalDistance = 0f;
double bearingInterval = 0f;//线路当前转向
Animator animator;
VideoPlayer videoPlayer;
// Start is called before the first frame update
void Start()
{
//测试数据
var routeId = 1255;
mapData = ConfigHelper.mapApi.GetData(routeId);//获取路书地理数据
mapRoute = ConfigHelper.mapApi.GetById(routeId).data;
animator = transform.GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
timer -= Time.deltaTime;
while (timer <= 0)
{
//var animInfo = animator.GetCurrentAnimatorStateInfo(0);
//if (animInfo.normalizedTime < 0.6)
//{
// if (speed > 30)
// {
// animator.Play("New State Right");
// }
// else if (speed > 15)
// {
// animator.Play("RideLoop_Medium_01 1");
// }
// else if (speed == 0)
// {
// animator.Play("OnBicycle_01_Idle 0");
// videoPlayer.Pause();
// }
// else
// {
// animator.Play("RideLoop_01");
// }
//}
ticks++;
ComputeNextSlope();
speed = Helper.CalculateSpeed(elevation, currentSlope, power, weight, bicycleWeight);
distance = Math.Round(speed / 3600, 5, MidpointRounding.AwayFromZero);
totalDistance += distance;
Debug.Log($"ticks:{ticks} speed:{speed} totalDistance:{totalDistance} bearing:{bearingInterval}");
timer += 1f;
transform.DORotate(new Vector3(0f, (float)(180 + bearingInterval), 0f), 1);
}
}
int currentIndex = 0;
void ComputeNextSlope()
{
double sumDistance = 0;
if (mapData == null)
return;
var pointList = mapData.List;
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;
}
elevation = pointList[currentIndex].Elevation;
currentSlope = pointList[currentIndex].Grade;
var preindex = currentIndex - 1 >= 0 ? currentIndex - 1 : 0;
bearingInterval = pointList[currentIndex].Bearing - pointList[preindex].Bearing;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d44d40e0ce48544ab744a5936f71d19
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,294 @@
using Assets.Scenes.Ride.Scripts;
using Assets.Scenes.Ride.Scripts.Model;
using Assets.Scenes.Ride.Scripts.Model.CyclingModels;
using Assets.Scripts.Apis;
using Assets.Scripts.Apis.Models;
using Assets.Scripts.UI.Prefab.Device;
using GeoJSON.Net.Geometry;
using Mapbox.Utils;
using RenderHeads.Media.AVProVideo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TurfCS;
using UnityEngine;
namespace Assets.Scripts.Scenes.VideoRide
{
public class VideoGameManager : DeviceServiceMonoBase
{
private List<VideoMapModel> videoPointList { get; set; }
private VideoPlayer currentVideoPlayer { get; set; }
private MapDataModel mapData { get; set; }
private MediaPlayer mediaPlayer { get; set; }
private bool isStart { get; set; }
private Route route { get; set; }
private MapRoute mapRoute { get; set; }
public RouteResultParam selectParamModel;
public RouteResult routeResult;
public string recordId { get; set; }
public DateTime startTime { get; set; }
public CyclingModel cyclingModel;
public BaseCycling cyclingController;
public Dictionary<int, int> mockDirection = new Dictionary<int, int>();
private double endDistance { get; set; }
public Dictionary<int, bool> slots = new Dictionary<int, bool>();
private async void Awake()
{
base.Awake();
//自动登录
if (App.CurrentUser == null)
{
await Login();
}
DeviceCache.Init(PFConstants.DeviceCacheFolder);
//var check = CheckAnt();
recordId = Guid.NewGuid().ToString();
startTime = UIManager.Now.GetDateTime();
MapUDPService.Init();//初始化TCP
MockDirection();
InitSlots();
}
void Start()
{
//获取媒体播放器
mediaPlayer = FindObjectOfType<MediaPlayer>();
var mapApi = ConfigHelper.mapApi;
const int routeId = 12353;
mapData = mapApi.GetData(routeId);//获取路书地理数据
mapRoute = mapApi.GetById(routeId).data;
route = new Route(mapData, mapRoute);
if (selectParamModel == null)
{
selectParamModel = new RouteResultParam
{
CompetitionId = 0,
ContinueIndex = 0,
ContinueMark = "",
GlobalContinue = false,
EndDistance = 0,
RankingsId = new List<string>(),
OnlineUserId = 0,
RouteId = routeId
};
}
endDistance = 0;
//倒计时5s开始
SetCyclingModel(CyclingModel.Single);
}
// Update is called once per frame
float timer = 1f;
void Update()
{
timer -= Time.deltaTime;
while (timer <= 0)
{
cyclingController?.Run(null);
var onlineRiders = cyclingController.riders;
timer += 1f;
}
}
private void InitSlots()
{
slots.Add(2, true);
slots.Add(4, true);
slots.Add(-2, true);
slots.Add(-6, true);
slots.Add(-4, true);
slots.Add(-8, true);
}
public int? GetSlotIndex()
{
foreach (var item in slots)
{
if (item.Value)
{
slots[item.Key] = false;
return item.Key;
}
}
return 0;
}
public async Task ContinueAsync()
{
//继续骑行数据
var r = await ConfigHelper.mapInterruptRecordApi.GetMapInterruptRecord("重庆", 0, 20, "routes");
if (r.result)
{
var first = r.data.FirstOrDefault();
RouteResult routeResult = first.ToObject<RouteResult>();
if (routeResult.ContinueCyclingParam != null)
{
App.RouteIdParam = routeResult.RouteId;
App.routeResult = routeResult;
//骑行结果
if (App.routeResult != null)
{
routeResult = App.routeResult;
selectParamModel = App.routeResult.ContinueCyclingParam;//继续骑行
SetCyclingModel(CyclingModel.Single);
endDistance = routeResult.EndDistance;
var ratio = endDistance / routeResult.TotalDistance;
var frame = Math.Round(ratio * mediaPlayer.Info.GetMaxFrameNumber());
SetCurrentFrame(routeResult.LastFrame ?? 0);
var v = FindObjectOfType<VideoPlayer>();
v.SetEndDistance(endDistance);
}
}
}
}
private void MockDirection()
{
var text = Resources.Load<TextAsset>("UI/direction");
var arr = text.text.Replace("\r\n", ",").Split(',');
foreach (var item in arr)
{
if (string.IsNullOrEmpty(item))
continue;
mockDirection.Add(Convert.ToInt32(item.Split(':')[0]), Convert.ToInt32(item.Split(':')[1]));
}
}
public void SetCyclingModel(CyclingModel mode)
{
this.cyclingModel = mode;
switch (cyclingModel)
{
case CyclingModel.Single:
cyclingController = new SingleModel(route, selectParamModel);
break;
}
}
//模拟登录
private async Task Login()
{
var result = await new UserApi().Login("15261826280", "123456", "");
App.CurrentUser = result.data;
}
//开始游戏
public void StartGame()
{
startTime = UIManager.Now.GetDateTime();
isStart = true;
}
public bool IsStart()
{
return isStart;
}
//按照某种速度播放视频
public void Play(float playbackRate = 1f)
{
if (mediaPlayer != null)
{
mediaPlayer.PlaybackRate = playbackRate;
mediaPlayer.Play();
}
}
//暂停游戏
public void Pause()
{
mediaPlayer?.Pause();
}
public void Quit()
{
mediaPlayer?.Stop();
}
public int? GetCurrentFrame()
{
return mediaPlayer?.Control.GetCurrentTimeFrames();
}
public void SetCurrentFrame(int seq)
{
mediaPlayer?.Control.SeekToFrame(seq);
}
public void Save(double totalDistance)
{
mediaPlayer?.Pause();//暂停视频
cyclingController.recorderData.EndTime = UIManager.Now.GetDateTime();
isStart = false;
var path = PFConstants.MapWorkoutRecordFolder + "/" + recordId;
Assets.Scenes.Ride.Scripts.Helper.CreateDirectoryIfNotExsit(path);
string imageFileName = path + "/" + Guid.NewGuid().ToString() + ".png";
CaptureCamera(Camera.main, new Rect(Screen.width * 0f, Screen.height * 0f, Screen.width * 0.5f, Screen.height * 0.5f), imageFileName);
cyclingController.recorderData.StartTime = startTime;
cyclingController.recorderData.IsCompleted = totalDistance >= mapData.TotalDistance;
cyclingController.recorderData.EndDistance = totalDistance;
cyclingController.recorderData.AntModelId = AntModelId;
cyclingController.recorderData.ManufacturerId = ManufacturerId;
cyclingController.recorderData.ManufacturerName = ManufacturerName;
cyclingController.recorderData.DeviceNumber = DeviceNumber;
cyclingController.recorderData.LastFrame = GetCurrentFrame();
var RankingId = cyclingController.recorderData.SaveWithLocalRecordAysnc(cyclingModel, selectParamModel, imageFileName, recordId, path);
}
protected void CaptureCamera(Camera camera, Rect rect, string fileName)
{
byte[] bytes = CaptureCameraReturnByte(camera, rect);
//var path = Helper.GetDataDir("MapWorkoutRecords/images");
//string filename = path + "/" + Guid.NewGuid().ToString() + ".png";
System.IO.File.WriteAllBytes(fileName, bytes);
//Debug.Log(string.Format("截屏了一张照片: {0}", filename));
}
private byte[] CaptureCameraReturnByte(Camera camera, Rect rect)
{
// 创建一个RenderTexture对象
RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 0);
// 临时设置相关相机的targetTexture为rt, 并手动渲染相关相机
camera.targetTexture = rt;
camera.Render();
//ps: --- 如果这样加上第二个相机,可以实现只截图某几个指定的相机一起看到的图像。
//ps: camera2.targetTexture = rt;
//ps: camera2.Render();
//ps: -------------------------------------------------------------------
// 激活这个rt, 并从中中读取像素。
RenderTexture.active = rt;
Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
screenShot.ReadPixels(rect, 0, 0);// 注:这个时候,它是从RenderTexture.active中读取像素
screenShot.Apply();
// 重置相关参数,以使用camera继续在屏幕上显示
camera.targetTexture = null;
//ps: camera2.targetTexture = null;
RenderTexture.active = null; // JC: added to avoid errors
GameObject.Destroy(rt);
// 最后将这些纹理数据,成一个图片文件
return screenShot.EncodeToJPG();
}
//两个坐标之间的距离
public double Distance(Vector2d from, Vector2d to)
{
var pt1 = Turf.Point(new double[] { from.x, from.y });
var pt2 = Turf.Point(new double[] { to.x, to.y });
return Turf.Distance(pt1, pt2);
}
//根据距离计算下一个点坐标
public 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);
}
else
{
return new Vector2d(0, 0);
}
}
public MapDataModel GetMapData()
{
return mapData;
}
public List<VideoMapModel> getVideoPointList()
{
return videoPointList;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 693e7abaf474b6a498a2940d602e0d8e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,104 @@
using Assets.Scenes.Ride.Scripts;
using Assets.Scenes.Ride.Scripts.Model;
using System;
using UnityEngine;
namespace Assets.Scripts.Scenes.VideoRide
{
public class VideoPlayer : AbstractVideoPlayer
{
protected override void Start()
{
base.Start();
animator.Play("idle");
}
public void SetPower(double power)
{
this.power = power;
}
public void SetEndDistance(double distance)
{
this.totalDistance = distance;
}
public void Complete()
{
start = false;
manager.Save(totalDistance);
}
protected override void ComputePlayer()
{
heartRate = manager.UpDateHeart();
//power = manager.UpdatePower();
cadance = manager.UpdateCadence();
weight = App.CurrentUser.Weight;
bicycleWeight = App.CurrentUser.BicycleWeight;
//发送阻力
manager.TrackResistance(currentSlope);
if (power > 0)
{
preSpeed = speed;
speed = Helper.CalculateSpeed(elevation, currentSlope, power, weight, bicycleWeight);
distance = Math.Round(speed / 3600, 5, MidpointRounding.AwayFromZero);
totalDistance += distance;
currentlatLon = manager.Along(totalDistance);
}
else
{
speed = 0;
distance = 0;
}
}
//控制视频播放速度
protected override void ComputeVideo()
{
mapData = manager.GetMapData();
float ratio = 1;
if (currentIndex + 1 < mapData.List.Count)
{
ratio = (float)(speed / mapData.List[currentIndex + 1].Speed);
}
else
{
ratio = (float)(speed / mapData.List[currentIndex].Speed);
}
manager.Play(ratio);
if (totalDistance >= mapData.TotalDistance)
{
start = false;
manager.Pause();//暂停视频
}
}
protected override void ComputeRecord()
{
var mapData = manager.GetMapData();
Debug.Log($"ticks:{ticks}-{manager.GetCurrentFrame()}-endistance:{totalDistance}-totalDistance:{mapData.TotalDistance}-index:{currentIndex}-speed:{speed}-currentSlope:{currentSlope}-GetCurrentFrame:{manager.GetCurrentFrame()}-currentlatLon:{bearing}");
//记录骑行数据
var recorderData = manager.cyclingController.recorderData;
var targetData = new TargetData
{
Ticks = ticks,
_Power = power,
_Speed = speed,
_Distance = totalDistance > mapData.TotalDistance ? mapData.TotalDistance : totalDistance,
_Cadence = cadance,
_HeartRate = heartRate,
_Lat = currentlatLon.x,
_Lon = currentlatLon.y,
_TotalClimb = totalClimb,
};
var preDistance = totalDistance >= mapData.TotalDistance ? targetData._Distance : targetData._Distance - distance;
recorderData.PreDistance = Math.Round(preDistance, 6, MidpointRounding.AwayFromZero);
recorderData.EndDistance = Math.Round(targetData._Distance, 6, MidpointRounding.AwayFromZero);
recorderData.RiderDatas.Add(targetData);
if (totalDistance >= mapData.TotalDistance)
{
start = false;
manager.Save(totalDistance);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 21a384a3224d3b248b1d79d68a1e7578
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,79 @@
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace Assets.Scripts.Scenes.VideoRide
{
public class VideoUIManager : MonoBehaviour
{
GameObject button;
VideoGameManager manager;
VideoPlayer videoPlayer;
Text infoText { get; set; }
// Start is called before the first frame update
void Start()
{
UIManager.SetModalPanel(transform.Find("ModalPanel").GetComponent<PFUIPanel>());
manager = FindObjectOfType<VideoGameManager>();
videoPlayer = FindObjectOfType<VideoPlayer>();
button = transform.Find("Panel/Button").gameObject;
StringBuilder sb = new StringBuilder();
GameObject start = transform.Find("Panel/start").gameObject;
GameObject stop = transform.Find("Panel/stop").gameObject;
GameObject save = transform.Find("Panel/save").gameObject;
GameObject left = transform.Find("Panel/left").gameObject;
GameObject right = transform.Find("Panel/right").gameObject;
GameObject continueBtn = transform.Find("Panel/continue").gameObject;
UIManager.AddEvent(continueBtn, UnityEngine.EventSystems.EventTriggerType.PointerClick, async (s) =>
{
await manager.ContinueAsync();
});
infoText = transform.Find("InfoText").GetComponent<Text>();
UIManager.AddEvent(button, UnityEngine.EventSystems.EventTriggerType.PointerClick, (s) =>
{
UIManager.Show(UIManager.Instance.DevicePanel, null, true);
});
UIManager.AddEvent(start, UnityEngine.EventSystems.EventTriggerType.PointerClick, (s) =>
{
videoPlayer.SetPower(200);
var list = FindObjectsOfType<OnlineVideoPlayer>();
foreach (var item in list)
{
item.SetPlayer(100, 10);
}
manager.StartGame();
});
UIManager.AddEvent(stop, UnityEngine.EventSystems.EventTriggerType.PointerClick, (s) =>
{
sb.AppendLine($"{manager.GetCurrentFrame()}:{0}");
Debug.Log(sb.ToString());
videoPlayer.SetPower(0);
});
UIManager.AddEvent(save, UnityEngine.EventSystems.EventTriggerType.PointerClick, (s) =>
{
videoPlayer.Complete();
});
UIManager.AddEvent(left, UnityEngine.EventSystems.EventTriggerType.PointerClick, (s) =>
{
sb.AppendLine($"{manager.GetCurrentFrame()}:{-5}");
});
UIManager.AddEvent(right, UnityEngine.EventSystems.EventTriggerType.PointerClick, (s) =>
{
sb.AppendLine($"{manager.GetCurrentFrame()}:{5}");
});
}
// Update is called once per frame
void Update()
{
if (videoPlayer != null && manager != null)
{
infoText.text = $"帧数:{manager.GetCurrentFrame()}";
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: deea375efff5f3d46a95e5b7b7165151
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,61 @@
using Assets.Scenes.Ride.Scripts;
using Assets.Scenes.Ride.Scripts.Model;
using Assets.Scripts;
using Assets.Scripts.Apis.Models;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using UnityEngine.Video;
namespace Assets.Scripts.Scenes.VideoRide
{
public class testDownLoad : MonoBehaviour
{
UnityWebRequest request = null;
// Start is called before the first frame update
void Start()
{
//测试UI
var button = transform.GetComponent<Button>();
var text = transform.GetComponentInChildren<Text>();
var inputFiled = transform.parent.GetComponentInChildren<InputField>();
var player = FindObjectOfType<VideoPlayer>();
var testPlayer = FindObjectOfType<TestPlayerController>();
var url = @"http://192.168.0.97:6031/12067924_720p.mp4";
var currentPath = "";
inputFiled.onValueChanged.AddListener((s) =>
{
testPlayer.power = Convert.ToDouble(s);
});
button.onClick.AddListener(() =>
{
StartCoroutine(Utils.DownloadVideo("sdsd.mp4", url
, (p, req) =>
{
text.text = Math.Round(p * 100, 2).ToString() + "%";
request = req;
}
, (path) =>
{
text.text = "100%";
currentPath = path;
//player.url = path;
}
));
if (!string.IsNullOrEmpty(currentPath))
{
//player.url = currentPath;
}
});
}
// Update is called once per frame
void Update()
{
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1334799e672a05949b3e33f7abab3641
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: