骑行界面调整,底层逻辑细化
@ -32,7 +32,7 @@
|
||||
_locationProvider.OnLocationUpdated -= LocationProvider_OnLocationUpdated;
|
||||
//_map.Initialize(location.LatitudeLongitude, _map.AbsoluteZoom);
|
||||
|
||||
var mainController = transform.parent.GetComponent<MainController>();
|
||||
var mainController = transform.parent.GetComponent<CyclingController>();
|
||||
if (mainController != null)
|
||||
{
|
||||
//初始化map
|
||||
|
||||
BIN
Assets/Plugins/NetCoreServer.dll
Normal file
33
Assets/Plugins/NetCoreServer.dll.meta
Normal file
@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80691a320791ff54ca89cd6cdaf7e0d2
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
205
Assets/Prefabs/VirtualPlayer.prefab
Normal file
@ -0,0 +1,205 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &1553891496
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 116094885906044059}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: cf37eca46d898384fa2d9e17dfa3e25e, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
character: {fileID: 116094885906044059}
|
||||
characterAnimator: {fileID: 116094885898626905}
|
||||
CurrentIndex: 0
|
||||
--- !u!1 &5773460712156952929
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4343934065607842291}
|
||||
- component: {fileID: 6299847091037955312}
|
||||
- component: {fileID: 6530994641530503712}
|
||||
- component: {fileID: 3304837852231199275}
|
||||
m_Layer: 9
|
||||
m_Name: Sphere
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &4343934065607842291
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5773460712156952929}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 8, y: 8, z: 8}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 116094885906139323}
|
||||
m_RootOrder: 4
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!33 &6299847091037955312
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5773460712156952929}
|
||||
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!23 &6530994641530503712
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5773460712156952929}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 03fcf11879198499f9e71b4e087af3c0, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!135 &3304837852231199275
|
||||
SphereCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5773460712156952929}
|
||||
m_Material: {fileID: 0}
|
||||
m_IsTrigger: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_Radius: 0.5
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!1001 &116094885906010681
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 100002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: VirtualPlayer
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 100002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_IsActive
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalScale.x
|
||||
value: 2
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalScale.y
|
||||
value: 2
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalScale.z
|
||||
value: 2
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 11
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 9500000, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
propertyPath: m_Controller
|
||||
value:
|
||||
objectReference: {fileID: 9100000, guid: 14e9d0801d59b004db16bd8b0057c8c9, type: 2}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 383b41aea1ea4ee43b23a95bb413ebd8, type: 3}
|
||||
--- !u!1 &116094885906044059 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 100002, guid: 383b41aea1ea4ee43b23a95bb413ebd8,
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 116094885906010681}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!4 &116094885906139323 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 400002, guid: 383b41aea1ea4ee43b23a95bb413ebd8,
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 116094885906010681}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!95 &116094885898626905 stripped
|
||||
Animator:
|
||||
m_CorrespondingSourceObject: {fileID: 9500000, guid: 383b41aea1ea4ee43b23a95bb413ebd8,
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 116094885906010681}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
7
Assets/Prefabs/VirtualPlayer.prefab.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f46190fc0ed09774fb2d01664232ea2a
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -19,7 +19,7 @@ RenderTexture:
|
||||
m_MipCount: -1
|
||||
m_DepthFormat: 2
|
||||
m_ColorFormat: 8
|
||||
m_MipMap: 0
|
||||
m_MipMap: 1
|
||||
m_GenerateMips: 1
|
||||
m_SRGB: 0
|
||||
m_UseDynamicScale: 1
|
||||
@ -27,11 +27,11 @@ RenderTexture:
|
||||
m_EnableCompatibleFormat: 1
|
||||
m_TextureSettings:
|
||||
serializedVersion: 2
|
||||
m_FilterMode: 1
|
||||
m_FilterMode: 0
|
||||
m_Aniso: 0
|
||||
m_MipBias: 0
|
||||
m_WrapU: 1
|
||||
m_WrapV: 1
|
||||
m_WrapW: 1
|
||||
m_WrapV: 2
|
||||
m_WrapW: 3
|
||||
m_Dimension: 2
|
||||
m_VolumeDepth: 1
|
||||
|
||||
@ -7,15 +7,18 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using XCharts;
|
||||
using UnityEngine.Networking;
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
|
||||
public class MainController : MonoBehaviour
|
||||
public class CyclingController : MonoBehaviour
|
||||
{
|
||||
private MapDataModel mapData;//当前路书数据
|
||||
private double[] coordiantes;//当前地图中心
|
||||
private int currentUserId;//当前选中的用户id
|
||||
private bool isStart;//当前游戏是否开始
|
||||
private string gameType;//当前骑行模式
|
||||
private DateTime startTime;//开始时间
|
||||
private bool initComplete;
|
||||
private CyclingModel cyclingModel;//当前骑行模式
|
||||
public int RouteId;
|
||||
|
||||
public MapDataModel GetMapData()
|
||||
{
|
||||
@ -29,28 +32,37 @@ public class MainController : MonoBehaviour
|
||||
// Start is called before the first frame update
|
||||
void Awake()
|
||||
{
|
||||
initComplete = false;
|
||||
cyclingModel = CyclingModel.Single;
|
||||
//获取当前用户信息 TODO
|
||||
|
||||
//获取路书信息
|
||||
//MapApi mapApi = new MapApi();
|
||||
//var result = mapApi.GetData(5942);
|
||||
|
||||
RouteId = 5942;
|
||||
var result = GetTestData();
|
||||
//StartCoroutine(requset());
|
||||
//获取UDP信息 TODO
|
||||
|
||||
//获取蓝牙设备信息 TODO
|
||||
|
||||
if (result != null && result.List.Count > 0)
|
||||
{
|
||||
mapData = result;
|
||||
coordiantes = result.List[0].Point;
|
||||
initComplete = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.Exception("fail to get route data");
|
||||
}
|
||||
|
||||
//TODO:
|
||||
//获取当前用户信息
|
||||
//获取当前udp信息
|
||||
//获取蓝牙设备信息
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
//发送UDP
|
||||
}
|
||||
|
||||
IEnumerator requset() {
|
||||
string url = @"http://192.168.0.97:5081/Map/GetData?routeid=5492&m=20";
|
||||
UnityWebRequest request = UnityWebRequest.Get(url);
|
||||
@ -95,5 +107,4 @@ public class MainController : MonoBehaviour
|
||||
}
|
||||
return dist.ToArray();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,23 +1,49 @@
|
||||
using System;
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class Helper
|
||||
{
|
||||
public static string GetDataDire(string dirName = "")
|
||||
public static string GetDataDire(string pathName)
|
||||
{
|
||||
|
||||
//var parentPath = System.IO.Directory.GetParent(Environment.CurrentDirectory).FullName;
|
||||
var parentPath = " ";//TODO
|
||||
var path = Path.Combine(parentPath, "PowerFunData", dirName);
|
||||
if (!System.IO.Directory.Exists(path))
|
||||
return @"D:\unityproject\Test\"+ pathName;
|
||||
}
|
||||
public static double AveragePower(IList<TargetData> list)
|
||||
{
|
||||
return Math.Floor(list.Where(p => p._Power > -1).Average(a => a._Power));
|
||||
}
|
||||
/// <summary>
|
||||
/// 优化功率
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
public static double GetNP(List<TargetData> list)
|
||||
{
|
||||
var _npinterval = new List<double>();
|
||||
var count = list.Count / 28;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
var list1 = list.Skip(i * 28).Take(28);
|
||||
double avgpower = Math.Pow((int)list1.Where(d => d._Power > -1).Average(a => a._Power), 4);
|
||||
_npinterval.Add(avgpower);
|
||||
}
|
||||
return path;
|
||||
double n = 0.25;
|
||||
if (_npinterval.Count == 0) return 0;
|
||||
return Math.Pow((_npinterval.Sum() / _npinterval.Count), n);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO:获取Ftp
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static int GetFtp()
|
||||
{
|
||||
return 200;
|
||||
}
|
||||
|
||||
public static string FormatTicks(int seconds)
|
||||
|
||||
8
Assets/Scenes/Ride/Scripts/Model.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdcb8176fafcd62448e8c70ed9d43074
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scenes/Ride/Scripts/Model/CyclingModels.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e8389fe2e69de14ba5b9b48f580dd81
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
108
Assets/Scenes/Ride/Scripts/Model/CyclingModels/BaseCycling.cs
Normal file
@ -0,0 +1,108 @@
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using GeoJSON.Net.Geometry;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model.CyclingModels
|
||||
{
|
||||
public abstract class BaseCycling
|
||||
{
|
||||
public CyclingModel Mode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否记录数据
|
||||
/// </summary>
|
||||
internal bool IsRecord { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 骑行数据记录器
|
||||
/// </summary>
|
||||
public RecorderDataModel recorderData { get; protected set; }
|
||||
|
||||
public List<BaseRider> riders { get; protected set; }
|
||||
/// <summary>
|
||||
/// 骑行的路线
|
||||
/// </summary>
|
||||
public Route route;
|
||||
/// <summary>
|
||||
/// 计时器
|
||||
/// </summary>
|
||||
public int Ticks = 0;
|
||||
/// <summary>
|
||||
/// 当前骑行的距离
|
||||
/// </summary>
|
||||
protected double currentDistance { get; set; }
|
||||
|
||||
public virtual bool CanPause => true;
|
||||
|
||||
protected TurfHelper _turfHelper;
|
||||
|
||||
protected double Zoom { get; private set; }
|
||||
protected string Bounds { get; private set; }
|
||||
|
||||
protected List<OutUser> realRiders;
|
||||
|
||||
protected GeographicPosition CenterPoint { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结束的时间
|
||||
/// </summary>
|
||||
protected DateTime? EndTime { get; set; }
|
||||
|
||||
public BaseCycling(Route route, CyclingModel cyclingModel)
|
||||
{
|
||||
this.route = route;
|
||||
this.Mode = cyclingModel;
|
||||
_turfHelper = new TurfHelper(route.JsonData.List.Select(d => d.Point));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 骑行函数(如果此方法不满足,可以在子类中重写此方法)
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
protected virtual void Run(TargetData targetData)
|
||||
{
|
||||
//将当前用户的位置发送到udf服务
|
||||
SendUserPositionToServer();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// =>发送用户的位置信息到服务端
|
||||
/// </summary>
|
||||
private void SendUserPositionToServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (recorderData.RiderDatas.Any())
|
||||
{
|
||||
var lastData = recorderData.RiderDatas.Last();
|
||||
var preDistance = recorderData.PreDistance;
|
||||
|
||||
var weightKg = Math.Round(lastData._Power / recorderData.CurrentUser.Weight, 2);
|
||||
MapUDPService.Send(route.RouteInstance.Id, recorderData.BelongUserId,
|
||||
new double[] { lastData._Lat, lastData._Lon },
|
||||
recorderData.IsCompleted, false, recorderData.EndDistance,
|
||||
true, 1, lastData._Speed, false, preDistance, weightKg, competitionId: recorderData.Competitionid, recorderData.Saved);
|
||||
}
|
||||
else if (recorderData.EndDistance > 0)//没有骑,但是有初始位置的情况
|
||||
{
|
||||
var point = _turfHelper.Along(recorderData.EndDistance);
|
||||
MapUDPService.Send(route.RouteInstance.Id, recorderData.BelongUserId, new double[] { point.Latitude, point.Longitude }, competitionId: recorderData.Competitionid);
|
||||
}
|
||||
else
|
||||
{
|
||||
MapUDPService.Send(route.RouteInstance.Id, recorderData.BelongUserId, route.Point.First().Reverse().ToArray(), competitionId: recorderData.Competitionid);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89d63056e2fd43e41b30635a0036ba33
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
106
Assets/Scenes/Ride/Scripts/Model/MapEnums.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 骑行模式
|
||||
/// </summary>
|
||||
public enum CyclingModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 单人模式
|
||||
/// </summary>
|
||||
Single = 0,
|
||||
/// <summary>
|
||||
/// 在线模式
|
||||
/// </summary>
|
||||
Online = 1,
|
||||
/// <summary>
|
||||
/// 多人历史数据回顾模式
|
||||
/// </summary>
|
||||
Review = 2,
|
||||
/// <summary>
|
||||
/// 比赛模式
|
||||
/// </summary>
|
||||
Competition = 3,
|
||||
/// <summary>
|
||||
/// 环球骑行
|
||||
/// </summary>
|
||||
GlobalCycling = 4
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 骑手类型
|
||||
/// </summary>
|
||||
public enum RiderType
|
||||
{
|
||||
//Real,//真实的人
|
||||
Online,//在线人
|
||||
Review,//回顾人(历史数据中的人)
|
||||
Virtual
|
||||
}
|
||||
/// <summary>
|
||||
/// 骑行状态(状态变更示意图:Paush=>Cycling=>Stop=>Cycling=>Stop)
|
||||
/// </summary>
|
||||
public enum CyclingStateEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 准备阶段
|
||||
/// </summary>
|
||||
Prepare,
|
||||
/// 骑行中
|
||||
/// </summary>
|
||||
Cycling,
|
||||
/// <summary>
|
||||
/// 暂停
|
||||
/// </summary>
|
||||
Stop
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送数据模式
|
||||
/// </summary>
|
||||
public enum SendDataMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 自由骑
|
||||
/// </summary>
|
||||
Freedom,
|
||||
/// <summary>
|
||||
/// 阻力模式
|
||||
/// </summary>
|
||||
Resistance,
|
||||
/// <summary>
|
||||
/// 轨道模式
|
||||
/// </summary>
|
||||
Track
|
||||
}
|
||||
/// <summary>
|
||||
/// 浏览器窗口
|
||||
/// </summary>
|
||||
public enum BrowserWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// 主页面窗口
|
||||
/// </summary>
|
||||
Main,
|
||||
/// <summary>
|
||||
/// 骑行页面窗口
|
||||
/// </summary>
|
||||
Cycling
|
||||
}
|
||||
|
||||
public enum CurrentPage
|
||||
{
|
||||
index,
|
||||
list,
|
||||
detial,
|
||||
review,
|
||||
competition,
|
||||
cycling
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/Model/MapEnums.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3d3dd3c4d6e2694eb9d94bc819a12f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
536
Assets/Scenes/Ride/Scripts/Model/OutModel.cs
Normal file
@ -0,0 +1,536 @@
|
||||
using GeoJSON.Net.Geometry;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 排名
|
||||
/// </summary>
|
||||
public class CompetitionRankingSortModel
|
||||
{
|
||||
public int Index { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Headimage { get; set; }
|
||||
|
||||
public double Near { get; set; }
|
||||
|
||||
public string KGWeight { get; set; }
|
||||
|
||||
public double Speed { get; set; }
|
||||
|
||||
public string CountryImg { get; set; }
|
||||
|
||||
public int UserId { get; set; }
|
||||
|
||||
public bool IsSelf { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 结果页模型
|
||||
/// </summary>
|
||||
public class CompetitionResultModel
|
||||
{
|
||||
public int Index { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
//public string Time { get; set; }
|
||||
|
||||
public double Power { get; set; }
|
||||
public double WeightKg { get; set; }
|
||||
public double Weight { get; set; }
|
||||
public double BicycleWeight { get; set; }
|
||||
|
||||
public double HeartRate { get; set; }
|
||||
|
||||
public string DeviceType { get; set; }
|
||||
|
||||
public string CreateTime { get; set; }
|
||||
/// <summary>
|
||||
/// 骑行时长
|
||||
/// </summary>
|
||||
public string TripTime { get; set; }
|
||||
|
||||
public string CompleteTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 与冲线时间的差距
|
||||
/// </summary>
|
||||
public string Gap { get; set; }
|
||||
}
|
||||
public class RankingDataModel
|
||||
{
|
||||
public int UserId { get; set; }
|
||||
|
||||
public TargetData data { get; set; }
|
||||
}
|
||||
|
||||
public class RankingSortData
|
||||
{
|
||||
public int Index { get; set; }
|
||||
public int UserId { get; set; }
|
||||
|
||||
public string WxHeadImg { get; set; }
|
||||
|
||||
public string NickName { get; set; }
|
||||
/// <summary>
|
||||
/// 注意这里TotalTime不是时间是距离,为了重用前端组件,没改名称
|
||||
/// </summary>
|
||||
public double TotalTime { get; set; }
|
||||
|
||||
public int Ticks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 其他人和我的距离(m)
|
||||
/// </summary>
|
||||
public double Near { get; set; }
|
||||
}
|
||||
public class CyclingFrameRankingModel
|
||||
{
|
||||
public List<RankingDataModel> data { get; set; }
|
||||
|
||||
public List<RankingSortData> sort { get; set; }
|
||||
|
||||
public int myranking { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 比赛的排名
|
||||
/// </summary>
|
||||
public class CompetitionRankingModel
|
||||
{
|
||||
public List<CompetitionRankingSortModel> Sorts { get; set; }
|
||||
|
||||
public int Total { get; set; }
|
||||
|
||||
public int MyRanking { get; set; }
|
||||
|
||||
public List<CompetitionResultModel> Results { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 骑行中 输出的数据模型
|
||||
/// </summary>
|
||||
public class OutModel
|
||||
{
|
||||
public double progress { get; set; }
|
||||
|
||||
public double? Elevation { get; set; }
|
||||
|
||||
public string Seconds { get; set; }
|
||||
|
||||
public int? EleIndex { get; set; }
|
||||
|
||||
//public long ExcuteTime { get; set; }
|
||||
|
||||
//public double? Bearing { get; set; }
|
||||
/// <summary>
|
||||
/// 坡度
|
||||
/// </summary>
|
||||
public double SlopeGrade { get; set; }
|
||||
|
||||
public TargetData targetData { get; set; }
|
||||
|
||||
public List<OutUser> baseRiders { get; set; }
|
||||
|
||||
public CyclingFrameRankingModel Ranking { get; set; }
|
||||
|
||||
public CompetitionRankingModel CompetitionRanking { get; set; }
|
||||
|
||||
public bool CanStart { get; set; } = true;
|
||||
/// <summary>
|
||||
/// 开始倒计时
|
||||
/// </summary>
|
||||
public int StartCountDown { get; set; }
|
||||
/// <summary>
|
||||
/// 结束倒计时
|
||||
/// </summary>
|
||||
public int EndCountDown { get; set; }
|
||||
/// <summary>
|
||||
/// 标识比赛的倒计时是关门时间
|
||||
/// </summary>
|
||||
public bool IsClosed { get; set; }
|
||||
///// <summary>
|
||||
///// 是否已保存
|
||||
///// </summary>
|
||||
//public bool Saved { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 比赛模式下,第一名的坐标
|
||||
/// </summary>
|
||||
public GeographicPosition FirstPoint { get; set; }
|
||||
|
||||
|
||||
public ChartSymbol ChartSymbol { get; set; }
|
||||
}
|
||||
|
||||
public class OutUser
|
||||
{
|
||||
public int UserId { get; set; }
|
||||
|
||||
public string InMapId { get; set; }
|
||||
|
||||
public double NextDistance { get; set; }
|
||||
|
||||
public double PreDistance { get; set; }
|
||||
|
||||
//public TargetData targetData { get; set; }//暂时不需要此字段
|
||||
public List<double[]> NextFrameArray { get; set; }
|
||||
//private List<object> _nextFrameArray { get; set; }
|
||||
//public List<object> NextFrameArray
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// if (_nextFrameArray != null)
|
||||
// {
|
||||
// return _nextFrameArray;
|
||||
// }
|
||||
// _nextFrameArray = (List<object>)CefBrowserPool.GetFrame(BrowserWindow.Main).EvaluateScriptAsync($"getFrameArray({PreDistance},{NextDistance})").ConfigureAwait(false).GetAwaiter().GetResult().Result;
|
||||
// return _nextFrameArray;
|
||||
// }
|
||||
//}
|
||||
|
||||
public string NickName { get; set; }
|
||||
public string WxHeadImg { get; set; }
|
||||
|
||||
public bool IsSelf
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.UserId == PubCommData.CurrentUser.Id;
|
||||
}
|
||||
}
|
||||
|
||||
public GeographicPosition Point { get; set; }
|
||||
|
||||
public double Bearing { get; set; }
|
||||
}
|
||||
|
||||
public class ChartSymbol
|
||||
{
|
||||
private double _grade = 0;
|
||||
private double _nextGrade = 0;
|
||||
public string GradeSymbol
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_grade > 0)
|
||||
{
|
||||
return "+";
|
||||
}
|
||||
if (_grade < 0)
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
public string GradeDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_grade < 0)
|
||||
{
|
||||
return (_grade * -1).ToString("0.#");
|
||||
}
|
||||
if (_grade > 0)
|
||||
{
|
||||
return _grade.ToString("0.#");
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
||||
public string NextGrade
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_nextGrade > 0)
|
||||
{
|
||||
return "+" + _nextGrade.ToString("0.#");
|
||||
}
|
||||
return _nextGrade.ToString("0.#");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 单位m
|
||||
/// </summary>
|
||||
public double Distance { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="grade"></param>
|
||||
/// <param name="nextGrade"></param>
|
||||
/// <param name="distance">单位m</param>
|
||||
public ChartSymbol(double grade, double nextGrade, double distance)
|
||||
{
|
||||
this._grade = grade;
|
||||
this._nextGrade = nextGrade;
|
||||
this.Distance = Math.Round(distance, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public class NearRiderModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Headimage { get; set; }
|
||||
|
||||
public double Near { get; set; }
|
||||
|
||||
public string KGWeight { get; set; }
|
||||
|
||||
public double Speed { get; set; }
|
||||
|
||||
public string CountryImg { get; set; }
|
||||
|
||||
public bool IsSelf { get; set; }
|
||||
}
|
||||
|
||||
public class MsgModel
|
||||
{
|
||||
public int RouteId { get; set; }
|
||||
|
||||
public int MemberId { get; set; }
|
||||
|
||||
public double[] Point { get; set; }
|
||||
|
||||
public bool exit { get; set; }
|
||||
|
||||
public double Speed { get; set; }
|
||||
|
||||
public bool IsCompleted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 需要展示的属性
|
||||
/// </summary>
|
||||
//public string Prop { get; set; }
|
||||
|
||||
public double EndDistance { get; set; }
|
||||
///// <summary>
|
||||
///// 是否展示在线的人
|
||||
///// </summary>
|
||||
//public bool ShowVirtual { get; set; }
|
||||
/// <summary>
|
||||
/// 命令类型,0命令,1消息
|
||||
/// </summary>
|
||||
public byte CommandType { get; set; }
|
||||
|
||||
//public bool IsVirtual { get; set; }
|
||||
/// <summary>
|
||||
/// 功率体重比
|
||||
/// </summary>
|
||||
public double WeightKg { get; set; }
|
||||
|
||||
public double PreDistance { get; set; }
|
||||
|
||||
public int Competitionid { get; set; }
|
||||
/// <summary>
|
||||
/// 客户端通过是否有用户保存了数据,来拉取相应的已经被保存的数据。(主要用在比赛)
|
||||
/// </summary>
|
||||
public bool Saved { get; set; }
|
||||
|
||||
public int V { get; set; }
|
||||
}
|
||||
|
||||
public class ReceiveMsgModel
|
||||
{
|
||||
public int RouteId { get; set; }
|
||||
|
||||
public int MemberId { get; set; }
|
||||
|
||||
public double[] Point { get; set; }
|
||||
|
||||
//public bool exit { get; set; }
|
||||
|
||||
public double Speed { get; set; }
|
||||
|
||||
public bool IsCompleted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 需要展示的属性
|
||||
/// </summary>
|
||||
//public string Prop { get; set; }
|
||||
|
||||
public double EndDistance { get; set; }
|
||||
/// <summary>
|
||||
/// 是否展示在线的人
|
||||
/// </summary>
|
||||
//public bool ShowVirtual { get; set; }
|
||||
/// <summary>
|
||||
/// 命令类型,0命令,1消息
|
||||
/// </summary>
|
||||
//public byte CommandType { get; set; }
|
||||
|
||||
//public bool IsVirtual { get; set; }
|
||||
|
||||
|
||||
public double PreDistance { get; set; }
|
||||
/// <summary>
|
||||
/// 功率体重比
|
||||
/// </summary>
|
||||
public double WeightKg { get; set; }
|
||||
public int Competitionid { get; set; }
|
||||
|
||||
public bool Saved { get; set; }
|
||||
|
||||
|
||||
public static ReceiveMsgModel Parse(string str)
|
||||
{
|
||||
var list = str.Split(',');
|
||||
if (list.Length != 10)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new ReceiveMsgModel
|
||||
{
|
||||
RouteId = Convert.ToInt32(list[0]),
|
||||
MemberId = Convert.ToInt32(list[1]),
|
||||
Point = new double[] { double.Parse(list[2].Split(':')[0]), double.Parse(list[2].Split(':')[1]) },
|
||||
IsCompleted = ToBoolean(list[3]),
|
||||
//exit = ToBoolean(list[4]),
|
||||
Speed = Convert.ToDouble(list[4]),
|
||||
PreDistance = Convert.ToDouble(list[5]),
|
||||
EndDistance = Convert.ToDouble(list[6]),
|
||||
WeightKg = Convert.ToDouble(list[7]),
|
||||
Competitionid = Convert.ToInt32(list[8]),
|
||||
Saved = ToBoolean(list[9])
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ToBoolean(string str)
|
||||
{
|
||||
return Convert.ToBoolean(int.Parse(str));
|
||||
}
|
||||
}
|
||||
|
||||
public class OnlineUser
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户Id
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
/// <summary>
|
||||
/// 在地图中的ID
|
||||
/// </summary>
|
||||
public string InMapId
|
||||
{
|
||||
get
|
||||
{
|
||||
//if (IsVirtual)
|
||||
//{
|
||||
// return "Online-Virtual-" + this.Id;
|
||||
//}
|
||||
return "Online-" + this.Id;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsVirtual { get; set; }
|
||||
/// <summary>
|
||||
/// 虚拟人物名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
public double Weight { get; set; }
|
||||
/// <summary>
|
||||
/// 头像地址
|
||||
/// </summary>
|
||||
public string HeadImage { get; set; }
|
||||
/// <summary>
|
||||
/// 路线Id
|
||||
/// </summary>
|
||||
public int RouteId { get; set; }
|
||||
/// <summary>
|
||||
/// FTP
|
||||
/// </summary>
|
||||
public int FTP { get; set; }
|
||||
/// <summary>
|
||||
/// 点位
|
||||
/// </summary>
|
||||
public double[] Point { get; set; }
|
||||
/// <summary>
|
||||
/// 需要展示的属性
|
||||
/// </summary>
|
||||
//public List<KeyPaire> Show { get; set; }
|
||||
/// <summary>
|
||||
/// 需要隐藏的属性
|
||||
/// </summary>
|
||||
public List<KeyPaire> Hide { get; set; }
|
||||
/// <summary>
|
||||
/// 是否骑行完毕
|
||||
/// </summary>
|
||||
public bool IsCompleted { get; set; }
|
||||
|
||||
public double PreDistance { get; set; }
|
||||
/// <summary>
|
||||
/// 最后距离
|
||||
/// </summary>
|
||||
public double EndDistance { get; set; }
|
||||
///// <summary>
|
||||
///// 是否退出
|
||||
///// </summary>
|
||||
//public bool exit { get; set; }
|
||||
/// <summary>
|
||||
/// 速度(km/h)
|
||||
/// </summary>
|
||||
public double Speed { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 圆形头像
|
||||
///// </summary>
|
||||
//public string CircHeadImg
|
||||
//{
|
||||
// get; set;
|
||||
//}
|
||||
|
||||
public bool IsSelf
|
||||
{
|
||||
get
|
||||
{
|
||||
return Id == PubCommData.CurrentUser.Id;
|
||||
}
|
||||
}
|
||||
|
||||
public double WeightKg { get; set; }
|
||||
|
||||
public int CompetitionId { get; set; }
|
||||
/// <summary>
|
||||
/// 已保存的
|
||||
/// </summary>
|
||||
public bool Saved { get; set; }
|
||||
|
||||
public DateTime LastActiveTime { get; set; }
|
||||
|
||||
public bool IsLost
|
||||
{
|
||||
get
|
||||
{
|
||||
return (DateTime.Now - LastActiveTime).TotalSeconds > 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class KeyPaire
|
||||
{
|
||||
public object Key { get; set; }
|
||||
|
||||
public object Value { get; set; }
|
||||
public KeyPaire(object key, object value)
|
||||
{
|
||||
this.Key = key;
|
||||
this.Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/Model/OutModel.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5741018b26c4d94dbd42daf26d87f3f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
216
Assets/Scenes/Ride/Scripts/Model/RecorderDataModel.cs
Normal file
@ -0,0 +1,216 @@
|
||||
using Assets.Scripts.Apis;
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model
|
||||
{
|
||||
public class RecorderDataModel
|
||||
{
|
||||
//private readonly MapWorkoutService service = new MapWorkoutService();
|
||||
|
||||
public t_user CurrentUser { get; set; }
|
||||
/// <summary>
|
||||
/// 所属人ID
|
||||
/// </summary>
|
||||
public int BelongUserId
|
||||
{
|
||||
get
|
||||
{
|
||||
return CurrentUser.Id;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 记录是否完毕
|
||||
/// </summary>
|
||||
public bool IsCompleted { get; set; }
|
||||
/// <summary>
|
||||
/// 是否需要计算排名
|
||||
/// </summary>
|
||||
public bool IsNeedRanking { get; set; }
|
||||
/// <summary>
|
||||
/// 骑行记录索引(用于中断骑行,继续骑行)
|
||||
/// </summary>
|
||||
public int ContinueIndex { get; set; }
|
||||
/// <summary>
|
||||
/// 骑行状态
|
||||
/// </summary>
|
||||
public CyclingStateEnum CyclingState { get; set; }
|
||||
/// <summary>
|
||||
/// 赛事Id
|
||||
/// </summary>
|
||||
public int Competitionid { get; set; }
|
||||
/// <summary>
|
||||
/// 当前已经骑行的距离(表示用户现在在的距离,并不是实际骑的距离)
|
||||
/// </summary>
|
||||
public double EndDistance { get; set; }
|
||||
/// <summary>
|
||||
/// 上次骑行的距离
|
||||
/// </summary>
|
||||
public double PreDistance { get; set; }
|
||||
/// <summary>
|
||||
/// 继续骑行记录标志
|
||||
/// </summary>
|
||||
public string ContinueMark { get; set; }
|
||||
/// <summary>
|
||||
/// 厂商Id
|
||||
/// </summary>
|
||||
public int ManufacturerId { get; set; }
|
||||
|
||||
public int? AntModelId { get; set; }
|
||||
/// <summary>
|
||||
/// 骑行数据
|
||||
/// </summary>
|
||||
public List<TargetData> RiderDatas = new List<TargetData>();
|
||||
/// <summary>
|
||||
/// 当前路线
|
||||
/// </summary>
|
||||
public Route CurrentRoute { get; set; }
|
||||
/// <summary>
|
||||
/// 骑行记录Id
|
||||
/// </summary>
|
||||
//public string RecordId { get; private set; }
|
||||
/// <summary>
|
||||
/// 设备号
|
||||
/// </summary>
|
||||
public string DeviceNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前给骑行台发送数据的模式
|
||||
/// </summary>
|
||||
public SendDataMode SendDataMode { get; set; }
|
||||
/// <summary>
|
||||
/// 临时使用的坡度
|
||||
/// </summary>
|
||||
public double SlopeGrade { get; set; }
|
||||
/// <summary>
|
||||
/// 临时使用的海拔
|
||||
/// </summary>
|
||||
public double Elevation { get; set; }
|
||||
/// <summary>
|
||||
/// 当前路书开始的距离
|
||||
/// </summary>
|
||||
public double CurrentRouteStartDistance { get; set; }
|
||||
|
||||
public DateTime StartTime { get; set; }
|
||||
/// <summary>
|
||||
/// 是否已经保存成功
|
||||
/// </summary>
|
||||
public bool Saved { get; set; }
|
||||
|
||||
public int GlobalCyclingId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 保存数据
|
||||
/// </summary>
|
||||
/// <param name="base64Image"></param>
|
||||
/// <returns></returns>
|
||||
public JsonResult<AddMapRecordResultModel> SaveData(CyclingModel cyclingModel, SelectParamModel selectParam, DateTime createTime, string base64Image = "")
|
||||
{
|
||||
if (RiderDatas.Count <= 0)
|
||||
{
|
||||
return new JsonResult<AddMapRecordResultModel> { result = true };
|
||||
}
|
||||
string newFileName = Guid.NewGuid().ToString();
|
||||
int FTP = Helper.GetFtp();
|
||||
double NP = Helper.GetNP(RiderDatas);
|
||||
//强度
|
||||
double IF = NP / FTP;
|
||||
//训练量
|
||||
double TSS = (RiderDatas.Count * NP * IF) / (FTP * 3600) * 100;
|
||||
var averagePower = Helper.AveragePower(RiderDatas);
|
||||
MapInterruptRecordApi service = new MapInterruptRecordApi();
|
||||
//AntManufacturer manufacturer = service.GetAntManufacturer(ManufacturerId);
|
||||
var recordId = Guid.NewGuid().ToString();
|
||||
var interruptRecord = new MapInterruptRecord
|
||||
{
|
||||
Id = recordId,
|
||||
RouteId = CurrentRoute.RouteInstance.Id,
|
||||
RouteName = CurrentRoute.RouteInstance.Name,
|
||||
TotalDistance = CurrentRoute.RouteInstance.Distance,
|
||||
UserId = BelongUserId,
|
||||
RecordFileName = newFileName + ".txt",
|
||||
Ftp = FTP,//FTP设置
|
||||
IF = Math.Round(IF, 2),
|
||||
Kj = RiderDatas.Sum(a => a._Power) / 1000,//消耗
|
||||
Tss = Math.Round(TSS, 2),
|
||||
EndDistance = EndDistance,
|
||||
IsCompleted = IsCompleted,
|
||||
|
||||
//TrainingTime = TimeHelper.FormatSeconds(RiderDatas.Last().Ticks),//训练时间
|
||||
NormalizedPower = Math.Floor(NP),//标准化功率
|
||||
AveragePower = averagePower,//平均功率
|
||||
MaxPower = RiderDatas.Max(a => a._Power),//最大功率
|
||||
WeightKg = Math.Round(averagePower / PubCommData.CurrentUser.Weight, 2),
|
||||
Weight = PubCommData.CurrentUser.Weight,
|
||||
BicycleWeight = PubCommData.CurrentUser.BicycleWeight,
|
||||
ContinueMark = ContinueMark,
|
||||
ContinueIndex = ContinueIndex,
|
||||
IsDelete = false,
|
||||
MapCompetitionId = Competitionid,
|
||||
ManufacturerName = "TODO",//manufacturer == null ? "" : manufacturer.Name,
|
||||
DeviceNumber = DeviceNumber,
|
||||
IsRanking = IsNeedRanking,
|
||||
CurrentRouteStartDistance = CurrentRouteStartDistance,
|
||||
ManufacturerId = ManufacturerId,
|
||||
AntModelId = AntModelId,
|
||||
StartTime = StartTime,
|
||||
CreateTime = createTime,
|
||||
Ticks = RiderDatas.Last().Ticks,
|
||||
Mode = cyclingModel.ToString(),
|
||||
Param = Newtonsoft.Json.JsonConvert.SerializeObject(selectParam),
|
||||
GlobalCyclingId = selectParam.GlobalCyclingId
|
||||
};
|
||||
//var range = new MapSpeedRange().GetSpeedRange(RiderDatas, CurrentRoute.RouteInstance.Distance);
|
||||
interruptRecord.SpeedRange = null; //JsonConvert.SerializeObject(range);
|
||||
|
||||
double process = Math.Round((EndDistance - interruptRecord.CurrentRouteStartDistance) / CurrentRoute.RouteInstance.Distance, 2);
|
||||
interruptRecord.Progress = process > 1 ? 1 : process;
|
||||
|
||||
var cadences = RiderDatas.Where(a => a._Cadence.HasValue && a._Cadence.Value > 0);
|
||||
if (cadences.Any())
|
||||
{
|
||||
interruptRecord.AverageCadence = Math.Round(cadences.Average(a => a._Cadence.GetValueOrDefault(0)));
|
||||
}
|
||||
interruptRecord.MaxCadence = Math.Round(RiderDatas.Max(a => a._Cadence.GetValueOrDefault(0)));
|
||||
interruptRecord.AverageHeartRate = Math.Round(RiderDatas.Average(a => a._HeartRate.GetValueOrDefault(0)));
|
||||
interruptRecord.MaxHeartRate = RiderDatas.Max(a => a._HeartRate.GetValueOrDefault(0));
|
||||
//service.CreateRecordCyclingData(interruptRecord);
|
||||
var path = Helper.GetDataDire("MapWorkoutRecords");
|
||||
var fname = path + "/" + newFileName + ".txt";
|
||||
var files = new List<string>();
|
||||
using (var fs = new FileInfo(fname).OpenWrite())
|
||||
{
|
||||
var stream = new StreamWriter(fs);
|
||||
stream.BaseStream.Seek(0, SeekOrigin.End);
|
||||
foreach (var item in RiderDatas)
|
||||
{
|
||||
stream.Write(item.Write() + "\r\n");
|
||||
}
|
||||
stream.Flush();
|
||||
stream.Close();
|
||||
files.Add(fname);
|
||||
}
|
||||
//TODO 截图
|
||||
if (!string.IsNullOrEmpty(base64Image))
|
||||
{
|
||||
//var imageName = path + "/" + Guid.NewGuid().ToString() + ".png";
|
||||
//base64Image = base64Image.Replace("data:image/png;base64,", "").Replace("data:image/jgp;base64,", "").Replace("data:image/jpg;base64,", "").Replace("data:image/jpeg;base64,", ""); ;
|
||||
//byte[] image = Convert.FromBase64String(base64Image);
|
||||
//using (MemoryStream ms = new MemoryStream(image))
|
||||
//using (Image img = Image.FromStream(ms))
|
||||
//{
|
||||
// img.Save(imageName, System.Drawing.Imaging.ImageFormat.Png);
|
||||
// //img.Dispose();
|
||||
//}
|
||||
//files.Add(imageName);
|
||||
}
|
||||
var result = service.Add(interruptRecord, files);
|
||||
return new JsonResult<AddMapRecordResultModel> { result = result.result, errMsg = result.errMsg, data = result.data };
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/Model/RecorderDataModel.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11c5f863a5d0baa49b7b374090197f99
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scenes/Ride/Scripts/Model/RiderModels.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb74a9f48e6075b4098a071b7c41755b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
60
Assets/Scenes/Ride/Scripts/Model/RiderModels/BaseRider.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model
|
||||
{
|
||||
public abstract class BaseRider
|
||||
{
|
||||
//internal static MapWorkoutService service = new MapWorkoutService();
|
||||
|
||||
public abstract RiderType riderType { get; }
|
||||
/// <summary>
|
||||
/// 用户Id
|
||||
/// </summary>
|
||||
public int UserId { get; set; }
|
||||
|
||||
public string InMapId
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.riderType.ToString() + "-" + UserId;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 用户姓名
|
||||
/// </summary>
|
||||
public string NickName { get; set; }
|
||||
/// <summary>
|
||||
/// 微信头像
|
||||
/// </summary>
|
||||
public string WxHeadImg { get; set; }
|
||||
/// <summary>
|
||||
/// 最后骑行的距离
|
||||
/// </summary>
|
||||
public double EndDistance { get; set; }
|
||||
/// <summary>
|
||||
/// 是否是当前登陆人
|
||||
/// </summary>
|
||||
public bool IsSelf
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.UserId == PubCommData.CurrentUser.Id;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 圆形头像
|
||||
/// </summary>
|
||||
public string CircHeadImg
|
||||
{
|
||||
get
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a318f90ef1c36742a0ffa27baa04c98
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,60 @@
|
||||
using GeoJSON.Net.Geometry;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model.RiderModels
|
||||
{
|
||||
public class OnlineRiderModel : BaseRider
|
||||
{
|
||||
public override RiderType riderType => RiderType.Online;
|
||||
|
||||
public double PreDistance { get; set; } = 0;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public GeographicPosition Point { get; set; }
|
||||
|
||||
public OutUser GetOutUser(double preDistance, double currentDistance, TurfHelper turfHelper, CyclingStateEnum cyclingState)
|
||||
{
|
||||
if (this.IsSelf)
|
||||
{
|
||||
var newRealUser = new OutUser()
|
||||
{
|
||||
NickName = this.NickName,
|
||||
WxHeadImg = this.WxHeadImg,
|
||||
UserId = this.UserId,
|
||||
//targetData = targetData,
|
||||
InMapId = this.InMapId,
|
||||
PreDistance = preDistance,
|
||||
NextDistance = currentDistance,
|
||||
Point = turfHelper.Along(currentDistance),
|
||||
};
|
||||
if (cyclingState != CyclingStateEnum.Cycling)
|
||||
{
|
||||
newRealUser.NextDistance = preDistance;
|
||||
}
|
||||
return newRealUser;
|
||||
}
|
||||
else
|
||||
{
|
||||
var newRealUser = new OutUser()
|
||||
{
|
||||
NickName = this.NickName,
|
||||
WxHeadImg = this.WxHeadImg,
|
||||
UserId = this.UserId,
|
||||
//targetData = targetData,
|
||||
InMapId = this.InMapId,
|
||||
PreDistance = this.PreDistance,
|
||||
NextDistance = this.EndDistance,
|
||||
Point = this.Point, //turfHelper.Along(this.EndDistance)
|
||||
};
|
||||
return newRealUser;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83879fd24afab69418f97cb56eaebda7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,55 @@
|
||||
using GeoJSON.Net.Geometry;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model.RiderModels
|
||||
{
|
||||
/// <summary>
|
||||
/// 骑行伴侣
|
||||
/// </summary>
|
||||
public class ReviewRiderModel : BaseRider
|
||||
{
|
||||
public override RiderType riderType => RiderType.Review;
|
||||
|
||||
public GeographicPosition Point { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 骑行记录数据
|
||||
/// </summary>
|
||||
public string[] record { get; set; }
|
||||
|
||||
public OutUser GetOutUser(int ticks, TurfHelper turfHelper)
|
||||
{
|
||||
var reviewer = this;
|
||||
TargetData revierData = null;
|
||||
if (ticks >= reviewer.record.Length)
|
||||
{
|
||||
revierData = TargetData.Read(reviewer.record[reviewer.record.Length - 1]);
|
||||
}
|
||||
else if (ticks > 0)
|
||||
{
|
||||
revierData = TargetData.Read(reviewer.record[ticks - 1]);
|
||||
}
|
||||
//(Ticks >= reviewer.record.Length ? TargetData.Read(reviewer.record[reviewer.record.Length - 1]) :
|
||||
//TargetData.Read(reviewer.record[Ticks]));
|
||||
var reivewPreDistance = ticks == 1 || ticks == 0 ? 0 :
|
||||
(ticks >= reviewer.record.Length ? TargetData.Read(reviewer.record[reviewer.record.Length - 1])._Distance :
|
||||
TargetData.Read(reviewer.record[ticks - 2])._Distance);
|
||||
var result = new OutUser()
|
||||
{
|
||||
UserId = this.UserId,
|
||||
//targetData = revierData,
|
||||
InMapId = this.InMapId,
|
||||
PreDistance = reivewPreDistance,
|
||||
NextDistance = ticks == 0 ? 0 : revierData._Distance,
|
||||
NickName = this.NickName,
|
||||
WxHeadImg = this.WxHeadImg
|
||||
};
|
||||
result.Point = turfHelper.Along(result.NextDistance);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d265479686613e418a745e888533ec5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
369
Assets/Scenes/Ride/Scripts/Model/Route.cs
Normal file
@ -0,0 +1,369 @@
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model
|
||||
{
|
||||
public class Route
|
||||
{
|
||||
/// <summary>
|
||||
/// 路线实例
|
||||
/// </summary>
|
||||
public MapRoute RouteInstance { get; private set; }
|
||||
/// <summary>
|
||||
/// 从服务端获取的Json数据
|
||||
/// </summary>
|
||||
public MapDataModel JsonData { get; set; }
|
||||
/// <summary>
|
||||
/// 当前路书的排行榜信息
|
||||
/// </summary>
|
||||
public List<MapRecordRanking> RecordRankings { get; set; }
|
||||
|
||||
private List<double[]> _Point = null;
|
||||
/// <summary>
|
||||
/// 点位信息
|
||||
/// </summary>
|
||||
public List<double[]> Point
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Point == null)
|
||||
{
|
||||
_Point = JsonData.List.Select(n => n.Point.Reverse().ToArray()).ToList();
|
||||
}
|
||||
return _Point;
|
||||
}
|
||||
}
|
||||
private List<double> _Elevation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 海拔信息
|
||||
/// </summary>
|
||||
public List<double> Elevation
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Elevation == null)
|
||||
{
|
||||
_Elevation = JsonData.List.Select(n => n.Elevation).ToList();
|
||||
}
|
||||
return _Elevation;
|
||||
}
|
||||
}
|
||||
|
||||
private List<double> _SlopeGrade { get; set; }
|
||||
/// <summary>
|
||||
/// 坡度信息
|
||||
/// </summary>
|
||||
public List<double> SlopeGrade
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_SlopeGrade == null)
|
||||
{
|
||||
//_SlopeGrade = CalPatch();
|
||||
_SlopeGrade = JsonData.List.Select(d => d.Grade).ToList();
|
||||
}
|
||||
return _SlopeGrade;
|
||||
}
|
||||
}
|
||||
private List<double> _StepDistance { get; set; }
|
||||
/// <summary>
|
||||
/// 每两点的距离
|
||||
/// </summary>
|
||||
public List<double> StepDistance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_StepDistance == null)
|
||||
{
|
||||
_StepDistance = JsonData.List.Select(n => n.Distance).ToList();
|
||||
}
|
||||
return _StepDistance;
|
||||
}
|
||||
}
|
||||
|
||||
public double? _TotalDistance { get; set; }
|
||||
|
||||
public double TotalDistance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_TotalDistance == null)
|
||||
{
|
||||
_TotalDistance = GetTotalDistance();
|
||||
}
|
||||
return (double)_TotalDistance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 每一小步到起点的距离
|
||||
/// </summary>
|
||||
private List<double> _StepToStartDistance;
|
||||
|
||||
public List<double> StepToStartDistance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_StepToStartDistance == null)
|
||||
{
|
||||
_StepToStartDistance = GetStepToStartDistance();
|
||||
}
|
||||
return _StepToStartDistance;
|
||||
}
|
||||
}
|
||||
|
||||
public Route(MapDataModel data)
|
||||
{
|
||||
JsonData = data;
|
||||
}
|
||||
|
||||
public Route(MapDataModel data, MapRoute mapRoute)
|
||||
{
|
||||
RouteInstance = mapRoute;
|
||||
JsonData = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// km
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public double GetTotalDistance()
|
||||
{
|
||||
var total = 0d;
|
||||
for (int i = 0; i < JsonData.List.Count - 1; i++)
|
||||
{
|
||||
var current = JsonData.List[i];
|
||||
var next = JsonData.List[i + 1];
|
||||
total += TurfHelper.GetDistances(new double[] { current.Point[1], current.Point[0] }, new double[] { next.Point[1], next.Point[0] });
|
||||
}
|
||||
return total / 1000;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据下标获取海拔
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public double GetElevationByIndex(int index)
|
||||
{
|
||||
if (index > this.Elevation.Count)
|
||||
{
|
||||
return this.Elevation.Last();
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.Elevation[index];
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据下标获取距离的小段
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public double GetDistanceStepByIndex(int index)
|
||||
{
|
||||
if (index > this.StepDistance.Count)
|
||||
{
|
||||
return this.StepDistance.Last();
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.StepDistance[index];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据索引获取坡度
|
||||
/// </summary>
|
||||
/// <param name="index">索引</param>
|
||||
/// <param name="average">是否需要平均坡度</param>
|
||||
/// <returns></returns>
|
||||
public double GetPatchByIndex(int index, bool average, double endDistance = 0, double cacheDistance = 5)
|
||||
{
|
||||
double slop = 0;
|
||||
if (average)
|
||||
{
|
||||
//每一小段的距离
|
||||
double step = GetDistanceStepByIndex(index);
|
||||
//每一段到起点的距离
|
||||
double stepToStart = GetStepToStartDistanceByIndex(index);
|
||||
//当前骑行距离与前一段的绝对值之差
|
||||
double absoluteValue = step - (stepToStart - endDistance);
|
||||
//绝对值之差是否大于多少米,如果大于则返回原始坡度,如果小于则返回平均坡度
|
||||
if (absoluteValue < cacheDistance && cacheDistance < step)
|
||||
{
|
||||
if (index >= this.SlopeGrade.Count - 1)
|
||||
{
|
||||
double slope = this.SlopeGrade.Last();
|
||||
//if (slope > 10)
|
||||
//{
|
||||
// slop = 10;
|
||||
//}
|
||||
//else if (slope < -10)
|
||||
//{
|
||||
// slop = -10;
|
||||
//}
|
||||
//else
|
||||
{
|
||||
slop = slope / 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double slope = this.SlopeGrade[index];
|
||||
//if (slope > 10)
|
||||
//{
|
||||
// slop = 10;
|
||||
//}
|
||||
//else if (slope < -10)
|
||||
//{
|
||||
// slop = -10;
|
||||
//}
|
||||
//else
|
||||
{
|
||||
slop = slope / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index >= this.SlopeGrade.Count - 1)
|
||||
{
|
||||
slop = this.SlopeGrade.Last();
|
||||
}
|
||||
else
|
||||
{
|
||||
slop = this.SlopeGrade[index];
|
||||
}
|
||||
}
|
||||
//if (slop > 10)
|
||||
//{
|
||||
// return 10;
|
||||
//}
|
||||
//if (slop < -10)
|
||||
//{
|
||||
// return -10;
|
||||
//}
|
||||
return slop;
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据距离获取点位下标
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int GetStepIndex(double distance)
|
||||
{
|
||||
distance *= 1000;//将距离转化为米
|
||||
var totalDistance = 0D;
|
||||
var index = 0;
|
||||
foreach (var item in this.StepDistance)
|
||||
{
|
||||
totalDistance += item;
|
||||
if (totalDistance > distance)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (distance > this.StepDistance[this.StepDistance.Count - 1])
|
||||
{
|
||||
return this.StepDistance.Count - 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通过索引获取当前到起点的距离(单位m)
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public double GetStepToStartDistanceByIndex(int index)
|
||||
{
|
||||
if (index >= this.StepToStartDistance.Count - 1)
|
||||
{
|
||||
return this.StepToStartDistance.Last();
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.StepToStartDistance[index];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算每一段路程的斜率
|
||||
/// </summary>
|
||||
private List<double> CalPatch()
|
||||
{
|
||||
if (this.Elevation != null)
|
||||
{
|
||||
List<double> grade = new List<double>();
|
||||
for (int i = 0; i < this.Point.Count - 1; i++)
|
||||
{
|
||||
var a = this.Elevation[i + 1] - this.Elevation[i];
|
||||
if (a == 0)
|
||||
{
|
||||
grade.Add(0);
|
||||
continue;
|
||||
}
|
||||
//勾股定理
|
||||
var c = this.StepDistance[i];//如果车停了下来,c为0
|
||||
if (c == 0 && i > 0)
|
||||
{
|
||||
grade.Add(grade[grade.Count - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
var b = Math.Sqrt(c * c - a * a);
|
||||
if (b == 0)//如果b等于,这就是垂直的墙壁
|
||||
{
|
||||
grade.Add(grade[grade.Count - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
grade.Add(a / b * 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
//检是否有NaN的值
|
||||
for (int i = 0; i < grade.Count; i++)
|
||||
{
|
||||
if (double.IsNaN(grade[i]) && i != 0)
|
||||
{
|
||||
grade[i] = grade[i - 1];
|
||||
}
|
||||
else if (double.IsNaN(grade[i]) && i == 0)
|
||||
{
|
||||
grade[i] = 0;
|
||||
}
|
||||
}
|
||||
return grade;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取每一段到起点的距离
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private List<double> GetStepToStartDistance()
|
||||
{
|
||||
if (StepDistance != null)
|
||||
{
|
||||
List<double> stepToStartDis = new List<double>();
|
||||
double start = 0;
|
||||
for (int i = 0; i < StepDistance.Count; i++)
|
||||
{
|
||||
start += StepDistance[i];
|
||||
stepToStartDis.Add(start);
|
||||
}
|
||||
return stepToStartDis;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/Model/Route.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b4a6fa5405752242a577299e27df510
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
47
Assets/Scenes/Ride/Scripts/Model/SelectParamModel.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model
|
||||
{
|
||||
public class SelectParamModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 在线用户ID,跟骑选的用户
|
||||
/// </summary>
|
||||
public int OnlineUserId { get; set; }
|
||||
/// <summary>
|
||||
/// 继续骑行的标志
|
||||
/// </summary>
|
||||
public string ContinueMark { get; set; }
|
||||
/// <summary>
|
||||
/// 当前第几次骑行
|
||||
/// </summary>
|
||||
public int? ContinueIndex { get; set; }
|
||||
/// <summary>
|
||||
/// 路线Id
|
||||
/// </summary>
|
||||
public int RouteId { get; set; }
|
||||
/// <summary>
|
||||
/// 赛事Id
|
||||
/// </summary>
|
||||
public int CompetitionId { get; set; }
|
||||
/// <summary>
|
||||
/// 最后一次骑行的距离
|
||||
/// </summary>
|
||||
public double EndDistance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排名信息Id,用于骑行回顾,多人
|
||||
/// </summary>
|
||||
public List<string> RankingsId { get; set; }
|
||||
///// <summary>
|
||||
///// 是否为全球骑行的继续骑行
|
||||
///// </summary>
|
||||
//public bool GlobalContinue { get; set; }
|
||||
|
||||
public int GlobalCyclingId { get; set; }
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/Model/SelectParamModel.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fab2eae6e723baa46ad8c972556f38c6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
72
Assets/Scenes/Ride/Scripts/Model/TargetData.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 指标数据
|
||||
/// </summary>
|
||||
public class TargetData
|
||||
{
|
||||
public double _Power = 0d;
|
||||
public double _Speed = 0;
|
||||
/// <summary>
|
||||
/// km
|
||||
/// </summary>
|
||||
public double _Distance { get; set; } = 0D;
|
||||
public double? _Cadence = 0;
|
||||
public int? _HeartRate = 0;
|
||||
public int Ticks = 0;
|
||||
/// <summary>
|
||||
/// 纬度
|
||||
/// </summary>
|
||||
public double _Lat { get; set; } = 0d;
|
||||
/// <summary>
|
||||
/// 经度
|
||||
/// </summary>
|
||||
public double _Lon { get; set; } = 0d;
|
||||
|
||||
//public double _Bearing = 0d;
|
||||
|
||||
public TargetData Clone()
|
||||
{
|
||||
return (TargetData)MemberwiseClone();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format($"Ticks:{Ticks} Power:{_Power} Speed:{_Speed} Distance:{_Distance} Cadence:{_Cadence} HeartRate:{_HeartRate} Lat:{_Lat} Lon:{_Lon}");
|
||||
}
|
||||
|
||||
public string Write()
|
||||
{
|
||||
return string.Format($"{ Ticks },{ _Power.ToString(CultureInfo.InvariantCulture) },{ _Speed.ToString(CultureInfo.InvariantCulture) },{ Math.Round(_Distance, 6).ToString(CultureInfo.InvariantCulture) },{ (_Cadence == null ? "" : _Cadence.Value.ToString(CultureInfo.InvariantCulture)) },{ (_HeartRate == null ? "null" : _HeartRate.Value.ToString(CultureInfo.InvariantCulture)) },{ Math.Round(_Lat, 6).ToString(CultureInfo.InvariantCulture) },{ Math.Round(_Lon, 6).ToString(CultureInfo.InvariantCulture) }");//,{_Bearing}
|
||||
}
|
||||
|
||||
public static TargetData Read(string data)
|
||||
{
|
||||
string[] split = data.Split(',');
|
||||
var target = new TargetData();
|
||||
target.Ticks = int.Parse(split[0]);
|
||||
target._Power = double.Parse(split[1]);
|
||||
target._Speed = double.Parse(split[2]);
|
||||
target._Distance = double.Parse(split[3]);
|
||||
target._Cadence = double.Parse(split[4]);
|
||||
if (!string.IsNullOrWhiteSpace(split[5]) && split[5] != "null")
|
||||
{
|
||||
target._HeartRate = int.Parse(split[5]);
|
||||
}
|
||||
if (split.Length > 6)
|
||||
{
|
||||
target._Lat = double.Parse(split[6]);
|
||||
target._Lon = double.Parse(split[7]);
|
||||
//target._Bearing = double.Parse(split[8]);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/Model/TargetData.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79850d6cccee69445927e491750a500b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
56
Assets/Scenes/Ride/Scripts/Model/t_user.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model
|
||||
{
|
||||
public class t_user
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Nickname { get; set; }
|
||||
/// <summary>
|
||||
/// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
|
||||
/// </summary>
|
||||
public int Sex { get; set; }
|
||||
public int Unit { get; set; }
|
||||
public double Weight { get; set; }
|
||||
public int FTP { get; set; }
|
||||
public int WheelDiameter { get; set; }
|
||||
public string Phone { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Pass { get; set; }
|
||||
public string OtherPlatforms { get; set; }
|
||||
public string Country { get; set; }
|
||||
public string Province { get; set; }
|
||||
public string City { get; set; }
|
||||
public string Area { get; set; }
|
||||
public string WxHeadImg { get; set; }
|
||||
public DateTime LastLoginTime { get; set; }
|
||||
/// <summary>
|
||||
/// 自动暂停
|
||||
/// </summary>
|
||||
public bool AutoPause { get; set; }
|
||||
/// <summary>
|
||||
/// 最大心率
|
||||
/// </summary>
|
||||
public int MaxHeartRate { get; set; }
|
||||
|
||||
public bool CanEditRoom { get; set; }
|
||||
/// <summary>
|
||||
/// 自行车重
|
||||
/// </summary>
|
||||
public double BicycleWeight { get; set; }
|
||||
|
||||
public string Contact { get; set; }
|
||||
|
||||
public string ContactPhone { get; set; }
|
||||
|
||||
public string ContactAddress { get; set; }
|
||||
/// <summary>
|
||||
/// 阻力灵敏度
|
||||
/// </summary>
|
||||
public int Sensitivity { get; set; }
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/Model/t_user.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d977fd7941debf4b90f950a8fd3c0a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scenes/Ride/Scripts/Network.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0b6448d57a2ab249a67f66c160c8293
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
18
Assets/Scenes/Ride/Scripts/Network/IService.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Network
|
||||
{
|
||||
interface IService
|
||||
{
|
||||
void Start(Action<List<ReceiveMsgModel>> action);
|
||||
|
||||
void Send(byte[] dgram, int bytes);
|
||||
|
||||
void Close();
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/Network/IService.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04b976b21b69ff640956ca0574491797
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
367
Assets/Scenes/Ride/Scripts/Network/MapUDPService.cs
Normal file
@ -0,0 +1,367 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using Assets.Scenes.Ride.Scripts.Network;
|
||||
using Assets.Scripts;
|
||||
using Assets.Scripts.Apis;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class MapUDPService
|
||||
{
|
||||
private static IService _udpService;
|
||||
//private static UdpClient udpClient;
|
||||
//private static IPEndPoint iPEndPoint;
|
||||
private static bool isExit = false;
|
||||
//private static Task task = null;
|
||||
//private static CancellationTokenSource cts { get; set; }
|
||||
private static CancellationToken ct { get; set; }
|
||||
//private static List<OnlineUser> onlineUsers { get; set; } = new List<OnlineUser>();
|
||||
private static System.Timers.Timer heartbeat { get; set; }
|
||||
public static bool Pause { get; set; } = false;
|
||||
|
||||
private static OnlineUserHelper _onlineUserHelper;
|
||||
private static OnlineUserHelper onlineUserHelper
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_onlineUserHelper == null)
|
||||
{
|
||||
_onlineUserHelper = new OnlineUserHelper();
|
||||
}
|
||||
return _onlineUserHelper;
|
||||
}
|
||||
}
|
||||
private static DateTime LastActiveTime = DateTime.Now;
|
||||
private static List<ReceiveMsgModel> msgs = new List<ReceiveMsgModel>();
|
||||
/// <summary>
|
||||
/// 初始化(如果UDP服务未启动,则会已没5秒一次不断尝试,直到连接上为止,前端不需要考虑任何UDP连接的事情)
|
||||
/// </summary>
|
||||
public static void Init()
|
||||
{
|
||||
try
|
||||
{
|
||||
//var ddd = new MapWorkoutService().GetRealOnlineUserInfo(new List<int> { 6 });
|
||||
isExit = false;
|
||||
Pause = false;
|
||||
|
||||
if (_udpService == null)
|
||||
{
|
||||
_udpService = new TcpService1();
|
||||
|
||||
_udpService.Start(list =>
|
||||
{
|
||||
LastActiveTime = DateTime.Now;
|
||||
//onlineUserHelper.RemoveExceptionData(list);
|
||||
msgs = list;
|
||||
onlineUserHelper.SetOnlineUser(msgs);
|
||||
});
|
||||
|
||||
heartbeat = new System.Timers.Timer();
|
||||
heartbeat.Interval = 1000;
|
||||
heartbeat.AutoReset = true;
|
||||
heartbeat.Enabled = true;
|
||||
heartbeat.Elapsed += Heartbeat_Elapsed;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Trace.WriteLine("UDP:" + e.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//发送一条心跳包
|
||||
//SendHeartbeat();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Heartbeat_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
//超过一秒没有收到消息
|
||||
if ((now - LastActiveTime).TotalSeconds > 1)
|
||||
{
|
||||
onlineUserHelper.SetOnlineUser(new List<ReceiveMsgModel>());
|
||||
}
|
||||
if (now.Second % 20 == 0)
|
||||
{
|
||||
//LastActiveTime = now;
|
||||
SendHeartbeat();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 发送心跳包
|
||||
/// </summary>
|
||||
private static void SendHeartbeat()
|
||||
{
|
||||
Send(0, PubCommData.CurrentUser.Id, new double[] { 0, 0 }, false, false, 0, true, 0);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 发送数据
|
||||
/// </summary>
|
||||
/// <param name="RouteId">路书Id</param>
|
||||
/// <param name="MemberId">用户id</param>
|
||||
/// <param name="Point">当前点位</param>
|
||||
/// <param name="prop">属性</param>
|
||||
/// <param name="IsCompleted">是否完成</param>
|
||||
/// <param name="exit">是否退出</param>
|
||||
public static void Send(int RouteId, int MemberId, double[] Point, bool IsCompleted = false, bool exit = false,
|
||||
double endDistance = 0, bool showVirtual = false, byte commandType = 1, double speed = 0, bool isVirtual = false, double preDistance = 0,
|
||||
double weightKg = 0, int competitionId = 0, bool saved = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
var model = new MsgModel
|
||||
{
|
||||
RouteId = RouteId,
|
||||
MemberId = MemberId,
|
||||
Point = Point,
|
||||
IsCompleted = IsCompleted,
|
||||
exit = exit,
|
||||
EndDistance = endDistance,
|
||||
//ShowVirtual = showVirtual,
|
||||
CommandType = commandType,
|
||||
Speed = speed,
|
||||
//IsVirtual = isVirtual,
|
||||
PreDistance = preDistance,
|
||||
WeightKg = weightKg,
|
||||
Competitionid = competitionId,
|
||||
Saved = saved,
|
||||
V = 1
|
||||
};
|
||||
var sendBytes = Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(model));
|
||||
_udpService.Send(sendBytes, sendBytes.Length);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("发送失败:" + e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
isExit = true;
|
||||
if (MapUDPService._udpService == null) return;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Send(0, PubCommData.CurrentUser.Id, new double[] { 1, 1 }, true, isExit);
|
||||
}
|
||||
_udpService.Close();
|
||||
|
||||
//task.Dispose();
|
||||
_udpService = null;
|
||||
_onlineUserHelper = null;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
//停止计时
|
||||
if (heartbeat != null)
|
||||
{
|
||||
heartbeat.Stop();
|
||||
heartbeat.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static OnlineUser GetOnlineUserLastDataById(int userId)
|
||||
{
|
||||
//return _onlineUserHelper.GetOnlineUserLastDataById(userId);
|
||||
//var msg = msgs.Where(m => m.MemberId == userId);
|
||||
//if (msg == null) return null;
|
||||
return onlineUserHelper.OnlineUsers.FirstOrDefault(u => u.Id == userId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据路书获取在线用户
|
||||
/// </summary>
|
||||
/// <param name="routeId"></param>
|
||||
/// <returns></returns>
|
||||
public static List<OnlineUser> GetOnlineUsers(params int[] routeId)
|
||||
{
|
||||
//return onlineUsers.Where(n => routeId.Contains(n.RouteId)).ToList();
|
||||
var result = onlineUserHelper.OnlineUsers.Where(u => routeId.Contains(u.RouteId)).ToList();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取附近的人(当前在线的所有人)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static object GetNearRiderData(int pageIndex, int pageSize = 5, double[] point = null)
|
||||
{
|
||||
if (point == null) return null;
|
||||
|
||||
var dict = new List<System.Tuple<double, OnlineUser>>();
|
||||
var allOnlineUsers = onlineUserHelper.OnlineUsers;
|
||||
foreach (var item in allOnlineUsers)
|
||||
{
|
||||
if (item.Id == PubCommData.CurrentUser.Id)
|
||||
{
|
||||
dict.Add(new Tuple<double, OnlineUser>(0, item));
|
||||
continue;
|
||||
}
|
||||
if (item.Point[0] != 0 && item.Point[1] != 0)
|
||||
{
|
||||
var distance = Math.Round(TurfHelper.GetDistances(point, item.Point) / 1000, 2);
|
||||
dict.Add(new Tuple<double, OnlineUser>(distance, item));
|
||||
}
|
||||
}
|
||||
var allList = dict.OrderBy(d => d.Item1);//.Select(d=>d.Item2);
|
||||
var list = allList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
|
||||
|
||||
var nearData = list.Select(n => new NearRiderModel()
|
||||
{
|
||||
Headimage = n.Item2.HeadImage,
|
||||
Name = n.Item2.Name,
|
||||
Near = n.Item1, //Math.Round(TurfHelper.GetDistances(point, n.Point) / 1000, 2),
|
||||
KGWeight = n.Item2.WeightKg.ToString(),
|
||||
Speed = Math.Round(n.Item2.Speed, 1),
|
||||
CountryImg = ConfigHelper.Host + $"User/GetCountryImg?userid={n.Item2.Id}",
|
||||
IsSelf = n.Item2.IsSelf
|
||||
});
|
||||
|
||||
return new
|
||||
{
|
||||
NearData = nearData,
|
||||
PageCount = (int)Math.Ceiling((double)allList.Count() / pageSize)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private class OnlineUserHelper
|
||||
{
|
||||
//public static List<OnlineUser> users { get; private set; }
|
||||
private static readonly object locker = new object();
|
||||
|
||||
|
||||
private readonly List<OnlineUser> onlineUsers = new List<OnlineUser>();
|
||||
public List<OnlineUser> OnlineUsers
|
||||
{
|
||||
get
|
||||
{
|
||||
//if((DateTime.Now - LastActiveTime).TotalSeconds > 1)
|
||||
//{
|
||||
// SetOnlineUser(new List<ReceiveMsgModel>());
|
||||
//}
|
||||
return onlineUsers.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置在线的人员
|
||||
/// </summary>
|
||||
public void SetOnlineUser(List<ReceiveMsgModel> mes)
|
||||
{
|
||||
try
|
||||
{
|
||||
var msgs = RemoveExceptionData(mes);
|
||||
//LastActiveTime = DateTime.Now;
|
||||
var ids = msgs.Where(m => onlineUsers.All(u => u.Id != m.MemberId)).Select(m => m.MemberId);
|
||||
if (ids.Any())
|
||||
{
|
||||
MapApi api = new MapApi();
|
||||
var rangeUser = api.GetOnlineUserInfo(ids).data;
|
||||
onlineUsers.AddRange(rangeUser);
|
||||
}
|
||||
foreach (var user in onlineUsers)
|
||||
{
|
||||
var item = msgs.FirstOrDefault(u => u.MemberId == user.Id);
|
||||
if (item != null)
|
||||
{
|
||||
user.LastActiveTime = DateTime.Now;
|
||||
user.RouteId = item.RouteId;
|
||||
user.Point = item.Point;
|
||||
user.IsCompleted = item.IsCompleted;
|
||||
//user.exit = item.exit;
|
||||
user.EndDistance = item.EndDistance;
|
||||
user.IsVirtual = item.MemberId < 0;
|
||||
user.Speed = item.Speed;
|
||||
user.WeightKg = item.WeightKg;
|
||||
user.PreDistance = item.PreDistance;
|
||||
user.CompetitionId = item.Competitionid;
|
||||
user.Saved = item.Saved;
|
||||
}
|
||||
else
|
||||
{
|
||||
user.PreDistance = user.EndDistance;
|
||||
}
|
||||
}
|
||||
onlineUsers.RemoveAll(u => u.IsLost);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
#if DEBUG
|
||||
throw;
|
||||
#endif
|
||||
//return new List<OnlineUser>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 去除重复数据,去除坐标为0的数据
|
||||
/// </summary>
|
||||
/// <param name="mes"></param>
|
||||
private List<ReceiveMsgModel> RemoveExceptionData(List<ReceiveMsgModel> mes)
|
||||
{
|
||||
var list = mes.ToList();
|
||||
//去除自己的数据和命令包
|
||||
//mes.RemoveAll(item => item.MemberId == PubCommData.CurrentUser.Id || item.Point[0] == 0);
|
||||
list.RemoveAll(item => item.Point[0] == 0 && item.Point[1] == 0);
|
||||
//去除重复数据
|
||||
list = list.Distinct(new OlineUserComparer()).ToList();
|
||||
|
||||
return list;
|
||||
}
|
||||
public class NearUserComparer : IEqualityComparer<NearRiderModel>
|
||||
{
|
||||
public bool Equals(NearRiderModel x, NearRiderModel y)
|
||||
{
|
||||
if (x == null)
|
||||
return y == null;
|
||||
return x.Name == y.Name;
|
||||
}
|
||||
|
||||
public int GetHashCode(NearRiderModel obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return 0;
|
||||
return obj.Name.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public class OlineUserComparer : IEqualityComparer<ReceiveMsgModel>
|
||||
{
|
||||
public bool Equals(ReceiveMsgModel x, ReceiveMsgModel y)
|
||||
{
|
||||
if (x == null)
|
||||
return y == null;
|
||||
return x.MemberId == y.MemberId;
|
||||
}
|
||||
|
||||
public int GetHashCode(ReceiveMsgModel obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return 0;
|
||||
return obj.MemberId.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/Network/MapUDPService.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f01b9ae72517c36488f04fdbbb889f71
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
123
Assets/Scenes/Ride/Scripts/Network/TcpService1.cs
Normal file
@ -0,0 +1,123 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using Assets.Scripts;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Network
|
||||
{
|
||||
public class TcpService1 : IService
|
||||
{
|
||||
private bool isExit = false;
|
||||
private PfTcpClient _tcpClient;
|
||||
private IPEndPoint iPEndPoint;
|
||||
//private Action<List<ReceiveMsgModel>> _action;
|
||||
|
||||
public void Start(Action<List<ReceiveMsgModel>> action)
|
||||
{
|
||||
if (_tcpClient == null)
|
||||
{
|
||||
//if (!IPAddress.TryParse(ConfigHelper.ServerIpAdress, out var ipString))
|
||||
//{
|
||||
// throw new ArgumentException("IP地址不正确");
|
||||
//}
|
||||
|
||||
//服务端端口
|
||||
iPEndPoint = ConfigHelper.TcpAddress;
|
||||
_tcpClient = new PfTcpClient(iPEndPoint.Address.ToString(), 11001, action);
|
||||
_tcpClient.OptionNoDelay = true;
|
||||
//_action = action;
|
||||
|
||||
_tcpClient.ConnectAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public void Send(byte[] dgram, int bytes)
|
||||
{
|
||||
if (_tcpClient == null) return;
|
||||
if (_tcpClient.IsConnected == false) return;
|
||||
//_tcpClient.WriteLine(System.Text.Encoding.ASCII.GetString(dgram));
|
||||
var txt = System.Text.Encoding.ASCII.GetString(dgram);
|
||||
//Debug.WriteLine("发送:"+txt);
|
||||
_tcpClient.Send(txt);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
isExit = true;
|
||||
_tcpClient.DisconnectAndStop();
|
||||
|
||||
_tcpClient = null;
|
||||
}
|
||||
|
||||
|
||||
class PfTcpClient : NetCoreServer.TcpClient
|
||||
{
|
||||
private bool _stop;
|
||||
Action<List<ReceiveMsgModel>> _action;
|
||||
public PfTcpClient(string address, int port, Action<List<ReceiveMsgModel>> action) : base(address, port)
|
||||
{
|
||||
_action = action;
|
||||
}
|
||||
|
||||
public void DisconnectAndStop()
|
||||
{
|
||||
_stop = true;
|
||||
DisconnectAsync();
|
||||
while (IsConnected)
|
||||
{
|
||||
Thread.Yield();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnConnected()
|
||||
{
|
||||
base.OnConnected();
|
||||
}
|
||||
|
||||
protected override void OnDisconnected()
|
||||
{
|
||||
//base.OnDisconnected();
|
||||
Debug.WriteLine("tcp断线,3秒后重连");
|
||||
Thread.Sleep(3000);
|
||||
|
||||
if (!_stop)
|
||||
{
|
||||
ConnectAsync();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnReceived(byte[] buffer, long offset, long size)
|
||||
{
|
||||
//base.OnReceived(buffer, offset, size);
|
||||
var returnData = Encoding.UTF8.GetString(buffer, (int)offset, (int)size);
|
||||
//Debug.WriteLine("收到:" + returnData+"\r\n");
|
||||
//System.IO.File.AppendAllText(System.Environment.CurrentDirectory + "接收到的数据.txt", returnData.Trim().Replace("\0", "")+"\r\n", Encoding.UTF8);
|
||||
var list = new List<ReceiveMsgModel>();
|
||||
var itemList = returnData.Split('|');
|
||||
|
||||
foreach (var item in itemList)
|
||||
{
|
||||
var info = ReceiveMsgModel.Parse(item);
|
||||
if (info != null)
|
||||
{
|
||||
list.Add(info);
|
||||
}
|
||||
}
|
||||
_action(list);
|
||||
}
|
||||
|
||||
protected override void OnError(SocketError error)
|
||||
{
|
||||
//base.OnError(error);
|
||||
Debug.WriteLine(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/Network/TcpService1.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d27070ad7cfef3418e8f764a42c08a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
94
Assets/Scenes/Ride/Scripts/Network/UdpService.cs
Normal file
@ -0,0 +1,94 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using Assets.Scripts;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Network
|
||||
{
|
||||
public class UdpService : IService
|
||||
{
|
||||
private bool isExit = false;
|
||||
private UdpClient udpClient;
|
||||
private IPEndPoint iPEndPoint;
|
||||
|
||||
public void Start(Action<List<ReceiveMsgModel>> action)
|
||||
{
|
||||
if (udpClient == null)
|
||||
{
|
||||
//if (!IPAddress.TryParse(ConfigHelper.ServerIpAdress, out var ipString))
|
||||
//{
|
||||
// throw new ArgumentException("IP地址不正确");
|
||||
//}
|
||||
|
||||
//服务端端口
|
||||
iPEndPoint = ConfigHelper.UdpAddress;
|
||||
udpClient = new UdpClient();
|
||||
uint IOC_IN = 0x80000000;
|
||||
uint IOC_VENDOR = 0x18000000;
|
||||
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
|
||||
udpClient.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
|
||||
udpClient.Client.ReceiveTimeout = 5000;//这里如果不设置超时,会导致整个应用程序阻塞。
|
||||
udpClient.Client.SendTimeout = 5000;
|
||||
udpClient.Connect(iPEndPoint);
|
||||
//heartbeat = new System.Timers.Timer();
|
||||
//heartbeat.Interval = 1000;//20秒一次心跳包
|
||||
//heartbeat.AutoReset = true;
|
||||
//heartbeat.Enabled = true;
|
||||
//heartbeat.Elapsed += Heartbeat_Elapsed;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (isExit == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] receiveBytes = udpClient.Receive(ref iPEndPoint);
|
||||
var returnData = Encoding.ASCII.GetString(receiveBytes);
|
||||
var list = new List<ReceiveMsgModel>();
|
||||
var itemList = returnData.Split('|');
|
||||
|
||||
foreach (var item in itemList)
|
||||
{
|
||||
var info = ReceiveMsgModel.Parse(item);
|
||||
if (info != null)
|
||||
{
|
||||
list.Add(info);
|
||||
}
|
||||
}
|
||||
action(list);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
await Task.Delay(6000);
|
||||
if (isExit == false && udpClient != null)
|
||||
{
|
||||
udpClient.Connect(iPEndPoint);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Send(byte[] dgram, int bytes)
|
||||
{
|
||||
udpClient?.Send(dgram, bytes);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
isExit = true;
|
||||
udpClient?.Close();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/Network/UdpService.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 170d4696cbfb82743a9189608d3a162a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
184
Assets/Scenes/Ride/Scripts/OtherPlayerController.cs
Normal file
@ -0,0 +1,184 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using Mapbox.Unity.Map;
|
||||
using Mapbox.Utils;
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using static Assets.Scripts.Apis.Models.MapDataModel;
|
||||
using System;
|
||||
using Random = UnityEngine.Random;
|
||||
using Assets.Scripts.Apis;
|
||||
using GeoJSON.Net.Geometry;
|
||||
using TurfCS;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class OtherPlayerController : MonoBehaviour
|
||||
{
|
||||
[Header("Character")]
|
||||
[SerializeField]
|
||||
GameObject character;
|
||||
[SerializeField]
|
||||
Animator characterAnimator;
|
||||
|
||||
AbstractMap map;
|
||||
|
||||
#region 动画控制参数
|
||||
Vector3 nextPos;
|
||||
Vector3 prePos;
|
||||
Vector2d currentlatlong; //当前坐标
|
||||
Vector2d nextlatlong; //下一个点的坐标
|
||||
float timer = 1.0f;//计时器
|
||||
#endregion
|
||||
|
||||
#region 选手骑行数据
|
||||
bool isStart;
|
||||
bool isMajor;//是否是主人公
|
||||
MapDataModel mapData;
|
||||
int userId;
|
||||
DateTime startTime;//开始骑行时间
|
||||
|
||||
double speed;
|
||||
double power;
|
||||
double gradev;
|
||||
double elevation;
|
||||
double cadance;
|
||||
double heartRate;
|
||||
int ticks;
|
||||
double totalDistance;
|
||||
double currentSlope;
|
||||
double nextSlope;
|
||||
double nextSlopeDistance;
|
||||
double distance;
|
||||
|
||||
public int UserId { get => userId; }
|
||||
public bool IsStart { get => isStart; }
|
||||
public double Speed { get => speed; }
|
||||
public double Power { get => power; }
|
||||
public double Cadance { get => cadance; }
|
||||
public double HeartRate { get => heartRate; }
|
||||
public int TotalTicks { get => ticks; }
|
||||
public double TotalDistance { get => totalDistance; }
|
||||
public double CurrentSlope { get => currentSlope; }
|
||||
public double NextSlope { get => nextSlope; }
|
||||
public double NextSlopeDistance { get => nextSlopeDistance; }
|
||||
public double Gradev { get => gradev; }
|
||||
public double Elevation { get => elevation; }
|
||||
#endregion
|
||||
|
||||
void Start()
|
||||
{
|
||||
characterAnimator = GetComponentInChildren<Animator>();
|
||||
var mainController = transform.parent.GetComponent<CyclingController>();
|
||||
map = FindObjectOfType<AbstractMap>();
|
||||
mapData = mainController.GetMapData();//获取路书信息
|
||||
isStart = true;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
timer -= Time.deltaTime;
|
||||
if (timer <= 0)//定时器 一秒执行一次
|
||||
{
|
||||
Run();
|
||||
timer = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
#region 骑行逻辑
|
||||
|
||||
//骑行中
|
||||
void Run()
|
||||
{
|
||||
if (IsStart)
|
||||
{
|
||||
power = 900;//功率
|
||||
speed = Helper.CalculateSpeed(elevation, 0, power, 65, 7);
|
||||
distance = Math.Round(speed / 3600, 6);
|
||||
totalDistance += distance;
|
||||
characterAnimator.SetBool("IsRide", false);//初始化动画状态
|
||||
if (totalDistance <= mapData.TotalDistance)
|
||||
{
|
||||
//数据处理
|
||||
ticks++;
|
||||
nextlatlong = Along(totalDistance);//下一个坐标
|
||||
nextPos = map.GeoToWorldPosition(nextlatlong);//下一个点
|
||||
nextPos.y += 0.3f;
|
||||
prePos = transform.localPosition;//当前点
|
||||
//动画控制
|
||||
if (distance > 0)
|
||||
{
|
||||
characterAnimator.SetBool("IsRide", true);//开始移动动画
|
||||
StartCoroutine(LookAtNextPos());//转向
|
||||
StartCoroutine(MoveTo());//移动
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO保存骑行数据
|
||||
characterAnimator.SetBool("ReachEnd", true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
characterAnimator.SetBool("IsRide", false);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 工具类
|
||||
public int CurrentIndex;
|
||||
//根据距离计算坐标
|
||||
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);
|
||||
}
|
||||
return nextlatlong;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 人物移动与转向控制
|
||||
IEnumerator LookAtNextPos()
|
||||
{
|
||||
Quaternion neededRotation = Quaternion.LookRotation(transform.localPosition - nextPos);
|
||||
Quaternion thisRotation = character.transform.localRotation;
|
||||
|
||||
float t = 0;
|
||||
while (t < 1.0f)
|
||||
{
|
||||
t += Time.deltaTime / 0.25f;
|
||||
var rotationValue = Quaternion.Slerp(thisRotation, neededRotation, t);
|
||||
character.transform.rotation = Quaternion.Euler(0, rotationValue.eulerAngles.y, 0);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
//人物移动控制
|
||||
IEnumerator MoveTo()
|
||||
{
|
||||
//让人物移动分点增加动画的流畅度
|
||||
float t = 0;
|
||||
while (t < 1)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
Vector3 v = Vector3.Lerp(prePos, nextPos, t);
|
||||
transform.localPosition = v;
|
||||
//控制海拔图的位置
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/OtherPlayerController.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf37eca46d898384fa2d9e17dfa3e25e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -13,6 +13,9 @@ using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using static CyclingController;
|
||||
using System.IO;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
@ -36,8 +39,10 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
|
||||
#region 选手骑行数据
|
||||
bool isStart;
|
||||
bool isMajor;//是否是主人公
|
||||
MapDataModel mapData;
|
||||
int userId;
|
||||
int routeId;
|
||||
DateTime startTime;//开始骑行时间
|
||||
|
||||
double speed;
|
||||
@ -45,7 +50,7 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
double gradev;
|
||||
double elevation;
|
||||
double cadance;
|
||||
double heartRate;
|
||||
int heartRate;
|
||||
int ticks;
|
||||
double totalDistance;
|
||||
double currentSlope;
|
||||
@ -71,10 +76,11 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
void Start()
|
||||
{
|
||||
characterAnimator = GetComponentInChildren<Animator>();
|
||||
var mainController = transform.parent.GetComponent<MainController>();
|
||||
var mainController = transform.parent.GetComponent<CyclingController>();
|
||||
map = FindObjectOfType<AbstractMap>();
|
||||
mapData = mainController.GetMapData();//获取路书信息
|
||||
InitializePlayer(mainController.GetCenterCoordinate());//初始人物
|
||||
routeId = mainController.RouteId;//路数id
|
||||
Initialize(mainController.GetCenterCoordinate());//初始人物
|
||||
}
|
||||
|
||||
void Update()
|
||||
@ -87,7 +93,7 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
}
|
||||
}
|
||||
|
||||
#region 骑行逻辑
|
||||
#region 游戏状态控制
|
||||
//开始骑行
|
||||
public void SetStart()
|
||||
{
|
||||
@ -103,10 +109,14 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
public void SetPause()
|
||||
{
|
||||
isStart = false;
|
||||
Complete();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 骑行逻辑
|
||||
|
||||
//初始化玩家距离/朝向
|
||||
void InitializePlayer(double[] coordinates)
|
||||
void Initialize(double[] coordinates)
|
||||
{
|
||||
ticks = 0;//当前骑行时间
|
||||
//初始化人物位置
|
||||
@ -119,7 +129,8 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
//Quaternion firstRotation = Quaternion.LookRotation(transform.localPosition - secondVect3d);
|
||||
//character.transform.rotation = Quaternion.Euler(0, firstRotation.eulerAngles.y, 0);
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
public List<TargetData> RiderDatas = new List<TargetData>();
|
||||
//骑行中
|
||||
void Run()
|
||||
{
|
||||
@ -131,6 +142,7 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
speed = Helper.CalculateSpeed(elevation, 0, power, 65, 7);
|
||||
distance = Math.Round(speed / 3600, 6);
|
||||
totalDistance += distance;
|
||||
|
||||
characterAnimator.SetBool("IsRide", false);//初始化动画状态
|
||||
if (totalDistance <= mapData.TotalDistance)
|
||||
{
|
||||
@ -143,7 +155,18 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
//记录骑行数据
|
||||
var recordText = string.Format($"{ ticks },{ power.ToString(CultureInfo.InvariantCulture) },{ speed.ToString(CultureInfo.InvariantCulture) },{ Math.Round(totalDistance, 6).ToString(CultureInfo.InvariantCulture) },{ cadance.ToString(CultureInfo.InvariantCulture) },{ heartRate.ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.x, 6).ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.y, 6).ToString(CultureInfo.InvariantCulture) }");
|
||||
Debug.Log(recordText);
|
||||
sb.AppendLine(recordText);
|
||||
|
||||
RiderDatas.Add(new TargetData
|
||||
{
|
||||
Ticks = ticks,
|
||||
_Power = power,
|
||||
_Speed = speed,
|
||||
_Distance = totalDistance,
|
||||
_Cadence = cadance,
|
||||
_HeartRate = heartRate,
|
||||
_Lat = nextlatlong.x,
|
||||
_Lon = nextlatlong.y
|
||||
});
|
||||
|
||||
//动画控制
|
||||
if (distance > 0)
|
||||
@ -155,7 +178,23 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO保存骑行数据
|
||||
totalDistance = mapData.TotalDistance;
|
||||
//记录骑行数据
|
||||
var recordText = string.Format($"{ ticks },{ power.ToString(CultureInfo.InvariantCulture) },{ speed.ToString(CultureInfo.InvariantCulture) },{ Math.Round(totalDistance, 6).ToString(CultureInfo.InvariantCulture) },{ cadance.ToString(CultureInfo.InvariantCulture) },{ heartRate.ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.x, 6).ToString(CultureInfo.InvariantCulture) },{ Math.Round(nextlatlong.y, 6).ToString(CultureInfo.InvariantCulture) }");
|
||||
Debug.Log(recordText);
|
||||
RiderDatas.Add(new TargetData
|
||||
{
|
||||
Ticks = ticks,
|
||||
_Power = power,
|
||||
_Speed = speed,
|
||||
_Distance = totalDistance,
|
||||
_Cadence = cadance,
|
||||
_HeartRate = heartRate,
|
||||
_Lat = nextlatlong.x,
|
||||
_Lon = nextlatlong.y
|
||||
});
|
||||
Complete();
|
||||
isStart = false;
|
||||
characterAnimator.SetBool("ReachEnd", true);
|
||||
}
|
||||
}
|
||||
@ -164,64 +203,102 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
characterAnimator.SetBool("IsRide", false);
|
||||
}
|
||||
}
|
||||
|
||||
//发送当前用户位置给UDPs
|
||||
void SendUdp() {
|
||||
|
||||
}
|
||||
//TODO:骑行结束
|
||||
void Finish()
|
||||
private int weight = 65;
|
||||
private int bicycleWeight = 7;
|
||||
private string ContinueMark = "TODO";
|
||||
private int ContinueIndex=0;
|
||||
private int Competitionid =0;
|
||||
private bool IsNeedRanking = true;
|
||||
private double CurrentRouteStartDistance = 0;
|
||||
private int ManufacturerId=0;
|
||||
private int AntModelId =0 ;
|
||||
private CyclingModel cyclingModel = CyclingModel.Single;
|
||||
private DateTime EndTime;
|
||||
void Complete()
|
||||
{
|
||||
//上传文件
|
||||
//var path = FileHelper.GetDataDire("MapWorkoutRecords");
|
||||
//var fname = path + "/" + newFileName + ".txt";
|
||||
//var files = new List<string>();
|
||||
|
||||
EndTime = startTime.AddSeconds(ticks);
|
||||
MapInterruptRecordApi api = new MapInterruptRecordApi();
|
||||
|
||||
int FTP = 200;
|
||||
double NP = 0;
|
||||
string id = Guid.NewGuid().ToString();
|
||||
string newFileName = Guid.NewGuid().ToString();
|
||||
int FTP = Helper.GetFtp();
|
||||
double NP = Helper.GetNP(RiderDatas);
|
||||
//强度
|
||||
double IF = NP / FTP;
|
||||
|
||||
|
||||
var mapRecord = new MapInterruptRecord
|
||||
//训练量
|
||||
double TSS = (RiderDatas.Count * NP * IF) / (FTP * 3600) * 100;
|
||||
var recordId = Guid.NewGuid().ToString();
|
||||
var averagePower = Helper.AveragePower(RiderDatas);
|
||||
var interruptRecord = new MapInterruptRecord
|
||||
{
|
||||
Id = id,
|
||||
RouteId = 5946,
|
||||
EndDistance = totalDistance,
|
||||
RouteImage = "",
|
||||
RecordFileName = "",
|
||||
CreateTime = DateTime.Now,//骑行结束时间
|
||||
IsCompleted = true,
|
||||
TotalDistance = totalDistance,
|
||||
Id = recordId,
|
||||
RouteId = routeId,
|
||||
RouteName = "",
|
||||
TotalDistance = mapData.TotalDistance,
|
||||
UserId = userId,
|
||||
Ftp = 200,
|
||||
IF = IF,
|
||||
Kj = 0,
|
||||
Tss = 0,
|
||||
NormalizedPower = Math.Round(NP, 0),
|
||||
AveragePower = 0,
|
||||
MaxPower = 0,
|
||||
Ticks = ticks,
|
||||
AverageCadence = 0,
|
||||
MaxCadence = 0,
|
||||
AverageHeartRate = 0,
|
||||
MaxHeartRate =0,
|
||||
Progress = 1,
|
||||
ContinueMark = "",
|
||||
ContinueIndex = 0,
|
||||
RecordFileName = newFileName + ".txt",
|
||||
Ftp = FTP,//FTP设置
|
||||
IF = Math.Round(IF, 2),
|
||||
Kj = RiderDatas.Sum(a => a._Power) / 1000,//消耗
|
||||
Tss = Math.Round(TSS, 2),
|
||||
EndDistance = totalDistance,
|
||||
IsCompleted = totalDistance >= mapData.TotalDistance,
|
||||
NormalizedPower = Math.Floor(NP),//标准化功率
|
||||
AveragePower = averagePower,//平均功率
|
||||
MaxPower = RiderDatas.Max(a => a._Power),//最大功率
|
||||
WeightKg = Math.Round(averagePower / weight, 2),
|
||||
Weight = weight,
|
||||
BicycleWeight = bicycleWeight,
|
||||
ContinueMark = ContinueMark,
|
||||
ContinueIndex = ContinueIndex,
|
||||
IsDelete = false,
|
||||
MapCompetitionId = 0,
|
||||
CurrentRouteStartDistance = 0,
|
||||
StartTime = DateTime.Now,
|
||||
WeightKg = 0,
|
||||
Weight = 0,
|
||||
BicycleWeight = 0,
|
||||
Mode = "Single",
|
||||
Param = "",
|
||||
DeviceNumber = "",
|
||||
ManufacturerId = 0,
|
||||
ManufacturerName ="",
|
||||
MapCompetitionId = Competitionid,
|
||||
ManufacturerName = "TODO",
|
||||
DeviceNumber = "TODO",
|
||||
IsRanking = IsNeedRanking,
|
||||
CurrentRouteStartDistance = CurrentRouteStartDistance,
|
||||
ManufacturerId = ManufacturerId,
|
||||
AntModelId = AntModelId,
|
||||
StartTime = startTime,
|
||||
CreateTime = EndTime,
|
||||
Ticks = RiderDatas.Last().Ticks,
|
||||
Mode = cyclingModel.ToString(),
|
||||
//Param = Newtonsoft.Json.JsonConvert.SerializeObject(selectParam),
|
||||
//GlobalCyclingId = selectParam.GlobalCyclingId
|
||||
};
|
||||
interruptRecord.SpeedRange = null;
|
||||
double process = Math.Round((totalDistance - interruptRecord.CurrentRouteStartDistance) /mapData.TotalDistance, 2);
|
||||
interruptRecord.Progress = process > 1 ? 1 : process;
|
||||
|
||||
api.Add(mapRecord, null);
|
||||
var cadences = RiderDatas.Where(a => a._Cadence.HasValue && a._Cadence.Value > 0);
|
||||
if (cadences.Any())
|
||||
{
|
||||
interruptRecord.AverageCadence = Math.Round(cadences.Average(a => a._Cadence.GetValueOrDefault(0)));
|
||||
}
|
||||
interruptRecord.MaxCadence = Math.Round(RiderDatas.Max(a => a._Cadence.GetValueOrDefault(0)));
|
||||
interruptRecord.AverageHeartRate = Math.Round(RiderDatas.Average(a => a._HeartRate.GetValueOrDefault(0)));
|
||||
interruptRecord.MaxHeartRate = RiderDatas.Max(a => a._HeartRate.GetValueOrDefault(0));
|
||||
|
||||
var path = Helper.GetDataDire("MapWorkoutRecords");
|
||||
var fname = path + "/" + newFileName + ".txt";
|
||||
var files = new List<string>();
|
||||
using (var fs = new FileInfo(fname).OpenWrite())
|
||||
{
|
||||
var stream = new StreamWriter(fs);
|
||||
stream.BaseStream.Seek(0, SeekOrigin.End);
|
||||
foreach (var item in RiderDatas)
|
||||
{
|
||||
stream.Write(item.Write() + "\r\n");
|
||||
}
|
||||
stream.Flush();
|
||||
stream.Close();
|
||||
files.Add(fname);
|
||||
}
|
||||
|
||||
var result = api.Add(interruptRecord, files);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
29
Assets/Scenes/Ride/Scripts/PubCommData.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
|
||||
public class PubCommData
|
||||
{
|
||||
public static t_user CurrentUser;
|
||||
|
||||
public static int PlanId;//当前训练id
|
||||
|
||||
public static string sp = "";
|
||||
|
||||
public static string po = "";
|
||||
|
||||
public static string SearchKeyword = "";
|
||||
|
||||
/// <summary>
|
||||
/// lat lng
|
||||
/// </summary>
|
||||
public static double[] location;
|
||||
/// <summary>
|
||||
/// 当前位置
|
||||
/// </summary>
|
||||
public static string Address;
|
||||
|
||||
public static double routeDistance;
|
||||
/// <summary>
|
||||
/// en,zh-CN
|
||||
/// </summary>
|
||||
public static string Lauguage = "";
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/PubCommData.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e19a9a72e39c8da4489a110f68ff2dc1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -27,7 +27,7 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
|
||||
GameObject _directionsGO;
|
||||
GameObject _mipMapRoute;
|
||||
MainController mainCotroller;
|
||||
CyclingController cyclingCotroller;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
@ -42,7 +42,7 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
|
||||
public void Start()
|
||||
{
|
||||
mainCotroller = transform.parent.GetComponent<MainController>();
|
||||
cyclingCotroller = transform.parent.GetComponent<CyclingController>();
|
||||
StartCoroutine(QueryTimer());
|
||||
//CreateRoute();
|
||||
}
|
||||
@ -70,7 +70,7 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
var meshData = new MeshData();
|
||||
var dat = new List<Vector3>();
|
||||
|
||||
var mapData = mainCotroller.GetMapData();
|
||||
var mapData = cyclingCotroller.GetMapData();
|
||||
if (mapData != null)
|
||||
{
|
||||
foreach (var mapDataItem in mapData.List)
|
||||
|
||||
230
Assets/Scenes/Ride/Scripts/TurfHelper.cs
Normal file
@ -0,0 +1,230 @@
|
||||
using GeoJSON.Net.Geometry;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TurfCS;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class TurfHelper
|
||||
{
|
||||
|
||||
//static TurfHelper()
|
||||
//{
|
||||
// string name = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".Resources.turf.min.js";
|
||||
// System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||
|
||||
//}
|
||||
|
||||
private LineString _line;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="points">坐标(lat,lon)</param>
|
||||
public TurfHelper(IEnumerable<double[]> points)
|
||||
{
|
||||
//var list = new GeoJSON.Net.Geometry.GeographicPosition();
|
||||
var list = points.Select(p => new GeoJSON.Net.Geometry.GeographicPosition(p[0], p[1]));
|
||||
|
||||
_line = new LineString(list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="distance">km</param>
|
||||
public GeographicPosition Along(double distance)
|
||||
{
|
||||
var pt1 = Turf.Along(_line, distance);
|
||||
return ((GeographicPosition)((GeoJSON.Net.Geometry.Point)pt1.Geometry).Coordinates);
|
||||
}
|
||||
|
||||
public double Bearing(double[] p1, double[] p2)
|
||||
{
|
||||
var pt1 = Turf.Point(p1);
|
||||
var pt2 = Turf.Point(p2);
|
||||
return Turf.Bearing(pt1, pt2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取两个点的距离m
|
||||
/// </summary>
|
||||
/// <param name="from"></param>
|
||||
/// <param name="to"></param>
|
||||
/// <returns></returns>
|
||||
public static double GetDistances(double[] from, double[] to)
|
||||
{
|
||||
var pt1 = Turf.Point(from);
|
||||
var pt2 = Turf.Point(to);
|
||||
var value = Turf.Distance(pt1, pt2, "kilometers") * 1000;
|
||||
return Math.Round(value, 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// https://gist.github.com/neilkennedy/9227665
|
||||
/// </summary>
|
||||
/// <param name="neLng"></param>
|
||||
/// <param name="neLat"></param>
|
||||
/// <param name="swLng"></param>
|
||||
/// <param name="swLat">SouthWest</param>
|
||||
/// <param name="point">lon,lat</param>
|
||||
/// <returns></returns>
|
||||
public static bool Inside(double neLng, double neLat, double swLng, double swLat, double[] point)
|
||||
{
|
||||
var poly = Turf.BboxPolygon(new List<double>() { neLng, neLat, swLng, swLat });
|
||||
var ptIn = Turf.Point(point);
|
||||
|
||||
return Turf.Inside(ptIn, poly);
|
||||
}
|
||||
|
||||
|
||||
///// <summary>
|
||||
/////
|
||||
///// </summary>
|
||||
///// <param name="bottomLeft">lng, lat</param>
|
||||
///// <param name="bottomRight"></param>
|
||||
///// <param name="topRight"></param>
|
||||
///// <param name="topLeft"></param>
|
||||
///// <param name="point"></param>
|
||||
///// <returns></returns>
|
||||
//public static bool Inside(List<double[]> points, double[] point)
|
||||
//{
|
||||
// var script = new StringBuilder("var points = [];");
|
||||
// foreach (var item in points)
|
||||
// {
|
||||
// script.AppendLine($"points.push([{ string.Join(",", item) }]);");
|
||||
// }
|
||||
// script.AppendLine($"points.push([{ string.Join(",", points.First()) }]);");
|
||||
// script.AppendLine("var poly = turf.polygon([points]);");
|
||||
// script.AppendLine($"turf.booleanPointInPolygon([{ string.Join(",", point) }], poly);");
|
||||
|
||||
|
||||
// var result = (bool)engine.Evaluate(script.ToString());
|
||||
|
||||
// return result;
|
||||
//}
|
||||
|
||||
public class location
|
||||
{
|
||||
public double lat;
|
||||
public double lng;
|
||||
}
|
||||
/// <summary>
|
||||
/// 坐标点是否在多边形内判断
|
||||
/// https://www.cnblogs.com/yushuo/p/9304471.html
|
||||
/// </summary>
|
||||
/// <param name="point"></param>
|
||||
/// <param name="pts"></param>
|
||||
/// <returns></returns>
|
||||
public static bool isPointInPolygon(location point, List<location> pts)
|
||||
{
|
||||
|
||||
//检查类型
|
||||
if (point == null || pts == null)
|
||||
return false;
|
||||
|
||||
var N = pts.Count;
|
||||
var boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
|
||||
var intersectCount = 0; //cross points count of x
|
||||
var precision = 2e-10; //浮点类型计算时候与0比较时候的容差
|
||||
location p1, p2; //neighbour bound vertices
|
||||
var p = point; //测试点
|
||||
p1 = pts[0]; //left vertex
|
||||
for (var i = 1; i <= N; ++i)
|
||||
{
|
||||
//check all rays
|
||||
if (p.lat.Equals(p1.lat) && p.lng.Equals(p1.lng))
|
||||
{
|
||||
return boundOrVertex; //p is an vertex
|
||||
}
|
||||
|
||||
p2 = pts[i % N]; //right vertex
|
||||
if (p.lat < Math.Min(p1.lat, p2.lat) || p.lat > Math.Max(p1.lat, p2.lat))
|
||||
{
|
||||
//ray is outside of our interests
|
||||
p1 = p2;
|
||||
continue; //next ray left point
|
||||
}
|
||||
|
||||
if (p.lat > Math.Min(p1.lat, p2.lat) && p.lat < Math.Max(p1.lat, p2.lat))
|
||||
{
|
||||
//ray is crossing over by the algorithm (common part of)
|
||||
if (p.lng <= Math.Max(p1.lng, p2.lng))
|
||||
{
|
||||
//x is before of ray
|
||||
if (p1.lat == p2.lat && p.lng >= Math.Min(p1.lng, p2.lng))
|
||||
{
|
||||
//overlies on a horizontal ray
|
||||
return boundOrVertex;
|
||||
}
|
||||
|
||||
if (p1.lng == p2.lng)
|
||||
{
|
||||
//ray is vertical
|
||||
if (p1.lng == p.lng)
|
||||
{
|
||||
//overlies on a vertical ray
|
||||
return boundOrVertex;
|
||||
}
|
||||
else
|
||||
{
|
||||
//before ray
|
||||
++intersectCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//cross point on the left side
|
||||
var xinters =
|
||||
(p.lat - p1.lat) * (p2.lng - p1.lng) / (p2.lat - p1.lat) +
|
||||
p1.lng; //cross point of lng
|
||||
if (Math.Abs(p.lng - xinters) < precision)
|
||||
{
|
||||
//overlies on a ray
|
||||
return boundOrVertex;
|
||||
}
|
||||
|
||||
if (p.lng < xinters)
|
||||
{
|
||||
//before ray
|
||||
++intersectCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//special case when ray is crossing through the vertex
|
||||
if (p.lat == p2.lat && p.lng <= p2.lng)
|
||||
{
|
||||
//p crossing over p2
|
||||
var p3 = pts[(i + 1) % N]; //next vertex
|
||||
if (p.lat >= Math.Min(p1.lat, p3.lat) && p.lat <= Math.Max(p1.lat, p3.lat))
|
||||
{
|
||||
//p.lat lies between p1.lat & p3.lat
|
||||
++intersectCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
intersectCount += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
p1 = p2; //next ray left point
|
||||
}
|
||||
|
||||
if (intersectCount % 2 == 0)
|
||||
{
|
||||
//偶数在多边形外
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//奇数在多边形内
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scenes/Ride/Scripts/TurfHelper.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c9cee88de351ad4da4f2d171a46a533
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -6,41 +6,56 @@ using System.Linq;
|
||||
using System.Collections;
|
||||
using Mapbox.Unity.Map;
|
||||
using DG.Tweening;
|
||||
using System;
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
|
||||
public class UIManager : MonoBehaviour
|
||||
{
|
||||
#region UI control
|
||||
[SerializeField]
|
||||
Button startBtn;
|
||||
Button startBtn;//开始按钮
|
||||
[SerializeField]
|
||||
Button simpleBtn;
|
||||
Button simpleBtn;//进入简约模式按钮
|
||||
[SerializeField]
|
||||
Text ditance;//当前骑行距离
|
||||
[SerializeField]
|
||||
Text candance;//踏频
|
||||
[SerializeField]
|
||||
Text heartRate;//心率
|
||||
[SerializeField]
|
||||
GameObject rightPanel;//右边列表
|
||||
[SerializeField]
|
||||
GameObject leftPanel;//左边列表
|
||||
[SerializeField]
|
||||
Text speedTxt;//当前速度
|
||||
[SerializeField]
|
||||
Text powerTxt;//功率
|
||||
[SerializeField]
|
||||
Text timerTxt;//计时器
|
||||
[SerializeField]
|
||||
Text countDownTxt;//倒计时5s
|
||||
[SerializeField] LineChart elevationChart;//海拔图
|
||||
[SerializeField] Image img;//当前用户头像
|
||||
[SerializeField]
|
||||
Button StartOrPauseButton;//暂停按钮
|
||||
[SerializeField]
|
||||
Button SettingButton;//设置那妞
|
||||
[SerializeField]
|
||||
Button DeviceButton;//设备按钮
|
||||
[SerializeField]
|
||||
Button ExitButton;//退出按钮
|
||||
#endregion
|
||||
|
||||
[SerializeField]
|
||||
GameObject rightPanel;
|
||||
[SerializeField]
|
||||
GameObject leftPanel;
|
||||
#region 控制器
|
||||
|
||||
[SerializeField]
|
||||
Text speedTxt;
|
||||
PlayerController playerController;//当前用户
|
||||
CyclingController mainController;//主控制器
|
||||
|
||||
[SerializeField]
|
||||
Text powerTxt;
|
||||
#endregion
|
||||
|
||||
[SerializeField]
|
||||
Text timerTxt;
|
||||
|
||||
[SerializeField]
|
||||
Text countDownTxt;
|
||||
|
||||
[SerializeField]
|
||||
LineChart elevationChart;
|
||||
|
||||
[SerializeField] Image img;
|
||||
|
||||
PlayerController playerController;
|
||||
MainController mainController;
|
||||
private float timeRemaining = 1f;
|
||||
private int count = 0;
|
||||
|
||||
@ -48,11 +63,21 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
startBtn.onClick.AddListener(StartRide);
|
||||
simpleBtn.onClick.AddListener(ClearPanel);
|
||||
StartOrPauseButton.onClick.AddListener(PauseRide);
|
||||
SettingButton.onClick.AddListener(ShowSettingPanel);
|
||||
DeviceButton.onClick.AddListener(ShowDevicePanel);
|
||||
ExitButton.onClick.AddListener(StopRide);
|
||||
|
||||
playerController = FindObjectOfType<PlayerController>();
|
||||
mainController = FindObjectOfType<MainController>();
|
||||
mainController = FindObjectOfType<CyclingController>();
|
||||
}
|
||||
|
||||
//根据不同的骑行模式渲染不同的UI界面
|
||||
void InitUI(CyclingModel cyclingModel)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
RenderChart();
|
||||
@ -66,23 +91,49 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
countDownTxt.gameObject.SetActive(true);
|
||||
countDownTxt.text = count.ToString();
|
||||
}
|
||||
//暂停游戏
|
||||
private void PauseRide()
|
||||
{
|
||||
playerController.SetPause();
|
||||
startBtn.gameObject.SetActive(true);
|
||||
}
|
||||
//结束游戏
|
||||
private void StopRide()
|
||||
{
|
||||
|
||||
}
|
||||
//显示设备连接
|
||||
private void ShowDevicePanel()
|
||||
{
|
||||
}
|
||||
//显示设置
|
||||
private void ShowSettingPanel()
|
||||
{
|
||||
}
|
||||
int isSimple = 1;
|
||||
//TODO:简约模式
|
||||
private void ClearPanel()
|
||||
{
|
||||
leftPanel.transform.DOMoveX(leftPanel.transform.position.x+isSimple * 286.1764f, 1);
|
||||
rightPanel.transform.DOMoveX(rightPanel.transform.position.x - isSimple * 286.1764f, 1);
|
||||
elevationChart.transform.DOMoveX(elevationChart.transform.position.x + isSimple * 286.1764f, 1);
|
||||
leftPanel.transform.DOLocalMove(new Vector3(leftPanel.transform.localPosition.x + isSimple * -430f, leftPanel.transform.localPosition.y, leftPanel.transform.localPosition.z), 1);
|
||||
rightPanel.transform.DOLocalMove(new Vector3(rightPanel.transform.localPosition.x+ isSimple* 330f, rightPanel.transform.localPosition.y, rightPanel.transform.localPosition.z), 1);
|
||||
//elevationChart.transform.DOMoveX(elevationChart.transform.position.x + isSimple * 286.1764f, 1);
|
||||
isSimple *= -1;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
//获取当前选中玩家绑定当前UI
|
||||
if (playerController != null)
|
||||
{
|
||||
//绑定UI
|
||||
speedTxt.text = $"{playerController.Speed}";
|
||||
powerTxt.text = $"{playerController.Power}";
|
||||
timerTxt.text = Helper.FormatTicks(playerController.TotalTicks);
|
||||
|
||||
ditance.text = $"{Math.Round(playerController.TotalDistance,2)}KM";
|
||||
heartRate.text = $"{Math.Round(playerController.HeartRate, 0)}";
|
||||
candance.text = $"{Math.Round(playerController.Cadance, 0)}";
|
||||
//倒计时
|
||||
if (count > 0)
|
||||
{
|
||||
timeRemaining -= Time.deltaTime;
|
||||
@ -98,11 +149,11 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
}
|
||||
}
|
||||
countDownTxt.text = count.ToString();
|
||||
|
||||
//移动海拔图头像 TODO:移动所有人的头像
|
||||
MoveChartMarkPoint();
|
||||
}
|
||||
}
|
||||
|
||||
//初始化海拔图
|
||||
void RenderChart()
|
||||
{
|
||||
elevationChart.ClearData();
|
||||
@ -115,12 +166,10 @@ namespace Assets.Scenes.Ride.Scripts
|
||||
|
||||
void MoveChartMarkPoint()
|
||||
{
|
||||
var dataPoints = elevationChart.series.list[0].dataPoints;
|
||||
var dataPoints = elevationChart.series.list[0].dataPoints.OrderBy(c=>c.x).ToList();
|
||||
if (dataPoints.Count > 0)
|
||||
{
|
||||
var pinLoction = dataPoints[playerController.CurrentIndex];
|
||||
Debug.Log(pinLoction);
|
||||
Debug.Log(dataPoints[0]);
|
||||
pinLoction.y += 10;
|
||||
img.transform.localPosition = pinLoction;
|
||||
}
|
||||
|
||||
8
Assets/Scenes/Ride/icons.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9605c5a09befa644fb31e6d59785fa21
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
BIN
Assets/Scenes/Ride/icons/Cadence Sensor_1.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
104
Assets/Scenes/Ride/icons/Cadence Sensor_1.png.meta
Normal file
@ -0,0 +1,104 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e814bd829485c14885e66788ddddd01
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Scenes/Ride/icons/Cadence Sensor_2.png
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
104
Assets/Scenes/Ride/icons/Cadence Sensor_2.png.meta
Normal file
@ -0,0 +1,104 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cd9b5ab531797d4eaa820fcfa982c62
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
BIN
Assets/Scenes/Ride/icons/Heart Rate Monitor_0.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
104
Assets/Scenes/Ride/icons/Heart Rate Monitor_0.png.meta
Normal file
@ -0,0 +1,104 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b8196c4e549a22d4f9379de1f208d0ae
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Scenes/Ride/icons/Heart Rate Monitor_1.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
104
Assets/Scenes/Ride/icons/Heart Rate Monitor_1.png.meta
Normal file
@ -0,0 +1,104 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 602a012543e878f49b091385a3bb7d68
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Scenes/Ride/icons/Heart Rate Monitor_2.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
104
Assets/Scenes/Ride/icons/Heart Rate Monitor_2.png.meta
Normal file
@ -0,0 +1,104 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfebaeb62faae4c4caa69f4a4d49e669
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
BIN
Assets/Scenes/Ride/icons/Power Meter_0.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
104
Assets/Scenes/Ride/icons/Power Meter_0.png.meta
Normal file
@ -0,0 +1,104 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa0429f412b20364382ad3842c9234dd
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Scenes/Ride/icons/Power Meter_1.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
104
Assets/Scenes/Ride/icons/Power Meter_1.png.meta
Normal file
@ -0,0 +1,104 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdab9e56a0e02f649babff60cf86d9c3
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Scenes/Ride/icons/Power Meter_2.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
104
Assets/Scenes/Ride/icons/Power Meter_2.png.meta
Normal file
@ -0,0 +1,104 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f06e0ed7b7049f14fa8d09a08fd524c7
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
@ -514,4 +514,4 @@ namespace Assets.Scripts.Apis
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -70,5 +71,21 @@ namespace Assets.Scripts.Apis
|
||||
return Get<JsonResult<Dictionary<string, string>>>($"Map/GetServiceKey").data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取在线用户的数据
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns></returns>
|
||||
public JsonResult<List<OnlineUser>> GetOnlineUserInfo(IEnumerable<int> ids)
|
||||
{
|
||||
//var result = PostAsync<JsonResult<List<OnlineUser>>>("Map/GetUserInfoByIds", ids).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<JsonResult<List<OnlineUser>>>(Post("Map/GetUserInfoByIds", ids));
|
||||
if (result.result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ using Assets.Scripts.Apis.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -17,5 +18,10 @@ namespace Assets.Scripts
|
||||
public static UserApi userApi = new UserApi();
|
||||
public static MapApi mapApi = new MapApi();
|
||||
public static MapInterruptRecordApi mapInterruptRecordApi = new MapInterruptRecordApi();
|
||||
public static string AppVersion = "1.0.0";
|
||||
|
||||
public static IPEndPoint UdpAddress ;
|
||||
|
||||
public static IPEndPoint TcpAddress ;
|
||||
}
|
||||
}
|
||||
|
||||
8
Assets/TextMesh Pro.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f54d1bd14bd3ca042bd867b519fee8cc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/TextMesh Pro/Documentation.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e7e8f5a82a3a134e91c54efd2274ea9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/TextMesh Pro/Examples & Extras.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce51c8e33b734b4db6086586558c53a3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/TextMesh Pro/Examples & Extras/Fonts.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b63e0053080646b9819789bf3bf9fa17
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/TextMesh Pro/Examples & Extras/Materials.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5808953df7a24274a851aa6dee52d30e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/TextMesh Pro/Examples & Extras/Prefabs.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bff2544887143f5807c7d5059d07f79
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/TextMesh Pro/Examples & Extras/Resources.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6d3a169ad794942a21da6a552d62f6f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f422cd1388b01047a58cd07c7a23d9d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f1e85c79acf49968737939ce8b445c7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ac6db30e75b49b282a3564110579f27
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/TextMesh Pro/Examples & Extras/Scenes.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db1090641b3241f6995b587eb21637bc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||