AR多人骑行研究
This commit is contained in:
1 parent
448b6d7798
commit
16e416332d
49 files changed
+5956
-1167
No files matched your search
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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/";
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
Reference in new issue
Block a user