骑行代码迁移,赛事逻辑初步框架完成
This commit is contained in:
1 parent
380e67cc1e
commit
ec45246aa4
151 files changed
+7689
-3538
No files matched your search
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51a1cfdf96f466e4aa751465d945a5c7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d89e303a3008b774e87b6ba0a35ea20b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e8389fe2e69de14ba5b9b48f580dd81
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb74a9f48e6075b4098a071b7c41755b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cecb30d95cebeb43b5768b505937c28
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2da7d3c8a2ec8054fa19b088b2a8c9d9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,318 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model.CyclingModels;
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using ChartAndGraph;
|
||||
using DG.Tweening;
|
||||
using GeoJSON.Net.Geometry;
|
||||
using Mapbox.Unity.Map;
|
||||
using Mapbox.Utils;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TurfCS;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public abstract class AbstractPlayer: MonoBehaviour
|
||||
{
|
||||
[Header("Character")]
|
||||
[SerializeField]
|
||||
GameObject character;
|
||||
[SerializeField]
|
||||
Animator characterAnimator;
|
||||
|
||||
protected AbstractMap map;
|
||||
//AbstractMap map;
|
||||
public bool IsShowInfo { get; set; }
|
||||
#region 动画控制参数
|
||||
public Vector3 nextPos;
|
||||
protected Vector3 prePos = Vector3.zero;
|
||||
float timer = 1.0f;//计时器
|
||||
#endregion
|
||||
|
||||
#region 选手骑行数据
|
||||
protected Vector2d nextlatlong; //下一个点的坐标
|
||||
protected Vector2d currentlatlong; //当前坐标
|
||||
//protected bool isStart;//开始或者暂停
|
||||
//public bool isQuit;//true 中途退出 或者到达终点
|
||||
protected bool isMajor;//是否是主人公
|
||||
protected MapDataModel mapData;
|
||||
//protected int userId;
|
||||
protected DateTime startTime;//开始骑行时间
|
||||
protected DateTime endTime;//结束骑行时间
|
||||
protected double weight;//体重
|
||||
protected double bicycleWeight;//车重
|
||||
protected double speed;
|
||||
protected double power;
|
||||
protected double elevation;
|
||||
protected double cadance;
|
||||
protected int heartRate;
|
||||
protected int ticks;
|
||||
protected double totalDistance;
|
||||
protected double currentSlope;
|
||||
protected double nextSlope;
|
||||
protected double nextSlopeDistance;
|
||||
protected double distance;
|
||||
protected double currentSlopeDistance;
|
||||
protected double lastEndDistance;
|
||||
protected double totalClimb;
|
||||
|
||||
public double TotalClimb { get => totalClimb; }
|
||||
public int UserId { set; get; }//{ get => userId; }
|
||||
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 Distance { get => distance; }
|
||||
public double CurrentSlope { get => currentSlope; }
|
||||
public double NextSlope { get => nextSlope; }
|
||||
public double NextSlopeDistance { get => nextSlopeDistance; }
|
||||
public double CurrentSlopeDistance { get => currentSlopeDistance; }
|
||||
public double Elevation { get => elevation; }
|
||||
public double LastEndDistance { get => lastEndDistance; }
|
||||
public Vector2d Currentlatlong { get => currentlatlong; }
|
||||
#endregion
|
||||
|
||||
#region UI对象
|
||||
|
||||
//UI对象
|
||||
protected GameObject headPanel;
|
||||
protected GraphChartBase graph;
|
||||
protected ChartDataSourceScript chartDataSourceScript;
|
||||
|
||||
#endregion
|
||||
void Start()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
Excute();
|
||||
AfterExcute();
|
||||
}
|
||||
protected virtual void AfterExcute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#region 骑行逻辑
|
||||
//初始化骑行数据
|
||||
protected CyclingController mainController;
|
||||
protected BaseCycling cyclingExcutor;
|
||||
protected virtual void Init()
|
||||
{
|
||||
characterAnimator = GetComponentInChildren<Animator>();
|
||||
mainController = transform.parent.GetComponent<CyclingController>();
|
||||
map = transform.parent.Find("Map").GetComponent<AbstractMap>();
|
||||
mapData = mainController.GetMapData();//获取路书信息
|
||||
|
||||
//获取海拔图UI对象
|
||||
var graphObject = transform.parent.Find("SingleUI/Panel/GraphChart");
|
||||
chartDataSourceScript = graphObject.GetComponent<ChartDataSourceScript>();
|
||||
graph = graphObject.GetComponent<GraphChartBase>();
|
||||
}
|
||||
|
||||
protected virtual void Excute()
|
||||
{
|
||||
//CamControl();
|
||||
timer -= Time.deltaTime;
|
||||
if (timer <= 0)//定时器 一秒执行一次
|
||||
{
|
||||
BeforeRun();
|
||||
Run();
|
||||
timer = 1.0f;
|
||||
}
|
||||
}
|
||||
public bool stopRecord = false;
|
||||
//骑行中
|
||||
protected virtual void Run()
|
||||
{
|
||||
if (mapData == null)
|
||||
return;
|
||||
ComputeNextSlope();//计算下一个坡度相关数据
|
||||
MoveGraphHead();//移动海拔图头像
|
||||
//人物动画控制
|
||||
if (characterAnimator != null)
|
||||
{
|
||||
characterAnimator.SetFloat("Speed", (float)speed);
|
||||
characterAnimator.SetFloat("Slope", (float)currentSlope);
|
||||
if (currentSlope > 5)
|
||||
{
|
||||
characterAnimator.speed = 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
characterAnimator.speed = 1f;
|
||||
}
|
||||
|
||||
if (totalDistance >= mapData.TotalDistance)
|
||||
{
|
||||
characterAnimator.SetBool("ReachEnd", true);//到达终点
|
||||
}
|
||||
}
|
||||
|
||||
//开始骑行
|
||||
if (GetStart())
|
||||
{
|
||||
|
||||
ticks++;
|
||||
Compute();//接受蓝牙设备数据计算
|
||||
|
||||
if (totalDistance > mapData.TotalDistance)
|
||||
{
|
||||
distance = totalDistance - mapData.TotalDistance;
|
||||
totalDistance = mapData.TotalDistance;
|
||||
stopRecord = true;
|
||||
StartCoroutine("LateUpload");
|
||||
}
|
||||
|
||||
//数据处理
|
||||
|
||||
nextPos = map.GeoToWorldPosition(currentlatlong);//下一个点
|
||||
nextPos.y += 1.35f;//提高y轴让人物站在地图上面
|
||||
prePos = transform.localPosition;//当前点
|
||||
thisRotation = transform.localRotation;
|
||||
//移动动画控制
|
||||
if (distance > 0)
|
||||
{
|
||||
//transform.localPosition = nextPos;
|
||||
StartCoroutine(LookAtNextPos());//转向
|
||||
StartCoroutine(MoveTo());//移动
|
||||
}
|
||||
}
|
||||
}
|
||||
//游戏开始开关
|
||||
public virtual bool GetStart()
|
||||
{
|
||||
return mainController.isStart;
|
||||
}
|
||||
protected virtual void BeforeRun()
|
||||
{
|
||||
|
||||
}
|
||||
//计算功率 速度 当前骑行总里程(M)心率 踏频 等
|
||||
protected virtual void Compute()
|
||||
{
|
||||
|
||||
}
|
||||
//当前用户调用来上传骑行记录
|
||||
public virtual void Upload()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 工具类
|
||||
|
||||
IEnumerator LateUpload()
|
||||
{
|
||||
yield return new WaitForSeconds(1);
|
||||
Upload();
|
||||
StopCoroutine("LateUpload");
|
||||
}
|
||||
|
||||
public int CurrentIndex;
|
||||
private int index;
|
||||
public double CurrentDistance;//当前所处区间距离
|
||||
public double NextSlopeTotalDistance;
|
||||
//当前距离所在的海拔/坡度/距离 下一个点的坡度以及剩余距离
|
||||
void ComputeNextSlope()
|
||||
{
|
||||
double sumDistance = 0;
|
||||
if (mapData == null)
|
||||
return;
|
||||
var pointList = mapData.List;
|
||||
int preIndex = 0;
|
||||
for (int i = 0; i < pointList.Count; i++)
|
||||
{
|
||||
sumDistance += pointList[i].Distance;
|
||||
if (totalDistance * 1000 <= sumDistance)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
preIndex = index > 0 ? index - 1:0;//前一个索引
|
||||
CurrentIndex = index;//当前索引
|
||||
int nextIndex = index == pointList.Count - 1 ? index : index + 1; //计算下一个点的坡度和距离
|
||||
|
||||
PreElevation = pointList[preIndex].Elevation; //计算上一个海拔
|
||||
PreSlope = pointList[preIndex].Grade; //计算上一个坡度
|
||||
//计算当前海拔和坡度&当前区间距离
|
||||
elevation = pointList[CurrentIndex].Elevation;
|
||||
currentSlope = pointList[CurrentIndex].Grade;
|
||||
CurrentDistance = pointList[CurrentIndex].Distance;
|
||||
//计算下一个海拔和坡度&当前区间距离
|
||||
nextSlope = pointList[nextIndex].Grade;
|
||||
nextSlopeDistance = sumDistance - totalDistance * 1000;
|
||||
NextSlopeTotalDistance = pointList[nextIndex].Distance;
|
||||
currentSlopeDistance = (totalDistance * 1000 - (sumDistance - pointList[index].Distance));// CurrentDistance-( totalDistance * 1000 - (sumDistance - pointList[index].Distance));
|
||||
}
|
||||
public double PreElevation;
|
||||
public double PreSlope;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 人物移动与转向控制
|
||||
|
||||
Quaternion thisRotation;
|
||||
public Quaternion currentRotation;
|
||||
IEnumerator LookAtNextPos()
|
||||
{
|
||||
if (prePos != nextPos)
|
||||
{
|
||||
Quaternion neededRotation = Quaternion.LookRotation(prePos - nextPos);
|
||||
|
||||
float t = 0;
|
||||
while (t < 1.0f)
|
||||
{
|
||||
t += Time.deltaTime / 0.5f;
|
||||
currentRotation = Quaternion.Slerp(thisRotation, neededRotation, t);
|
||||
character.transform.rotation = Quaternion.Euler(0, currentRotation.eulerAngles.y, 0);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vector3 deltaPos = Vector3.zero;
|
||||
Vector3 previousPos = Vector3.zero;
|
||||
void CamControl()
|
||||
{
|
||||
deltaPos = transform.position - previousPos;
|
||||
deltaPos.y = 0;
|
||||
Camera.main.transform.position = Vector3.Lerp(Camera.main.transform.position, Camera.main.transform.position + deltaPos, Time.time);
|
||||
previousPos = transform.position;
|
||||
}
|
||||
public Vector3 currentPos = new Vector3(0,0,0);
|
||||
//人物移动控制
|
||||
protected virtual IEnumerator MoveTo()
|
||||
{
|
||||
//让人物移动分点增加动画的流畅度
|
||||
float t = 0;
|
||||
while (t < 1)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
|
||||
Vector3 v = Vector3.Lerp(prePos, nextPos, t);
|
||||
currentPos = v;
|
||||
transform.localPosition = v;
|
||||
yield return null; new WaitForEndOfFrame();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UI行为
|
||||
|
||||
protected virtual void MoveGraphHead()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f01d57cfa983552409f7c9e896892c31
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class ArrowSpirteRenderScript:MonoBehaviour
|
||||
{
|
||||
List<Sprite> sprites;
|
||||
Image image;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
sprites = new List<Sprite>();
|
||||
for (int i = 1; i < 51; i++)
|
||||
{
|
||||
sprites.Add(Resources.Load<Sprite>($"Images/Ride/Ride Bright/Ride_bright{i.ToString("0000")}"));
|
||||
}
|
||||
image = transform.GetComponent<Image>();
|
||||
}
|
||||
int index = 0;
|
||||
float time = 0;
|
||||
void Update()
|
||||
{
|
||||
time += Time.deltaTime;
|
||||
if (time < 0.03)
|
||||
{
|
||||
return;
|
||||
}
|
||||
time = 0;
|
||||
if (index % 49 == 0)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
image.sprite = sprites[index];
|
||||
index ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f34d1e1c66a3f8a418997dd9d78c8f29
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,93 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using Assets.Scripts;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class BaseListFactory : MonoBehaviour
|
||||
{
|
||||
protected AbstractPlayer playerController;
|
||||
protected CyclingController cyclingController;
|
||||
|
||||
protected GameObject nearByItem;
|
||||
protected GameObject nearByMajorItem;
|
||||
private GameObject scroll;
|
||||
private GameObject body;
|
||||
|
||||
protected int totalPages = 0;
|
||||
protected int bufferSize = 0;
|
||||
protected int pageIndex = 1;
|
||||
protected int pageSize = 7;
|
||||
private int preNum = 0;//前面的数量
|
||||
private int offset = 8;//显示区域的数量
|
||||
|
||||
protected bool startMouse = false;
|
||||
protected float t = 1f;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
scroll = transform.parent.parent.gameObject;
|
||||
if (scroll != null)
|
||||
{
|
||||
UIManager.AddEvent(scroll, UnityEngine.EventSystems.EventTriggerType.EndDrag, OnEndDrag);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetAxis("Mouse ScrollWheel") != 0)
|
||||
{
|
||||
if (scroll.GetComponent<ScrollRect>().verticalNormalizedPosition <= 0 ||
|
||||
scroll.GetComponent<ScrollRect>().verticalNormalizedPosition >= (pageIndex == 0 ? 1.2 : 1))
|
||||
{
|
||||
startMouse = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (startMouse)
|
||||
{
|
||||
startMouse = false;
|
||||
OnEndDrag(null);
|
||||
}
|
||||
}
|
||||
|
||||
t -= Time.deltaTime;
|
||||
while (t < 0)
|
||||
{
|
||||
Utils.DestroyChildren(transform);
|
||||
CreateList();
|
||||
t = 1;
|
||||
}
|
||||
}
|
||||
protected virtual void CreateList()
|
||||
{
|
||||
|
||||
}
|
||||
private void OnEndDrag(BaseEventData arg0)
|
||||
{
|
||||
var scrollrect = scroll.GetComponent<ScrollRect>();
|
||||
if (scrollrect.verticalNormalizedPosition <= 0)
|
||||
{
|
||||
var p = pageIndex + 1;
|
||||
if (p * pageSize <= totalPages)
|
||||
{
|
||||
pageIndex++;
|
||||
}
|
||||
|
||||
}
|
||||
if (scrollrect.verticalNormalizedPosition >= (pageIndex == 0 ? 1.2 : 1))
|
||||
{
|
||||
var p = pageIndex - 1;
|
||||
if (p > 0)
|
||||
{
|
||||
pageIndex--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be7bdc22e15ad254da04ebf9dc274fe5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,570 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using System.Linq;
|
||||
using Mapbox.Unity.Map;
|
||||
using DG.Tweening;
|
||||
using System;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.EventSystems;
|
||||
using ChartAndGraph;
|
||||
using Assets.Scripts;
|
||||
using Assets.Scripts.Apis.Models;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
|
||||
public class BaseUIManager : MonoBehaviour
|
||||
{
|
||||
#region UI control
|
||||
protected GameObject target;
|
||||
protected GameObject nearByPanel;//附近的人列表
|
||||
protected GameObject leftPanel;//伴侣骑行列表
|
||||
protected GameObject nextSlopePanel;//下一个坡度面板
|
||||
protected GameObject currentSlopePanel;//当前坡度面板
|
||||
protected GameObject selectPanel;//骑行模式选择
|
||||
protected GameObject selectPlayer;//伴侣骑行选择窗口
|
||||
protected GameObject reviewPanel;
|
||||
protected GameObject titlePanel;
|
||||
protected GameObject quitPanel;//退出界面
|
||||
|
||||
protected Text nextSlopeText;//下一个坡度
|
||||
protected Text nextSlopeDistanceText;//下一个坡度距离
|
||||
protected Text currentSlopeText;//当前坡度
|
||||
protected Text currentSlopeDistanceText;//当前坡度已骑行距离
|
||||
protected Text currentSlopeToatalDistanceText;//当前坡度总距离
|
||||
protected Text speedTxt;//当前速度
|
||||
protected Text powerTxt;//功率
|
||||
protected Text timerTxt;//计时器
|
||||
protected Text ditance;//当前骑行距离
|
||||
protected Text totalDistance;//当前骑行距离
|
||||
protected Text candance;//踏频
|
||||
protected Text heartRate;//心率
|
||||
protected Text countDownTxt;//倒计时5s
|
||||
protected Text mapName;//路书名称
|
||||
protected Text fps;//fps
|
||||
protected Text totalClimb;
|
||||
|
||||
protected Button startBtn;//开始按钮
|
||||
protected Button simpleBtn;//进入简约模式按钮
|
||||
protected Button pauseButton;//暂停按钮
|
||||
protected Button settingButton;//设置那妞
|
||||
protected Button deviceButton;//设备按钮
|
||||
protected Button viewButton;//视角按钮
|
||||
protected Button exitButton;//退出按钮
|
||||
protected Button singleButton;//单人骑行按钮
|
||||
protected Button shadowButton;//影子选手按钮
|
||||
protected Button addButton;//添加伴侣骑行
|
||||
protected Button saveButton;//退出panel保存按钮
|
||||
protected Button cancelQuitButton;//退出panel取消按钮
|
||||
protected Button closeQuitButton;//退出panel关闭按钮
|
||||
|
||||
protected RawImage head;//海拔图头像
|
||||
protected GameObject miniMap;//小地图
|
||||
protected RawImage altitudeGraph;//海拔图
|
||||
protected Image leftImage;
|
||||
protected Image rightImage;
|
||||
protected Image area;
|
||||
#endregion
|
||||
|
||||
#region 控制器
|
||||
|
||||
protected PlayerController playerController;//当前用户
|
||||
protected CyclingController mainController;//主控制器
|
||||
|
||||
#endregion
|
||||
|
||||
protected float timeRemaining = 1f;
|
||||
protected int count = 0;
|
||||
protected Image arrow;
|
||||
protected AbstractMap map;
|
||||
protected Transform t;
|
||||
protected GameObject alertPanel;
|
||||
protected Button alertBtn;
|
||||
protected Button alertCloseBtn;
|
||||
protected Text preSlopeText;
|
||||
protected GameObject startPanel;
|
||||
protected GameObject headPanel;
|
||||
protected GameObject settingPanel;
|
||||
protected Button abandonButton;
|
||||
protected GameObject singleArea;
|
||||
protected Sprite downhill1;
|
||||
protected Sprite uphill1;
|
||||
protected Sprite straight;
|
||||
|
||||
protected Sprite downhill1Small;
|
||||
protected Sprite uphill1Small;
|
||||
protected Sprite straightSmall;
|
||||
|
||||
protected Image nextSlopeImage;
|
||||
protected Image currentSlopeImage;
|
||||
protected Image miniMapProcess;
|
||||
protected Image currentSlopeProcess;
|
||||
protected Text miniMapProcessText;
|
||||
|
||||
protected Slider cameraSlider;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
#region 控件获取与事件绑定
|
||||
fps = transform.Find("Panel/FPS").GetComponent<Text>();
|
||||
arrow = transform.Find("Panel/Arrow").GetComponent<Image>();
|
||||
map = transform.parent.Find("Map").GetComponent<AbstractMap>();
|
||||
leftPanel = transform.Find("Panel/ReviewPanel").gameObject;
|
||||
nearByPanel = transform.Find("Panel/NearPanel").gameObject;
|
||||
startPanel = transform.Find("Panel/StartPanel").gameObject;
|
||||
startBtn = transform.Find("Panel/StartPanel/StartButton").GetComponent<Button>();
|
||||
simpleBtn = transform.Find("Panel/SimpleButton").GetComponent<Button>();
|
||||
ditance = transform.Find("Panel/ComputerPanel/Distance").GetComponent<Text>();
|
||||
titlePanel = transform.Find("Panel/TitlePanel").gameObject;
|
||||
totalDistance = transform.Find("Panel/TitlePanel/TotalDistance").GetComponent<Text>();
|
||||
candance = transform.Find("Panel/PowerPanel/Cadance").GetComponent<Text>();
|
||||
heartRate = transform.Find("Panel/PowerPanel/Hrv").GetComponent<Text>();
|
||||
nextSlopePanel = transform.Find("Panel/NextSlopePanel").gameObject;
|
||||
currentSlopePanel = transform.Find("Panel/CurrentSlopePanel").gameObject;
|
||||
nextSlopeText = transform.Find("Panel/NextSlopePanel/NextSlopeText").GetComponent<Text>();
|
||||
nextSlopeDistanceText = transform.Find("Panel/NextSlopePanel/NextSlopeDistance").GetComponent<Text>();
|
||||
currentSlopeText = transform.Find("Panel/CurrentSlopePanel/CurrentSlopeText").GetComponent<Text>();
|
||||
currentSlopeDistanceText = transform.Find("Panel/CurrentSlopePanel/CurrentSlopeDistance").GetComponent<Text>();
|
||||
currentSlopeToatalDistanceText = transform.Find("Panel/CurrentSlopePanel/TotalSlopeDistance").GetComponent<Text>();
|
||||
currentSlopeProcess = transform.Find("Panel/CurrentSlopePanel/Process").GetComponent<Image>();
|
||||
|
||||
speedTxt = transform.Find("Panel/ComputerPanel/Speed").GetComponent<Text>();
|
||||
powerTxt = transform.Find("Panel/PowerPanel/Power").GetComponent<Text>();
|
||||
timerTxt = transform.Find("Panel/ComputerPanel/Timer").GetComponent<Text>();
|
||||
countDownTxt = transform.Find("Panel/CountDown").GetComponent<Text>();
|
||||
mapName = transform.Find("Panel/TitlePanel/MapName").GetComponent<Text>();
|
||||
totalClimb = transform.Find("Panel/ComputerPanel/TotalClimb").GetComponent<Text>();
|
||||
//img = transform.Find("Panel/ElevationChart/HeadImage").GetComponent<RawImage>();
|
||||
head = transform.Find("Panel/GraphChart/HeadPanel/Head").GetComponent<RawImage>();
|
||||
headPanel = transform.Find("Panel/GraphChart/HeadPanel").gameObject;
|
||||
t = transform.Find("Panel/GraphChart/Button");
|
||||
miniMap = transform.Find("Panel/MiniMap").gameObject;
|
||||
|
||||
alertPanel = transform.Find("Panel/Alert").gameObject;
|
||||
|
||||
selectPanel = transform.Find("Panel/SelectPanel").gameObject;
|
||||
selectPlayer = transform.Find("Panel/SelectPlayer").gameObject;
|
||||
reviewPanel = transform.Find("Panel/ReviewPanel").gameObject;
|
||||
quitPanel = transform.Find("Panel/QuitPanel").gameObject;
|
||||
|
||||
pauseButton = transform.Find("Panel/ToolBarPanel/StartOrPauseButton").GetComponent<Button>();
|
||||
settingButton = transform.Find("Panel/ToolBarPanel/SettingButton").GetComponent<Button>();
|
||||
deviceButton = transform.Find("Panel/ToolBarPanel/DeviceButton").GetComponent<Button>();
|
||||
exitButton = transform.Find("Panel/ToolBarPanel/ExitButton").GetComponent<Button>();
|
||||
|
||||
singleButton = transform.Find("Panel/SelectPanel/SingleButton").GetComponent<Button>();
|
||||
shadowButton = transform.Find("Panel/SelectPanel/ShadowButton").GetComponent<Button>();
|
||||
|
||||
singleArea = transform.Find("Panel/ReviewPanel/SingleArea").gameObject;
|
||||
addButton = transform.Find("Panel/ReviewPanel/SingleArea/AddButton").GetComponent<Button>();
|
||||
|
||||
saveButton = transform.Find("Panel/QuitPanel/QuitPanel/SaveButton").GetComponent<Button>();
|
||||
cancelQuitButton = transform.Find("Panel/QuitPanel/QuitPanel/CancelButton").GetComponent<Button>();
|
||||
closeQuitButton = transform.Find("Panel/QuitPanel/QuitPanel/CloseButton").GetComponent<Button>();
|
||||
abandonButton = transform.Find("Panel/QuitPanel/QuitPanel/AbandonButton").GetComponent<Button>();
|
||||
|
||||
viewButton = transform.Find("Panel/ViewButton").GetComponent<Button>();
|
||||
altitudeGraph = transform.Find("Panel/TitlePanel/AltitudeGraph").GetComponent<RawImage>();
|
||||
leftImage = transform.Find("Panel/TitlePanel/AltitudeGraph/Left").GetComponent<Image>();
|
||||
rightImage = transform.Find("Panel/TitlePanel/AltitudeGraph/Right").GetComponent<Image>();
|
||||
area = transform.Find("Panel/TitlePanel/AltitudeGraph/Area").GetComponent<Image>();
|
||||
settingPanel = transform.Find("Panel/SettingPanel").gameObject;
|
||||
preSlopeText = transform.Find("Panel/PreSlopePanel/PreSlopeText").GetComponent<Text>();
|
||||
|
||||
nextSlopeImage = transform.Find("Panel/NextSlopePanel/NextSlopeImage").GetComponent<Image>();
|
||||
currentSlopeImage = transform.Find("Panel/CurrentSlopePanel/Image").GetComponent<Image>();
|
||||
|
||||
//加载坡度图片
|
||||
downhill1 = Resources.Load<Sprite>("Images/Ride/downhill 1");
|
||||
uphill1 = Resources.Load<Sprite>("Images/Ride/uphill 1");
|
||||
straight = Resources.Load<Sprite>("Images/Ride/straight");
|
||||
|
||||
downhill1Small = Resources.Load<Sprite>("Images/Ride/downhill-small");
|
||||
uphill1Small = Resources.Load<Sprite>("Images/Ride/uphill-small");
|
||||
straightSmall = Resources.Load<Sprite>("Images/Ride/straight-small");
|
||||
|
||||
target = transform.parent.Find("Target").gameObject;
|
||||
//小地图进度
|
||||
miniMapProcess = transform.Find("Panel/MiniMap/Process").GetComponent<Image>();
|
||||
miniMapProcessText = transform.Find("Panel/MiniMap/Process/Text").GetComponent<Text>();
|
||||
|
||||
|
||||
UIManager.AddEvent(pauseButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, PauseRide);
|
||||
UIManager.AddEvent(exitButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, StopRide);
|
||||
UIManager.AddEvent(saveButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, SaveRide);
|
||||
|
||||
UIManager.AddEvent(settingButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, ShowSettingPanel);
|
||||
UIManager.AddEvent(deviceButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, ShowDevicePanel);
|
||||
UIManager.AddEvent(simpleBtn.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, ClearPanel);
|
||||
|
||||
UIManager.AddEvent(abandonButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, CancelQuit);
|
||||
UIManager.AddEvent(closeQuitButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, CloseQuit);
|
||||
UIManager.AddEvent(cancelQuitButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, CloseQuit);
|
||||
|
||||
UIManager.AddEvent(viewButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, ChangeView);
|
||||
|
||||
UIManager.AddEvent(singleButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerEnter, OnPointEnter);
|
||||
UIManager.AddEvent(shadowButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerEnter, OnPointEnter);
|
||||
UIManager.AddEvent(singleButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerExit, OnPointExit);
|
||||
UIManager.AddEvent(shadowButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerExit, OnPointExit);
|
||||
|
||||
#endregion
|
||||
}
|
||||
protected virtual void Start()
|
||||
{
|
||||
Init();//初始
|
||||
RenderChart();//渲染海拔图
|
||||
}
|
||||
protected virtual void Update()
|
||||
{
|
||||
time -= Time.deltaTime;
|
||||
while (time < 0) {
|
||||
MoveElevationImage();
|
||||
BindDataSource();
|
||||
fps.text = (1 / Time.deltaTime).ToString();
|
||||
time = 1;
|
||||
}
|
||||
MoveCamera();
|
||||
}
|
||||
private float cameraX = 0;
|
||||
private float cameraY = 0;
|
||||
private float cameraZ = 0;
|
||||
|
||||
private Transform player;
|
||||
private MapRoute routeInstance;
|
||||
public AbstractPlayer currentPlayer { get; set; }//当前选中用户
|
||||
|
||||
private float time = 1f;
|
||||
private float? localY;
|
||||
|
||||
private Vector3 m = new Vector3(0.1f, 0.1f, 0.1f);
|
||||
private Vector3 CameraVector = Vector3.zero;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
playerController = FindObjectOfType<PlayerController>();
|
||||
currentPlayer = playerController;//默认当前用户为当前选中用户
|
||||
mainController = FindObjectOfType<CyclingController>();
|
||||
player = transform.parent.Find("Player");
|
||||
var route = mainController.GetRoute();
|
||||
routeInstance = route.RouteInstance;
|
||||
//初始化3d视角
|
||||
var camera = routeInstance.Camera;
|
||||
if (!string.IsNullOrEmpty(camera))
|
||||
{
|
||||
var cameraArr = camera.Split(',');
|
||||
cameraX = float.Parse(cameraArr[0]);
|
||||
cameraY = float.Parse(cameraArr[1]);
|
||||
cameraZ = float.Parse(cameraArr[2]);
|
||||
}
|
||||
//开发者视角调整
|
||||
cameraSlider = transform.Find("Panel/CameraSlider").GetComponent<Slider>();
|
||||
Text CameraText = transform.Find("Panel/CameraSlider/Text").GetComponent<Text>();
|
||||
string[] phoneList = new string[] { "18120141032", "15651831367", "18120141031", "15261826280", "18662240319" };
|
||||
if (phoneList.Contains(App.CurrentUser.Phone))
|
||||
{
|
||||
cameraSlider.gameObject.SetActive(true);
|
||||
cameraSlider.value = cameraY;
|
||||
CameraText.text = cameraY.ToString("f0");
|
||||
cameraSlider.onValueChanged.AddListener((f) =>
|
||||
{
|
||||
cameraY = f;
|
||||
CameraText.text = f.ToString("f0");
|
||||
});
|
||||
}
|
||||
//路书基本信息绑定
|
||||
mapName.text = routeInstance.Name;
|
||||
totalDistance.text = Math.Round(mainController.GetMapData().TotalDistance, 1).ToString() + "KM";//总里程
|
||||
Utils.DisplayImage(altitudeGraph, route.RouteInstance.AltitudeGraph);//渲染海拔图
|
||||
//影子骑行按钮控制
|
||||
if (mainController.mapRouteRankingList == null || mainController.mapRouteRankingList.Count == 0)
|
||||
{
|
||||
shadowButton.image.sprite = Resources.Load<Sprite>("Images/Ride/Shadow Mode_no");
|
||||
shadowButton.enabled = false;
|
||||
shadowButton.interactable = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
shadowButton.enabled = true;
|
||||
shadowButton.interactable = true;
|
||||
}
|
||||
//标记3d的地图可以用
|
||||
if (!route.RouteInstance.Enable3D)
|
||||
{
|
||||
viewButton.enabled = false;
|
||||
viewButton.interactable = false;
|
||||
mainController.Is3dView = false;
|
||||
mainController.player.transform.localScale = new Vector3(0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
mainController.Is3dView = false;
|
||||
ChangeView(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//移动摄像头和箭头位置
|
||||
public void MoveCamera()
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
target.transform.position = playerController.currentPos; //player.transform.position;// new Vector3((float)Math.Round(player.transform.position.x,1), 0, (float)Math.Round(player.transform.position.z,1));
|
||||
if (!mainController.Is3dView)
|
||||
{
|
||||
Vector3 v = Vector3.zero;
|
||||
v.y += playerController.currentRotation.eulerAngles.y + 160f; //target.transform.rotation = playerController.transform.rotation;//new Quaternion(playerController.transform.rotation.x, playerController.transform.rotation.y +1f, playerController.transform.rotation.z, playerController.transform.rotation.w);
|
||||
target.transform.eulerAngles = v; //.Set(0, playerController.currentRotation.eulerAngles.y + 160f, 0);// = new Vector3(0, playerController.transform.eulerAngles.y + 160f, 0);
|
||||
//mainController.player.transform.localScale.Set(0.1f, 0.1f, 0.1f);
|
||||
player.transform.localScale = m;
|
||||
}
|
||||
else
|
||||
{
|
||||
CameraVector.x = cameraX;
|
||||
CameraVector.y = cameraY;
|
||||
CameraVector.z = cameraZ;
|
||||
target.transform.eulerAngles = CameraVector;
|
||||
}
|
||||
//控制照片移动
|
||||
((RectTransform)arrow.transform).position = Camera.main.WorldToScreenPoint(target.transform.position);
|
||||
if (playerController.Speed > 0 && mainController.isStart)
|
||||
{
|
||||
arrow.transform.Find("bg").gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
arrow.transform.Find("bg").gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
//绑定数据源
|
||||
public void BindDataSource()
|
||||
{
|
||||
//获取当前选中玩家绑定当前UI
|
||||
if (playerController != null)
|
||||
{
|
||||
speedTxt.text = $"{Math.Round(playerController.Speed, 1)}";
|
||||
powerTxt.text = $"{playerController.Power}";
|
||||
timerTxt.text = Helper.FormatTicks(playerController.TotalTicks);
|
||||
ditance.text = Math.Round(playerController.TotalDistance, 1).ToString("f1");
|
||||
heartRate.text = $"{Math.Round(playerController.HeartRate, 0)}";
|
||||
candance.text = $"{Math.Round(playerController.Cadance, 0)}";
|
||||
preSlopeText.text = $"{Math.Round(playerController.PreSlope, 1)}%";
|
||||
currentSlopeToatalDistanceText.text = $"Total:{Math.Round(playerController.CurrentDistance, 0)}M";
|
||||
//坡度相关数据
|
||||
nextSlopeText.text = Math.Round(playerController.NextSlope, 1).ToString() + "%";
|
||||
//nextSlopeDistanceText.GetComponent<NumberDotween>().AnimateNum((float)playerController.NextSlopeDistance, 0, "-{0}M");
|
||||
nextSlopeDistanceText.text = $"{Math.Round(playerController.NextSlopeTotalDistance, 0)}M";
|
||||
currentSlopeText.text = Math.Round(playerController.CurrentSlope, 1).ToString() + "%";
|
||||
currentSlopeDistanceText.GetComponent<NumberDotween>().AnimateNum((float)playerController.CurrentSlopeDistance, Math.Round(playerController.CurrentDistance, 0), playerController.CurrentIndex, 0, "{0}M", currentSlopeProcess);
|
||||
currentSlopeDistanceText.GetComponent<NumberDotween>().AnimateNumText((float)playerController.CurrentDistance - (float)playerController.CurrentSlopeDistance, Math.Round(playerController.CurrentDistance, 0), playerController.CurrentIndex, 0, "{0}M", currentSlopeProcess);
|
||||
totalClimb.text = Math.Round(playerController.TotalClimb, 0).ToString();
|
||||
//小地图进度
|
||||
var process = (float)(playerController.TotalDistance / routeInstance.Distance);
|
||||
miniMapProcess.fillAmount = process;
|
||||
miniMapProcessText.text = $"{process*100:f0}%";
|
||||
//动态改变坡度图片
|
||||
ChangeSlopeImage(nextSlopeImage, playerController.NextSlope);
|
||||
ChangeSlopeImage(currentSlopeImage, playerController.CurrentSlope);
|
||||
}
|
||||
}
|
||||
//改变坡度图片
|
||||
public void ChangeSlopeImage(Image image,double slope)
|
||||
{
|
||||
if (slope >= 1)
|
||||
{
|
||||
image.sprite = uphill1;
|
||||
}
|
||||
else if (slope > -1 && slope < 1)
|
||||
{
|
||||
image.sprite = straight;
|
||||
}
|
||||
else
|
||||
{
|
||||
image.sprite = downhill1;
|
||||
}
|
||||
}
|
||||
//开始骑行
|
||||
public virtual void StartRide()
|
||||
{
|
||||
|
||||
}
|
||||
//继续骑行
|
||||
public virtual void ContinueRide()
|
||||
{
|
||||
|
||||
}
|
||||
//暂停游戏
|
||||
public virtual void PauseRide(BaseEventData baseEventData)
|
||||
{
|
||||
mainController.SetPause();
|
||||
count = 0;
|
||||
countDownTxt.gameObject.SetActive(false);
|
||||
startBtn.gameObject.SetActive(true);
|
||||
startPanel.SetActive(true);
|
||||
}
|
||||
//保存游戏
|
||||
public virtual void SaveRide(BaseEventData baseEventData)
|
||||
{
|
||||
if (playerController.TotalTicks > 0 && !mainController.isQuit)
|
||||
{
|
||||
mainController.SetQuit();
|
||||
playerController.Upload();
|
||||
quitPanel.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SceneManager.LoadScene("MainScene");
|
||||
}
|
||||
}
|
||||
//不保存退出
|
||||
public virtual void CancelQuit(BaseEventData baseEventData)
|
||||
{
|
||||
quitPanel.SetActive(false);
|
||||
SceneManager.LoadScene("MainScene");
|
||||
}
|
||||
//取消退出
|
||||
public void CloseQuit(BaseEventData baseEventData)
|
||||
{
|
||||
quitPanel.SetActive(false);
|
||||
}
|
||||
//切换视角
|
||||
public void ChangeView(BaseEventData baseEventData)
|
||||
{
|
||||
mainController.ChangeMapImageStyle(arrow.gameObject);
|
||||
}
|
||||
//结束游戏
|
||||
public virtual void StopRide(BaseEventData baseEventData)
|
||||
{
|
||||
if (playerController.TotalTicks > 0)
|
||||
{
|
||||
quitPanel.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
SceneManager.LoadScene("MainScene");
|
||||
}
|
||||
}
|
||||
//显示设备连接
|
||||
public void ShowDevicePanel(BaseEventData baseEventData)
|
||||
{
|
||||
UIManager.Show(UIManager.Instance.DevicePanel, transform.Find("Panel").GetComponent<PFUIPanel>());
|
||||
}
|
||||
//显示设置
|
||||
public void ShowSettingPanel(BaseEventData baseEventData)
|
||||
{
|
||||
settingPanel.SetActive(true);
|
||||
}
|
||||
//进入简约模式
|
||||
int isSimple = 1;
|
||||
private bool clearLock = true;
|
||||
public void ClearPanel(BaseEventData baseEventData)
|
||||
{
|
||||
if (clearLock)
|
||||
{
|
||||
clearLock = false;
|
||||
leftPanel.transform.DOLocalMove(new Vector3(leftPanel.transform.localPosition.x + isSimple * 430f, leftPanel.transform.localPosition.y, leftPanel.transform.localPosition.z), 1);
|
||||
titlePanel.transform.DOLocalMove(new Vector3(titlePanel.transform.localPosition.x, titlePanel.transform.localPosition.y + isSimple * 200f, titlePanel.transform.localPosition.z), 1);
|
||||
miniMap.transform.DOLocalMove(new Vector3(miniMap.transform.localPosition.x, miniMap.transform.localPosition.y + isSimple * 260f, miniMap.transform.localPosition.z), 1);
|
||||
nextSlopePanel.transform.DOLocalMove(new Vector3(nextSlopePanel.transform.localPosition.x, nextSlopePanel.transform.localPosition.y + isSimple * 260f, nextSlopePanel.transform.localPosition.z), 1);
|
||||
currentSlopePanel.transform.DOLocalMove(new Vector3(currentSlopePanel.transform.localPosition.x, currentSlopePanel.transform.localPosition.y + isSimple * 120f, currentSlopePanel.transform.localPosition.z), 1);
|
||||
var Scale = isSimple == 1 ? new Vector3(0.7f, 0.7f, 0.7f) : new Vector3(1f, 1f, 1f);
|
||||
currentSlopePanel.transform.DOScale(Scale, 1);
|
||||
|
||||
viewButton.transform.DOLocalMove(new Vector3(viewButton.transform.localPosition.x + isSimple * 200f, viewButton.transform.localPosition.y, viewButton.transform.localPosition.z), 1);
|
||||
|
||||
nearByPanel.transform.DOLocalMove(new Vector3(nearByPanel.transform.localPosition.x + isSimple * -330f, nearByPanel.transform.localPosition.y, nearByPanel.transform.localPosition.z), 1).onComplete += () =>
|
||||
{
|
||||
clearLock = true;
|
||||
isSimple *= -1;
|
||||
simpleBtn.transform.GetComponent<Image>().sprite = isSimple == -1 ? Resources.Load<Sprite>("Images/Ride/full 1") : Resources.Load<Sprite>("Images/Ride/simple 1");
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
//初始化海拔图
|
||||
GraphChartBase graph;
|
||||
ChartDataSourceScript chartDataSourceScript;
|
||||
public void RenderChart()
|
||||
{
|
||||
var mapData = mainController.GetMapData();
|
||||
double x = 0;
|
||||
Dictionary<double, double> dataSource = new Dictionary<double, double>();
|
||||
List<double> dd = new List<double>();
|
||||
var one = mapData.List.Where(c => c.Distance == 0).Count();
|
||||
foreach (var item in mapData.List)
|
||||
{
|
||||
if (!dataSource.ContainsKey(x))
|
||||
{
|
||||
dataSource.Add(x, item.Elevation);
|
||||
}
|
||||
x += item.Distance;
|
||||
dd.Add(item.Elevation);
|
||||
}
|
||||
chartDataSourceScript = transform.Find("Panel/GraphChart").GetComponent<ChartDataSourceScript>();
|
||||
graph = transform.Find("Panel/GraphChart").GetComponent<GraphChartBase>();
|
||||
chartDataSourceScript.SetDataSource(dd.ToArray());
|
||||
|
||||
if (App.CurrentUser != null)
|
||||
{
|
||||
Utils.DisplayImage(head, App.CurrentUser.WxHeadImg);
|
||||
}
|
||||
}
|
||||
//移动总海拔图范围
|
||||
public void MoveElevationImage()
|
||||
{
|
||||
if (chartDataSourceScript.mData.Count <= chartDataSourceScript.targetPoints)
|
||||
{
|
||||
leftImage.gameObject.SetActive(false);
|
||||
rightImage.gameObject.SetActive(false);
|
||||
altitudeGraph.gameObject.SetActive(false);
|
||||
area.gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
var start = chartDataSourceScript.GetRealTimeStart();
|
||||
var end = chartDataSourceScript.GetRealTimeEnd();
|
||||
|
||||
var originWith =0D;
|
||||
var with = altitudeGraph.GetComponent<RectTransform>().sizeDelta.x;
|
||||
|
||||
var left = start * with + originWith;
|
||||
var right = end * with + originWith;
|
||||
var rectTransform = area.gameObject.GetComponent<RectTransform>();
|
||||
var width = (float)(end - start)* 286F;
|
||||
rectTransform.DOSizeDelta(new Vector2((float)width+5f, 40), 1);
|
||||
rectTransform.DOLocalMoveX((float)(left), 1);
|
||||
leftImage.GetComponent<RectTransform>().DOLocalMoveX((float)left, 1);
|
||||
rightImage.GetComponent<RectTransform>().DOLocalMoveX((float)right, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#region 事件行为
|
||||
|
||||
public void OnPointEnter(BaseEventData pointerEventData)
|
||||
{
|
||||
var button = ((PointerEventData)pointerEventData).pointerEnter.GetComponent<Button>();
|
||||
if (button != null)
|
||||
{
|
||||
var enterTransform = button.transform;
|
||||
if (localY == null)
|
||||
{
|
||||
localY = enterTransform.localPosition.y;
|
||||
}
|
||||
enterTransform.DOLocalMoveY(localY.Value + 5f, 0.5f);
|
||||
}
|
||||
}
|
||||
public void OnPointExit(BaseEventData pointerEventData)
|
||||
{
|
||||
var button = ((PointerEventData)pointerEventData).pointerEnter.GetComponent<Button>();
|
||||
if (button != null)
|
||||
{
|
||||
var enterTransform = button.transform;
|
||||
enterTransform.DOLocalMoveY(localY.Value, 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1525adde7daa9b440b73a0d6223f2755
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,250 @@
|
||||
using ChartAndGraph;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class ChartDataSourceScript:MonoBehaviour, IComparer<DoubleVector2>
|
||||
{
|
||||
public string Category = "Player 2";
|
||||
public int DownSampleToPoints = 0;
|
||||
public int targetPoints = 500;
|
||||
public List<DoubleVector2> mData = new List<DoubleVector2>(); // the data held by the chart
|
||||
double pageSize = 2f;
|
||||
double currentPagePosition = 0.0;
|
||||
double currentZoom = 0f;
|
||||
GraphChartBase graph;
|
||||
public double mCurrentPageSizeFactor = double.NegativeInfinity;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
graph = GetComponent<GraphChartBase>();
|
||||
}
|
||||
public double GetRealTimeStart()
|
||||
{
|
||||
return graph.HorizontalScrolling / mData.Count();
|
||||
}
|
||||
|
||||
public double GetRealTimeEnd()
|
||||
{
|
||||
return (graph.HorizontalScrolling+ graph.DataSource.HorizontalViewSize) / mData.Count();
|
||||
}
|
||||
|
||||
public bool ReachEnd()
|
||||
{
|
||||
return graph.HorizontalScrolling + graph.DataSource.HorizontalViewSize >= mData.Count;
|
||||
}
|
||||
|
||||
public bool ReachMid(int index)
|
||||
{
|
||||
return index - graph.HorizontalScrolling >= graph.DataSource.HorizontalViewSize / 2;
|
||||
}
|
||||
|
||||
public void InitHorizontalScrolling(int index)
|
||||
{
|
||||
var halfView = graph.DataSource.HorizontalViewSize / 2;
|
||||
if (index >= halfView)
|
||||
{
|
||||
if (index + halfView >= mData.Count)
|
||||
{
|
||||
graph.HorizontalScrolling = mData.Count - graph.DataSource.HorizontalViewSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
graph.HorizontalScrolling = index - halfView;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool VerifySorted(List<DoubleVector2> data)
|
||||
{
|
||||
if (data == null)
|
||||
return true;
|
||||
for (int i = 1; i < data.Count; i++)
|
||||
{
|
||||
if (data[i].x < data[i - 1].x)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void LoadWithoutDownSampling(int start, int end)
|
||||
{
|
||||
for (int i = start; i < end; i++) // load the data
|
||||
{
|
||||
graph.DataSource.AddPointToCategory("Player 2", mData[i].x, mData[i].y);
|
||||
}
|
||||
|
||||
}
|
||||
public int total;
|
||||
void LoadWithDownSampling(int start, int end)
|
||||
{
|
||||
total = end - start;
|
||||
|
||||
if (DownSampleToPoints >= total)
|
||||
{
|
||||
graph.DataSource.HorizontalViewSize = total;
|
||||
LoadWithoutDownSampling(start, end);
|
||||
return;
|
||||
}
|
||||
|
||||
double sampleCount = ((double)total) / (double)DownSampleToPoints;
|
||||
// graph.DataSource.AddPointToCategory(Category, mData[start].x, mData[start].y);
|
||||
pointMap.Clear();
|
||||
|
||||
for (int i = 0; i < DownSampleToPoints; i++)
|
||||
{
|
||||
int fractionStart = start + (int)(i * sampleCount); // the first point with a fraction
|
||||
int fractionEnd = start + (int)((i + 1) * sampleCount); // the first point with a fraction
|
||||
fractionEnd = Math.Min(fractionEnd, mData.Count - 1);
|
||||
double x = 0, y = 0;
|
||||
double divide = 0.0;
|
||||
List<int> l = new List<int>();
|
||||
for (int j = fractionStart; j < fractionEnd; j++) // avarge the poins
|
||||
{
|
||||
x += mData[j].x;
|
||||
y += mData[j].y;
|
||||
l.Add(j);
|
||||
divide++;
|
||||
}
|
||||
if (divide > 0.0)
|
||||
{
|
||||
x /= divide;
|
||||
y /= divide;
|
||||
pointMap.Add(l, i);
|
||||
graph.DataSource.AddPointToCategory("Player 2", x, y);
|
||||
}
|
||||
else
|
||||
Debug.Log("error");
|
||||
}
|
||||
// graph.DataSource.AddPointToCategory(Category, mData[last].x, mData[last].y);
|
||||
}
|
||||
public int GetViewIndex(int index)
|
||||
{
|
||||
foreach (var item in pointMap)
|
||||
{
|
||||
if (item.Key.Contains(index))
|
||||
{
|
||||
return item.Value;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
private IDictionary<IList<int>, int> pointMap = new Dictionary<IList<int>, int>();
|
||||
|
||||
public int FindClosestIndex(double position) // if you want to know what is index is currently displayed . use binary search to find it
|
||||
{
|
||||
//NOTE :: this method assumes your data is sorted !!!
|
||||
int res = mData.BinarySearch(new DoubleVector2(position, 0.0), this);
|
||||
if (res >= 0)
|
||||
return res;
|
||||
return ~res;
|
||||
}
|
||||
|
||||
double PageSizeFactor
|
||||
{
|
||||
get
|
||||
{
|
||||
return pageSize * graph.DataSource.HorizontalViewSize;
|
||||
}
|
||||
}
|
||||
void findPointsForPage(double position, out int start, out int end) // given a page position , find the right most and left most indices in the data for that page.
|
||||
{
|
||||
int index = FindClosestIndex(position); // use binary search to find the closest position to the current scroll point
|
||||
|
||||
double endPosition = position + PageSizeFactor;
|
||||
double startPosition = position - PageSizeFactor;
|
||||
|
||||
//starting from the current index , we find the page boundries
|
||||
for (start = index; start > 0; start--)
|
||||
{
|
||||
if (mData[start].x < startPosition) // take the first point that is out of the page. so the graph doesn't break at the edge
|
||||
break;
|
||||
}
|
||||
|
||||
for (end = index; end < mData.Count; end++)
|
||||
{
|
||||
if (mData[end].x > endPosition) // take the first point that is out of the page
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
public int start, end;
|
||||
public void LoadPage(double pagePosition)
|
||||
{
|
||||
if (graph != null)
|
||||
{
|
||||
graph.DataSource.StartBatch(); // call start batch
|
||||
graph.DataSource.HorizontalViewOrigin = 0;
|
||||
|
||||
findPointsForPage(pagePosition, out start, out end); // get the page edges
|
||||
graph.DataSource.ClearCategory("Player 2"); // clear the cateogry
|
||||
|
||||
graph.DataSource.HorizontalViewSize = targetPoints > mData.Count ? mData.Count : targetPoints;
|
||||
|
||||
if (DownSampleToPoints <= 0)
|
||||
LoadWithoutDownSampling(start, end);
|
||||
else
|
||||
LoadWithDownSampling(start, end);
|
||||
graph.DataSource.EndBatch();
|
||||
graph.HorizontalScrolling = pagePosition;
|
||||
}
|
||||
currentPagePosition = pagePosition;
|
||||
}
|
||||
public void SetData(List<DoubleVector2> data)
|
||||
{
|
||||
if (data == null)
|
||||
data = new List<DoubleVector2>(); // set up an empty list instead of null
|
||||
if (VerifySorted(data) == false)
|
||||
{
|
||||
Debug.LogWarning("The data used with large data feed must be sorted acoording to the x value, aborting operation");
|
||||
return;
|
||||
}
|
||||
mData = data;
|
||||
LoadPage(currentPagePosition); // load the page at position 0
|
||||
}
|
||||
|
||||
public void SetDataSource(double[] data)
|
||||
{
|
||||
graph = GetComponent<GraphChartBase>();
|
||||
List<DoubleVector2> source = new List<DoubleVector2>();
|
||||
|
||||
for (int i = 0; i < data.Length; i++) // initialize with random data
|
||||
{
|
||||
source.Add(new DoubleVector2(i, data[i]));
|
||||
}
|
||||
SetData(source);
|
||||
}
|
||||
|
||||
public int Compare(DoubleVector2 x, DoubleVector2 y)
|
||||
{
|
||||
if (x.x < y.x)
|
||||
return -1;
|
||||
if (x.x > y.x)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
public double pageStartThreshold;
|
||||
public double pageEndThreshold;
|
||||
public void Update()
|
||||
{
|
||||
if (graph != null)
|
||||
{
|
||||
//check the scrolling position of the graph. if we are past the view size , load a new page
|
||||
pageStartThreshold = currentPagePosition - mCurrentPageSizeFactor;
|
||||
pageEndThreshold = currentPagePosition + mCurrentPageSizeFactor - graph.DataSource.HorizontalViewSize;
|
||||
|
||||
if (graph.HorizontalScrolling < pageStartThreshold || graph.HorizontalScrolling > pageEndThreshold || currentZoom >= graph.DataSource.HorizontalViewSize * 2f)
|
||||
{
|
||||
currentZoom = graph.DataSource.HorizontalViewSize;
|
||||
mCurrentPageSizeFactor = PageSizeFactor * 0.9f;
|
||||
LoadPage(graph.HorizontalScrolling);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff4d53c2dc763154da522c9b8cb76877
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,50 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using Assets.Scenes.Ride.Scripts.Model.CyclingModels;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class CompetitionRankingFactory : BaseListFactory
|
||||
{
|
||||
private List<CompetitionRankingSortModel> rankingList {get;set;}
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
cyclingController = FindObjectOfType<CyclingController>();
|
||||
playerController = FindObjectOfType<PlayerController>();
|
||||
nearByItem = Resources.Load<GameObject>("UI/Prefab/Ride/NearbyItem");
|
||||
nearByMajorItem = Resources.Load<GameObject>("UI/Prefab/Ride/NearbyMajorItem");
|
||||
}
|
||||
protected override void CreateList()
|
||||
{
|
||||
//获取实时排名
|
||||
CompetitionModel s = cyclingController.cyclingController as CompetitionModel;
|
||||
var ss = s?.competitionRankingModel;
|
||||
rankingList = ss?.Sorts;
|
||||
|
||||
if (rankingList == null) return;
|
||||
totalPages = rankingList.Count();
|
||||
for (int i = 0; i < rankingList.Count(); i++)
|
||||
{
|
||||
Create(rankingList[i]);
|
||||
}
|
||||
}
|
||||
private void Create(CompetitionRankingSortModel item)
|
||||
{
|
||||
//创建
|
||||
GameObject prefabItem = item.IsSelf ? nearByMajorItem : nearByItem;
|
||||
GameObject newObj = (GameObject)Instantiate(prefabItem, transform);
|
||||
var nearByItemscript = newObj.GetComponent<NearByItemScript>();
|
||||
nearByItemscript.setUserId(item.UserId);
|
||||
nearByItemscript.setName(item.Name);
|
||||
nearByItemscript.setRatio(item.KGWeight+"W/KG");
|
||||
nearByItemscript.setSpeed(item.Speed.ToString() + "KM/H");
|
||||
//nearByItemscript.setHead(item.Headimage);
|
||||
//nearByItemscript.setCountry(cyclingController.GetCountryImageByName(item.));
|
||||
nearByItemscript.setDistance(item.Near.ToString() + "KM");
|
||||
bufferSize++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a572f54bd2296f41a2b47567f33fd64
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,59 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model.CyclingModels;
|
||||
using Assets.Scripts;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class CompetitionResultFactory: MonoBehaviour
|
||||
{
|
||||
CyclingController cyclingController;
|
||||
private void Awake()
|
||||
{
|
||||
cyclingController = FindObjectOfType<CyclingController>();
|
||||
var closeBtn = transform.Find("Close").gameObject;
|
||||
UIManager.AddEvent(closeBtn, UnityEngine.EventSystems.EventTriggerType.PointerClick, Close);
|
||||
}
|
||||
|
||||
float time = 1;
|
||||
private void Update()
|
||||
{
|
||||
time -= Time.deltaTime;
|
||||
while (time < 0)
|
||||
{
|
||||
Refresh();
|
||||
time = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
if (cyclingController.cyclingController is CompetitionModel model)
|
||||
{
|
||||
var list = model?.competitionRankingModel?.Results;
|
||||
if (list == null) return;
|
||||
var parent = transform.Find("ScrollView/Viewport/Content");
|
||||
Utils.DestroyChildren(parent);
|
||||
foreach (var item in list)
|
||||
{
|
||||
var finalRankingItem = Instantiate(Resources.Load<GameObject>("UI/Prefab/Match/FinalRankingItem"), parent);
|
||||
var finalRankingItemScript = finalRankingItem.GetComponent<FinalRankingItemScript>();
|
||||
finalRankingItemScript.setRanking(item.Index.ToString());
|
||||
finalRankingItemScript.setHeartRate(item.HeartRate.ToString("f0"));
|
||||
finalRankingItemScript.setName(item.Name);
|
||||
finalRankingItemScript.setPower(item.Power.ToString());
|
||||
finalRankingItemScript.setRatio(item.WeightKg.ToString("f2"));
|
||||
finalRankingItemScript.setTimer(item.TripTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Close(BaseEventData baseEventData)
|
||||
{
|
||||
this.gameObject.SetActive(false);
|
||||
this.Destroy();
|
||||
SceneManager.LoadScene("MainScene");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7fed0d77ca8dce4a85ed6f9a848355d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,125 @@
|
||||
using UnityEngine;
|
||||
using DG.Tweening;
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using UnityEngine.EventSystems;
|
||||
using Assets.Scenes.Ride.Scripts.Model.CyclingModels;
|
||||
using UnityEngine.UI;
|
||||
using Assets.Scripts;
|
||||
using Assets.Scripts.Apis;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class CompetitionUIManager : BaseUIManager
|
||||
{
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
}
|
||||
GameObject countDownPanel;
|
||||
Text title;
|
||||
Text timer;
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
//创建倒计时面板
|
||||
countDownPanel = Instantiate(Resources.Load<GameObject>("UI/Prefab/Match/CountDownPanel"), transform.Find("Panel"));
|
||||
title = countDownPanel.transform.Find("Title").GetComponent<Text>();
|
||||
timer = countDownPanel.transform.Find("Timer").GetComponent<Text>();
|
||||
countDownPanel.SetActive(false);
|
||||
ShowCurrentRanking();
|
||||
|
||||
}
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
CountDown();
|
||||
}
|
||||
|
||||
//开始游戏触发事件
|
||||
public void StartRide(BaseEventData baseEventData)
|
||||
{
|
||||
this.StartRide();
|
||||
}
|
||||
CompetitionModel competitionModel;
|
||||
bool canStart = false;
|
||||
//开始骑行-加个5秒钟倒计时
|
||||
public override void StartRide()
|
||||
{
|
||||
competitionModel = mainController.cyclingController as CompetitionModel;
|
||||
}
|
||||
|
||||
private void CountDown()
|
||||
{
|
||||
count = competitionModel?.StartCountdown()??0;
|
||||
canStart = competitionModel?.CanStart()??false;
|
||||
//比赛开始前倒计时
|
||||
if (count >= 0)
|
||||
{
|
||||
//显示倒计时面板信息
|
||||
showCountDown(count, "Get ready!");
|
||||
}
|
||||
//比赛开始
|
||||
if (count<=0 && canStart)
|
||||
{
|
||||
mainController.SetStart();
|
||||
countDownPanel.SetActive(false);
|
||||
}
|
||||
//比赛进行中
|
||||
if (competitionModel != null)
|
||||
{
|
||||
//显示结果
|
||||
if (competitionModel.mapCompetition?.HasRecord ?? false)
|
||||
{
|
||||
ShowResultList();
|
||||
}
|
||||
var s = competitionModel?.EndCountDown();
|
||||
//显示关门时间
|
||||
if (s.Value.Item2)
|
||||
{
|
||||
//显示倒计时面板信息
|
||||
showCountDown(s.Value.Item1, "remaining");
|
||||
if (s.Value.Item1 <= 0)
|
||||
{
|
||||
//自动保存,游戏设置结束
|
||||
base.SaveRide(null);
|
||||
}
|
||||
}
|
||||
//显示当前比赛进行多长时间了
|
||||
timerTxt.text = competitionModel.ShowTime;
|
||||
}
|
||||
}
|
||||
|
||||
private void showCountDown(int count,string text)
|
||||
{
|
||||
countDownPanel.SetActive(true);
|
||||
title.text = text;
|
||||
timer.text = Helper.FormatTicks(count);
|
||||
}
|
||||
|
||||
public override void ContinueRide()
|
||||
{
|
||||
MapCompetitionApi s = new MapCompetitionApi();
|
||||
_ = s.ApplyMapCompetition(App.CompetionId);
|
||||
mainController.SetCyclingModel(CyclingModel.Competition);
|
||||
}
|
||||
public override void PauseRide(BaseEventData baseEventData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//实时显示当前比赛排名
|
||||
GameObject competitionRankingList;
|
||||
public void ShowCurrentRanking()
|
||||
{
|
||||
competitionRankingList = Instantiate(Resources.Load<GameObject>("UI/Prefab/Match/CompetitionRankingPanel"), transform.Find("Panel"));
|
||||
}
|
||||
GameObject competitionResultPanel;
|
||||
//实时刷新显示比赛结果
|
||||
public void ShowResultList()
|
||||
{
|
||||
if (competitionResultPanel == null)
|
||||
{
|
||||
competitionResultPanel = Instantiate(Resources.Load<GameObject>("UI/Prefab/Match/CompetitionResultPanel"), transform.Find("Panel"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ef2d2135dbfedc418fd2a7a18a0a254
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,703 @@
|
||||
using Assets.Scripts.Apis;
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Networking;
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using Assets.Scenes.Ride.Scripts.Model.CyclingModels;
|
||||
using Assets.Scenes.Ride.Scripts;
|
||||
using Mapbox.Unity.Map;
|
||||
using UnityEngine;
|
||||
using GeoJSON.Net.Geometry;
|
||||
using TurfCS;
|
||||
using Mapbox.Utils;
|
||||
using Assets.Scripts;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Events;
|
||||
using Assets.Scenes.Ride.Scripts.Model.RiderModels;
|
||||
using System.IO;
|
||||
|
||||
public class CyclingController : DeviceServiceMonoBase
|
||||
{
|
||||
public AbstractMap map;
|
||||
public GameObject player;
|
||||
public GameObject UIObject;
|
||||
public RouteResultParam selectParamModel;
|
||||
public RouteResult routeResult;
|
||||
|
||||
public Dictionary<int, SeletedPlayerScript> selectPlayerDic { set; get; } = new Dictionary<int, SeletedPlayerScript>();
|
||||
|
||||
public int preticks;
|
||||
|
||||
#region 参数
|
||||
private MapRoute mapRoute;//当前路书数据
|
||||
private MapDataModel mapData;//当前路书数据
|
||||
private Route route;//当前路书综合数据
|
||||
public List<MapRouteRanking> mapRouteRankingList { get; set; }
|
||||
private Vector2d coordiantes;//当前地图中心
|
||||
|
||||
public bool isStart;//当前游戏是否开始
|
||||
public CyclingModel cyclingModel;//当前骑行模式
|
||||
public BaseCycling cyclingController { get; set; }
|
||||
private int routeId;
|
||||
private int competitionId;
|
||||
|
||||
private MapApi mapApi;
|
||||
public DateTime startTime;
|
||||
public DateTime endTime;
|
||||
public bool isQuit;
|
||||
public bool isPause;
|
||||
#endregion
|
||||
GameObject loadingcanvas;
|
||||
LoadingController loadingController;
|
||||
private async Task Login()
|
||||
{
|
||||
var result = await new UserApi().Login("15261826280", "123456", "");
|
||||
App.CurrentUser = result.data;
|
||||
}
|
||||
GameObject miniMap;
|
||||
GameObject resultPanel;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
#if UNITY_EDITOR
|
||||
if (App.CurrentUser == null)
|
||||
{
|
||||
Login();
|
||||
}
|
||||
#endif
|
||||
//获取路书信息
|
||||
mapApi = ConfigHelper.mapApi;
|
||||
routeId = App.RouteIdParam > 0? App.RouteIdParam : 2633;
|
||||
//mapRoute = mapApi.GetById(routeId).data;
|
||||
//miniMap = transform.Find("MiniMap").gameObject;//小地图
|
||||
resultPanel = transform.Find("SingleUI/Panel/ResultPanel").gameObject;
|
||||
competitionId = App.CompetionId;
|
||||
//App.CompetionId = 0;//清空比赛参数
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
App.TextureCache.Clear();
|
||||
}
|
||||
Transform target;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
UIManager.Instance.MainPanel = this.transform.Find("SingleUI/Panel").GetComponent<PFUIPanel>();
|
||||
UIManager.Instance.ModalsPanel = this.transform.Find("SingleUI/ModalPanel").GetComponent<PFUIPanel>();
|
||||
onlineUserPrefab = Resources.Load<GameObject>("UI/Prefab/Ride/OnlinePlayer");
|
||||
miniMapPlayerPrefab = Resources.Load<GameObject>("UI/Prefab/Ride/MiniMapPlayer");
|
||||
target = transform.Find("Target");
|
||||
miniMap = transform.Find("MiniMap").gameObject;//小地图
|
||||
//进入倒计时
|
||||
singleUIManager = UIObject.GetComponent<BaseUIManager>();
|
||||
TrailRenderer trail = player.GetComponent<TrailRenderer>();
|
||||
trail.Clear();
|
||||
playerController = player.GetComponent<PlayerController>();
|
||||
currentPlayer = playerController;//当前选中用户
|
||||
loadingController = FindObjectOfType<LoadingController>();
|
||||
loadingController.InjectController(this);
|
||||
//进入比赛
|
||||
if (competitionId > 0)
|
||||
{
|
||||
StartCoroutine(InitRace());
|
||||
return;
|
||||
}
|
||||
//进入单人骑行
|
||||
if (routeId > 0)
|
||||
{
|
||||
StartCoroutine(Init());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator Init()
|
||||
{
|
||||
yield return new WaitForSeconds(1);
|
||||
mapRoute = mapApi.GetById(routeId).data;
|
||||
loadingController.Init(mapRoute);//初始化loading页面
|
||||
loadingController.AddProcess(10);
|
||||
InitData();//初始化数据
|
||||
InitGameObject();//初始化场景
|
||||
MapUDPService.Init();//初始化TCP
|
||||
loadingController.AddProcess(10);
|
||||
}
|
||||
//初始比赛
|
||||
private IEnumerator InitRace()
|
||||
{
|
||||
yield return new WaitForSeconds(1);
|
||||
mapRoute = mapApi.GetById(routeId).data;
|
||||
loadingController.Init(mapRoute);//初始化loading页面
|
||||
loadingController.AddProcess(10);
|
||||
InitRaceData();//初始化比赛数据
|
||||
InitRaceGameObject();//初始化比赛场景
|
||||
MapUDPService.Init();//初始化比赛TCP
|
||||
loadingController.AddProcess(10);
|
||||
}
|
||||
|
||||
//初始化数据
|
||||
private void InitData()
|
||||
{
|
||||
mapData = mapApi.GetData(routeId);//获取路书地理数据
|
||||
route = new Route(mapData, mapRoute);
|
||||
loadingController.AddProcess(10);
|
||||
#region 其他场景传参处理
|
||||
//骑行结果
|
||||
if (App.routeResult != null )
|
||||
{
|
||||
routeResult = App.routeResult;
|
||||
selectParamModel = App.routeResult.ContinueCyclingParam;//继续骑行
|
||||
preticks = App.routeResult.Ticks;
|
||||
}
|
||||
|
||||
if (selectParamModel == null)
|
||||
{
|
||||
selectParamModel = new RouteResultParam
|
||||
{
|
||||
CompetitionId = 0,
|
||||
ContinueIndex = 0,
|
||||
ContinueMark = "",
|
||||
GlobalContinue = false,
|
||||
EndDistance = 0,
|
||||
RankingsId = new List<string>(),
|
||||
OnlineUserId = 0,
|
||||
RouteId = App.RouteIdParam
|
||||
};
|
||||
}
|
||||
|
||||
App.routeResult = null;
|
||||
|
||||
#endregion
|
||||
//异步请求mapbox画出当前路书路线图
|
||||
loadingController.DrawMapRoute(mapData);
|
||||
//计算上次骑行距离调整地图中心点
|
||||
double endDistance = selectParamModel.EndDistance;
|
||||
coordiantes = Along(endDistance);
|
||||
loadingController.AddProcess(10);
|
||||
//查询排行榜
|
||||
var list = mapApi.GetRouteRanking(App.RouteIdParam, "1", 0, 10, "");
|
||||
if (list.result)
|
||||
{
|
||||
loadingController.CreateRankingList(list.data.list);
|
||||
loadingController.AddProcess(10);
|
||||
}
|
||||
var shaowList = mapApi.GetShadowList(App.RouteIdParam, "", 0, 10);
|
||||
if (shaowList.result)
|
||||
{
|
||||
mapRouteRankingList = shaowList.data.list;
|
||||
}
|
||||
}
|
||||
|
||||
private MapCompetition competition;
|
||||
private void InitRaceData()
|
||||
{
|
||||
mapData = mapApi.GetData(routeId);//获取路书地理数据
|
||||
route = new Route(mapData, mapRoute);
|
||||
loadingController.AddProcess(10);
|
||||
#region 其他场景传参处理
|
||||
MapCompetitionApi mapCompetitionApi = new MapCompetitionApi();
|
||||
competition = mapCompetitionApi.GetById(competitionId).data;
|
||||
|
||||
selectParamModel = new RouteResultParam
|
||||
{
|
||||
CompetitionId = competitionId,
|
||||
ContinueIndex = 0,
|
||||
ContinueMark = "",
|
||||
GlobalContinue = false,
|
||||
EndDistance = 0,
|
||||
RankingsId = new List<string>(),
|
||||
OnlineUserId = 0,
|
||||
RouteId = App.RouteIdParam
|
||||
};
|
||||
|
||||
#endregion
|
||||
//异步请求mapbox画出当前路书路线图
|
||||
loadingController.DrawMapRoute(mapData);
|
||||
//计算上次骑行距离调整地图中心点
|
||||
double endDistance = selectParamModel.EndDistance;
|
||||
coordiantes = Along(endDistance);
|
||||
loadingController.AddProcess(10);
|
||||
#region 查询排行榜
|
||||
var list = mapApi.GetRouteRanking(App.RouteIdParam, "1", 0, 10, "");
|
||||
if (list.result)
|
||||
{
|
||||
loadingController.CreateRankingList(list.data.list);
|
||||
loadingController.AddProcess(10);
|
||||
}
|
||||
var shaowList = mapApi.GetShadowList(App.RouteIdParam, "", 0, 10);
|
||||
if (shaowList.result)
|
||||
{
|
||||
mapRouteRankingList = shaowList.data.list;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
private Vector3 mapPos = Vector3.zero;
|
||||
//加载人物和地图以及UI界面
|
||||
private void InitGameObject()
|
||||
{
|
||||
map.gameObject.SetActive(true);
|
||||
player.SetActive(true);
|
||||
UIObject.SetActive(true);
|
||||
singleUIManager = UIObject.AddComponent<SingleUIManager>();
|
||||
miniMap.SetActive(true);
|
||||
map.OnTileFinished += Map_OnTileFinished;
|
||||
mapPos = map.transform.position;
|
||||
}
|
||||
|
||||
private void InitRaceGameObject()
|
||||
{
|
||||
map.gameObject.SetActive(true);
|
||||
player.SetActive(true);
|
||||
UIObject.SetActive(true);
|
||||
singleUIManager = UIObject.AddComponent<CompetitionUIManager>();
|
||||
miniMap.SetActive(true);
|
||||
map.OnTileFinished += Map_OnTileFinished;
|
||||
mapPos = map.transform.position;
|
||||
//SetCyclingModel(CyclingModel.Competition);
|
||||
}
|
||||
|
||||
//private void Map_OnTileFinished(Mapbox.Unity.MeshGeneration.Data.UnityTile obj)
|
||||
//{
|
||||
// var playerController = player.GetComponent<PlayerController>();
|
||||
// player.transform.position = map.GeoToWorldPosition(playerController.Currentlatlong);
|
||||
//}
|
||||
|
||||
//设置骑行模式
|
||||
public void SetCyclingModel(CyclingModel mode)
|
||||
{
|
||||
this.cyclingModel = mode;
|
||||
switch (cyclingModel)
|
||||
{
|
||||
case CyclingModel.Single:
|
||||
cyclingController = new SingleModel(route, selectParamModel);
|
||||
break;
|
||||
case CyclingModel.Review:
|
||||
cyclingController = new ReviewModel(route, selectParamModel);
|
||||
break;
|
||||
//TODO:比赛模式
|
||||
case CyclingModel.Competition:
|
||||
cyclingController = new CompetitionModel(route, selectParamModel, currentPlayer);
|
||||
break;
|
||||
}
|
||||
GameStart();
|
||||
InitPlayer();//初始化人物方向等
|
||||
}
|
||||
PlayerController playerController;
|
||||
public AbstractPlayer currentPlayer;
|
||||
//初始化人物位置角度
|
||||
private void InitPlayer()
|
||||
{
|
||||
lockView = true;
|
||||
|
||||
Vector2d lastLatLon = Along(recorderData.EndDistance);
|
||||
Vector3 currentPos = map.GeoToWorldPosition(lastLatLon);
|
||||
currentPos.y += 1f;
|
||||
player.transform.position = currentPos;
|
||||
playerController.currentPos = currentPos;
|
||||
|
||||
Vector2d nextLatLon = Along(recorderData.EndDistance + 0.1);
|
||||
//设定人物方向
|
||||
var s = map.GeoToWorldPosition(lastLatLon);
|
||||
var e = map.GeoToWorldPosition(nextLatLon);
|
||||
Quaternion neededRotation = Quaternion.LookRotation(s - e);
|
||||
player.transform.rotation = Quaternion.Euler(0, neededRotation.eulerAngles.y, 0);
|
||||
playerController.currentRotation = neededRotation;
|
||||
//初始化海拔图头像位置
|
||||
var index = GetCurrentIndex(recorderData.EndDistance);
|
||||
playerController.InitGraph(index);
|
||||
}
|
||||
//SingleUIManager singleUIManager;
|
||||
BaseUIManager singleUIManager;
|
||||
public void GameStart()
|
||||
{
|
||||
singleUIManager.StartRide();
|
||||
}
|
||||
|
||||
public void GoContinueRide()
|
||||
{
|
||||
singleUIManager.ContinueRide();
|
||||
}
|
||||
|
||||
#region TCP相关
|
||||
|
||||
public void TcpHandler()
|
||||
{
|
||||
if (cyclingController != null)
|
||||
{
|
||||
//tcp数据传输
|
||||
cyclingController.Run(null);
|
||||
//在线人物或比赛人物渲染
|
||||
ShowOnlineUsers();
|
||||
}
|
||||
}
|
||||
|
||||
List<OnlinePlayerController> otherList = new List<OnlinePlayerController>();
|
||||
GameObject onlineUserPrefab;
|
||||
GameObject miniMapPlayerPrefab;
|
||||
|
||||
int messageIndex = 0;
|
||||
private void ShowOnlineUsers()
|
||||
{
|
||||
var onlineRiders = cyclingController.riders;
|
||||
var currentOnlineUserList = FindObjectsOfType<OnlinePlayerController>();
|
||||
//新增或者更新
|
||||
foreach (var item in onlineRiders)
|
||||
{
|
||||
var onlineRider = item as OnlineRiderModel;
|
||||
var currentUser = currentOnlineUserList.Where(c => c.UserId == item.UserId).FirstOrDefault();
|
||||
var onlineDistance = onlineRider.EndDistance - onlineRider.PreDistance;
|
||||
var onlineTotalDistance = onlineRider.EndDistance;
|
||||
var index = GetCurrentIndex(onlineTotalDistance);
|
||||
|
||||
if (currentUser == null)
|
||||
{
|
||||
//大地图人物
|
||||
GameObject otherPlayerObj = (GameObject)Instantiate(onlineUserPrefab, transform);
|
||||
otherPlayerObj.transform.position = map.GeoToWorldPosition(Along(onlineTotalDistance));
|
||||
var onlinePlayerController = otherPlayerObj.GetComponent<OnlinePlayerController>();
|
||||
otherList.Add(onlinePlayerController);
|
||||
|
||||
onlinePlayerController.UserId = onlineRider.UserId;
|
||||
|
||||
onlinePlayerController.SetDataSource(onlineTotalDistance, onlineDistance, onlineRider.NickName, onlineRider.WeightKg, index);
|
||||
onlinePlayerController.SetHead(onlineRider.WxHeadImg);
|
||||
//小地图人物
|
||||
GameObject miniPlayer = (GameObject)Instantiate(miniMapPlayerPrefab, transform);
|
||||
var miniController = miniPlayer.GetComponent<MiniMapPlayerController>();
|
||||
miniController.SetController(onlinePlayerController);
|
||||
//发消息xx进入路书
|
||||
if(messageIndex > 0)
|
||||
EventQueueSystem.QueueEvent(new JoinMessageEvent(onlineRider.NickName, onlineRider.WxHeadImg));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
currentUser.SetDataSource(onlineTotalDistance, onlineDistance, onlineRider.NickName, onlineRider.WeightKg, index);
|
||||
}
|
||||
}
|
||||
if(onlineRiders.Count > 0)
|
||||
messageIndex++;
|
||||
//移除
|
||||
foreach (var item in currentOnlineUserList)
|
||||
{
|
||||
var currentItem = onlineRiders.Where(c => c.UserId == item.UserId).FirstOrDefault();
|
||||
if (currentItem == null)
|
||||
{
|
||||
item.RemoveSelf();
|
||||
}
|
||||
var s = playerController.TotalDistance - item.TotalDistance;
|
||||
}
|
||||
//显示面板信息
|
||||
var others = FindObjectsOfType<AbstractPlayer>();
|
||||
foreach (var item in others)
|
||||
{
|
||||
item.IsShowInfo = false;
|
||||
}
|
||||
var frontPlayer = others.Where(c => c.TotalDistance - playerController.TotalDistance < 0.25 && c.TotalDistance - playerController.TotalDistance >= 0 && !(c is PlayerController)).OrderBy(c=>c.TotalDistance).FirstOrDefault();
|
||||
var bakePlayer = others.Where(c => c.TotalDistance - playerController.TotalDistance >-0.25 && c.TotalDistance - playerController.TotalDistance < 0 && !(c is PlayerController)).OrderByDescending(c=>c.TotalDistance).FirstOrDefault();
|
||||
if(frontPlayer != null)
|
||||
frontPlayer.IsShowInfo = true;
|
||||
if (bakePlayer != null)
|
||||
bakePlayer.IsShowInfo = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void SetUIManager(PFUIPanel mainPanel, PFUIPanel model)
|
||||
{
|
||||
UIManager.Instance.MainPanel = mainPanel;//this.transform.Find("SingleUI/Panel").GetComponent<PFUIPanel>();
|
||||
UIManager.Instance.ModalsPanel = model;// this.transform.Find("SingleUI/ModalPanel").GetComponent<PFUIPanel>();
|
||||
}
|
||||
|
||||
public void ReSetUIManager()
|
||||
{
|
||||
UIManager.Instance.MainPanel = this.transform.Find("SingleUI/Panel").GetComponent<PFUIPanel>();
|
||||
UIManager.Instance.ModalsPanel = this.transform.Find("SingleUI/ModalPanel").GetComponent<PFUIPanel>();
|
||||
}
|
||||
|
||||
public void AddEvent(GameObject sender, EventTriggerType eventType, UnityAction<BaseEventData> unityAction)
|
||||
{
|
||||
UIManager.AddEvent(sender, eventType, unityAction);
|
||||
}
|
||||
public void ShowDevice(PFUIPanel pFUIPanel)
|
||||
{
|
||||
UIManager.Show(UIManager.Instance.DevicePanel, pFUIPanel);
|
||||
}
|
||||
|
||||
public Texture GetCountryImageByCode(string code)
|
||||
{
|
||||
return UIManager.Instance.loginRegOptions.GetCountryImage(code);
|
||||
}
|
||||
|
||||
public Texture GetCountryImageByName(string name)
|
||||
{
|
||||
return UIManager.Instance.loginRegOptions.GetCountryImageByName(name);
|
||||
}
|
||||
|
||||
#region 视角切换
|
||||
|
||||
public AbstractMap map3d;
|
||||
public bool Is3dView;
|
||||
public void ChangeMapImageStyle(GameObject arrowGameObj)
|
||||
{
|
||||
var playerController = player.GetComponent<PlayerController>();
|
||||
var trailRenderer = player.GetComponent<TrailRenderer>();
|
||||
trailRenderer.time = 0;
|
||||
StartCoroutine(EnableTrailRenderer(trailRenderer));
|
||||
if (!Is3dView)
|
||||
{
|
||||
//地图属性变更
|
||||
map.Terrain.ExaggerationFactor = 1.5f;
|
||||
map.Terrain.SetElevationType(ElevationLayerType.TerrainWithElevation);
|
||||
map.ImageLayer.SetLayerSource(ImagerySourceType.Custom);
|
||||
map.SetCenterLatitudeLongitude(playerController.Currentlatlong);
|
||||
map.transform.position = mapPos;
|
||||
//map3d.gameObject.SetActive(true);
|
||||
//map.gameObject.SetActive(false);
|
||||
//人物属性变更
|
||||
var pos = map.GeoToWorldPosition(playerController.Currentlatlong);
|
||||
playerController.currentPos = pos;
|
||||
target.position = pos;
|
||||
player.transform.localScale = new Vector3(3f, 3f, 3f);
|
||||
player.transform.position = pos;
|
||||
|
||||
arrowGameObj.SetActive(false);
|
||||
Is3dView = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//地图属性变更
|
||||
map.ImageLayer.SetLayerSource(ImagerySourceType.JuzeTest);
|
||||
map.Terrain.ExaggerationFactor = 0f;
|
||||
map.Terrain.SetElevationType(ElevationLayerType.FlatTerrain);
|
||||
map.SetCenterLatitudeLongitude(playerController.Currentlatlong);
|
||||
map.transform.position = Vector3.zero;
|
||||
//map.gameObject.SetActive(true);
|
||||
//map3d.gameObject.SetActive(false);
|
||||
//人物属性变更
|
||||
var pos = map.GeoToWorldPosition(playerController.Currentlatlong);
|
||||
player.transform.position = pos;
|
||||
player.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
|
||||
target.position = pos;
|
||||
//playerController.currentPos = Vector3.zero;
|
||||
arrowGameObj.SetActive(true);
|
||||
Is3dView = false;
|
||||
}
|
||||
}
|
||||
private bool lockView = false;
|
||||
private void Map_OnTileFinished(Mapbox.Unity.MeshGeneration.Data.UnityTile obj)
|
||||
{
|
||||
if (!lockView) {
|
||||
|
||||
var playerController = player.GetComponent<PlayerController>();
|
||||
player.transform.localScale = new Vector3(3f, 3f, 3f);
|
||||
var locations = playerController.Currentlatlong == null ? playerController.Currentlatlong : new Vector2d(mapData.List[0].Point[0], mapData.List[0].Point[1]);
|
||||
player.transform.position = map.GeoToWorldPosition(locations);
|
||||
mapPos = map.transform.position;
|
||||
if (recorderData != null)
|
||||
{
|
||||
var lastLatLon = Along(recorderData.EndDistance);
|
||||
var nextLatLon = Along(recorderData.EndDistance+0.1);
|
||||
player.transform.position = map.GeoToWorldPosition(lastLatLon);
|
||||
//设定人物方向
|
||||
var s = map.GeoToWorldPosition(lastLatLon);
|
||||
var e = map.GeoToWorldPosition(nextLatLon);
|
||||
Quaternion neededRotation = Quaternion.LookRotation(s - e);
|
||||
player.transform.rotation = Quaternion.Euler(0, neededRotation.eulerAngles.y, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator EnableTrailRenderer(TrailRenderer trailRenderer)
|
||||
{
|
||||
yield return new WaitForSeconds(2f);
|
||||
trailRenderer.Clear();
|
||||
trailRenderer.time = 30;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 游戏状态控制
|
||||
//开始骑行
|
||||
public void SetStart()
|
||||
{
|
||||
if (!isPause || DateTime.MinValue == startTime)
|
||||
{
|
||||
isStart = true;
|
||||
startTime = UIManager.Now.GetDateTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetContinue();
|
||||
}
|
||||
}
|
||||
//继续骑行
|
||||
public void SetContinue()
|
||||
{
|
||||
isStart = true;
|
||||
isPause = false;
|
||||
}
|
||||
//暂停骑行
|
||||
public void SetPause()
|
||||
{
|
||||
isStart = false;
|
||||
isPause = true;
|
||||
}
|
||||
//退出或者完成骑行
|
||||
public void SetQuit()
|
||||
{
|
||||
isStart = false;
|
||||
isQuit = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 数据处理
|
||||
/// <summary>
|
||||
/// 当前骑行数据的记录器
|
||||
/// </summary>
|
||||
private RecorderDataModel recorderData
|
||||
{
|
||||
get
|
||||
{
|
||||
return cyclingController?.recorderData;
|
||||
}
|
||||
}
|
||||
public Route GetRoute()
|
||||
{
|
||||
return route;
|
||||
}
|
||||
|
||||
public MapDataModel GetMapData()
|
||||
{
|
||||
return mapData;
|
||||
}
|
||||
|
||||
public void Save(double totalDistance)
|
||||
{
|
||||
isQuit = true;
|
||||
isStart = false;
|
||||
|
||||
string recordId = Guid.NewGuid().ToString();
|
||||
//var path = Helper.GetDataDir("MapWorkoutRecords/"+ recordId);
|
||||
var path = PFConstants.MapWorkoutRecordFolder + "/" + recordId;
|
||||
Helper.CreateDirectoryIfNotExsit(path);
|
||||
|
||||
string imageFileName = path +"/"+ Guid.NewGuid().ToString() + ".png";
|
||||
CaptureCamera(Camera.main, new Rect(Screen.width * 0f, Screen.height * 0f, Screen.width * 0.5f, Screen.height * 0.5f), imageFileName);
|
||||
|
||||
cyclingController.recorderData.StartTime = startTime;
|
||||
cyclingController.recorderData.EndTime = UIManager.Now.GetDateTime();
|
||||
cyclingController.recorderData.IsCompleted = totalDistance == mapData.TotalDistance;
|
||||
cyclingController.recorderData.EndDistance = totalDistance;
|
||||
cyclingController.recorderData.AntModelId = AntModelId;
|
||||
cyclingController.recorderData.ManufacturerId = ManufacturerId;
|
||||
cyclingController.recorderData.ManufacturerName = ManufacturerName;
|
||||
cyclingController.recorderData.DeviceNumber = DeviceNumber;
|
||||
//显示骑行结果
|
||||
resultPanel.SetActive(true);
|
||||
var rs = resultPanel.GetComponent<ResultPanelScript>();
|
||||
rs.InjectController(this);
|
||||
rs.SetDataSource(cyclingController.recorderData);
|
||||
cyclingController.recorderData.SaveWithLocalRecordAysnc(cyclingModel, selectParamModel, imageFileName, recordId, path);
|
||||
}
|
||||
|
||||
protected void CaptureCamera(Camera camera, Rect rect,string fileName)
|
||||
{
|
||||
// 创建一个RenderTexture对象
|
||||
RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 0);
|
||||
// 临时设置相关相机的targetTexture为rt, 并手动渲染相关相机
|
||||
camera.targetTexture = rt;
|
||||
camera.Render();
|
||||
//ps: --- 如果这样加上第二个相机,可以实现只截图某几个指定的相机一起看到的图像。
|
||||
//ps: camera2.targetTexture = rt;
|
||||
//ps: camera2.Render();
|
||||
//ps: -------------------------------------------------------------------
|
||||
|
||||
// 激活这个rt, 并从中中读取像素。
|
||||
RenderTexture.active = rt;
|
||||
Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
|
||||
screenShot.ReadPixels(rect, 0, 0);// 注:这个时候,它是从RenderTexture.active中读取像素
|
||||
screenShot.Apply();
|
||||
|
||||
// 重置相关参数,以使用camera继续在屏幕上显示
|
||||
camera.targetTexture = null;
|
||||
//ps: camera2.targetTexture = null;
|
||||
RenderTexture.active = null; // JC: added to avoid errors
|
||||
GameObject.Destroy(rt);
|
||||
// 最后将这些纹理数据,成一个图片文件
|
||||
byte[] bytes = screenShot.EncodeToPNG();
|
||||
|
||||
//var path = Helper.GetDataDir("MapWorkoutRecords/images");
|
||||
//string filename = path + "/" + Guid.NewGuid().ToString() + ".png";
|
||||
System.IO.File.WriteAllBytes(fileName, bytes);
|
||||
//Debug.Log(string.Format("截屏了一张照片: {0}", filename));
|
||||
}
|
||||
|
||||
public Vector2d GetCenterCoordinate()
|
||||
{
|
||||
return coordiantes;
|
||||
}
|
||||
|
||||
public int GetCurrentIndex(double endDistance)
|
||||
{
|
||||
int index = 0;
|
||||
var pointList = mapData.List;
|
||||
double sumDistance = 0;
|
||||
|
||||
for (int i = 0; i < pointList.Count; i++)
|
||||
{
|
||||
sumDistance += pointList[i].Distance;
|
||||
if (endDistance * 1000 <= sumDistance)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
index = endDistance >= mapData.TotalDistance ? index + 1 : index;
|
||||
return index;
|
||||
}
|
||||
public Vector2d Along(double endDistance)
|
||||
{
|
||||
if (mapData != null)
|
||||
{
|
||||
var list = mapData.List.Select(p => new GeoJSON.Net.Geometry.GeographicPosition(p.Point[0], p.Point[1]));
|
||||
LineString lineString = new LineString(list);
|
||||
var pt1 = Turf.Along(lineString, endDistance);
|
||||
var ll = ((GeographicPosition)((GeoJSON.Net.Geometry.Point)pt1.Geometry).Coordinates);
|
||||
return new Vector2d(ll.Latitude, ll.Longitude);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Vector2d(0,0);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 海拔图数据
|
||||
/// </summary>
|
||||
public float[] GetRealTimeLineChartData(int index)
|
||||
{
|
||||
List<float> dist = new List<float>();
|
||||
var list = mapData.List.Select(c => (float) c.Elevation ).ToArray();
|
||||
var count = list.Count();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (i > index)
|
||||
{
|
||||
dist.Add(list[i]);
|
||||
}
|
||||
}
|
||||
return dist.ToArray();
|
||||
}
|
||||
|
||||
public float[] GetLineChartData()
|
||||
{
|
||||
var list = mapData.List.Select(c => (float)c.Elevation).ToArray();
|
||||
return list;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 904fddf6d736a004a969cdfa63f14076
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,313 @@
|
||||
using Assets.Scripts.Ble;
|
||||
using Assets.Scripts.Devices;
|
||||
using Assets.Scripts.Devices.Ant;
|
||||
using Assets.Scripts.Devices.Ant.Interfaces;
|
||||
using Assets.Scripts.Devices.Ble;
|
||||
using Assets.Scripts.Scenes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class DeviceServiceMonoBase: BaseScene
|
||||
{
|
||||
public void TrackResistance(double grade)
|
||||
{
|
||||
var device = (CurrentTrainer as ITrainerDevice);
|
||||
if (device != null)
|
||||
{
|
||||
device.SetTrackResistance(grade);
|
||||
}
|
||||
}
|
||||
#region 获取设备数据
|
||||
|
||||
public AbstractDevice CurrentTrainer
|
||||
{
|
||||
get {
|
||||
var devices = App.MainDeviceAdapter.GetDevices().Where(d => d.State == DeviceState.Connected && (d.Sensor == SensorType.Trainer));
|
||||
_device = null;//重置设备状态
|
||||
if (devices.Count() > 0)
|
||||
{
|
||||
_device = devices.OrderByDescending(d => d.Sensor == SensorType.Trainer).First();
|
||||
var RiderWeight = (_device as IRequiresRiderWeight).RiderWeight;
|
||||
if (RiderWeight == 0)
|
||||
{
|
||||
(_device as IRequiresRiderWeight).RiderWeight = App.CurrentUser.Weight;
|
||||
}
|
||||
if (_device.Network == NetworkType.ANT)
|
||||
{
|
||||
var antDevice = _device as AbstractAntDevice;
|
||||
ManufacturerId = antDevice.ManufacturerId;
|
||||
AntModelId = antDevice.AntModelId;
|
||||
DeviceNumber = $"{ antDevice.DeviceNumber },{ antDevice.DeviceType}";
|
||||
}
|
||||
else
|
||||
{
|
||||
var bleDevice = _device as BleDevice;
|
||||
DeviceNumber = $"{ Helper.FormateMacAddress(bleDevice.Address) },{ ServiceUuids.GetBySensor(bleDevice.Sensor) }";
|
||||
ManufacturerName = bleDevice.Name + "," + bleDevice.Network + "," + bleDevice.Sensor;
|
||||
}
|
||||
}
|
||||
|
||||
return _device;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新速度(KM/H)
|
||||
///
|
||||
/// </summary>
|
||||
public double UpDateSpeed()
|
||||
{
|
||||
return SpeedDevice == null ? 0 : SpeedDevice.Speed;
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新心率
|
||||
/// </summary>
|
||||
/// <param name="heart"></param>
|
||||
public int? UpDateHeart()
|
||||
{
|
||||
if (HeartDevice != null)
|
||||
{
|
||||
return HeartDevice.HeartRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新功率
|
||||
/// </summary>
|
||||
public double UpdatePower()
|
||||
{
|
||||
var t = PowerDevice == null ? 0 : PowerDevice.Power;
|
||||
return t;
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新踏频
|
||||
/// </summary>
|
||||
/// <param name="cadence"></param>
|
||||
public int UpdateCadence()
|
||||
{
|
||||
return CadenceDevice == null ? 0 : CadenceDevice.Cadence;
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新距离(KM)
|
||||
/// </summary>
|
||||
/// <param name="distance"></param>
|
||||
public double UpdateDistance(double speed)
|
||||
{
|
||||
return Math.Round(speed / 3600, 5,MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 设备接口
|
||||
|
||||
#region field
|
||||
|
||||
protected AbstractDevice _device;
|
||||
protected AntConnector _antConnector;
|
||||
|
||||
public int? ManufacturerId { get; private set; }
|
||||
public string ManufacturerName { get; private set; }
|
||||
public string DeviceNumber { get; private set; }
|
||||
public int? AntModelId { get; private set; }
|
||||
|
||||
private readonly static System.Collections.Generic.Dictionary<string, string> _routeDataCache = new Dictionary<string, string>();
|
||||
|
||||
#endregion
|
||||
#region 事件
|
||||
|
||||
//用户骑行界面非正常关闭(不清楚有哪些非正常),资源没有释放,导致定时器仍在运作。
|
||||
public static bool baseExit { get; set; } = false;
|
||||
#endregion
|
||||
public bool CheckAnt()
|
||||
{
|
||||
//_antConnector = AntConnector.Instance();
|
||||
var devices = App.MainDeviceAdapter.GetDevices().Where(d => d.State == DeviceState.Connected && (d.Sensor == SensorType.Trainer || d.Sensor == SensorType.Power));
|
||||
if (devices.Count() > 0)
|
||||
{
|
||||
_device = devices.OrderByDescending(d => d.Sensor == SensorType.Trainer).First();
|
||||
if (_device != null && _device is IRequiresRiderWeight)
|
||||
{
|
||||
(_device as IRequiresRiderWeight).RiderWeight = App.CurrentUser.Weight;
|
||||
}
|
||||
if (_device.Network == NetworkType.ANT)
|
||||
{
|
||||
var antDevice = _device as AbstractAntDevice;
|
||||
ManufacturerId = antDevice.ManufacturerId;
|
||||
AntModelId = antDevice.AntModelId;
|
||||
DeviceNumber = $"{ antDevice.DeviceNumber },{ antDevice.DeviceType}";
|
||||
}
|
||||
else
|
||||
{
|
||||
var bleDevice =_device as BleDevice;
|
||||
DeviceNumber = $"{ bleDevice.Address },{ bleDevice.Sensor }";
|
||||
ManufacturerName = bleDevice.Name + " " + bleDevice.Network + " " + bleDevice.Sensor;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (App.CurrentUser.FTP <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_device == null)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//设备列表
|
||||
///速率设备
|
||||
protected ISpeedDevice SpeedDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
//速度和踏频一体的传感器,里面的速度是不可以读的,只允许读 踏频,切记
|
||||
//if (_antConnector == null)
|
||||
//{
|
||||
// return null;
|
||||
//}
|
||||
var device = App.MainDeviceAdapter.GetDevices().Where(d => d.State == DeviceState.Connected && d is ISpeedDevice).FirstOrDefault();
|
||||
if (device != null)
|
||||
{
|
||||
return (ISpeedDevice)device;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 心率设备
|
||||
/// </summary>
|
||||
protected IHeartRateDevice HeartDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
//if (_antConnector == null)
|
||||
//{
|
||||
// return null;
|
||||
//}
|
||||
var device = App.MainDeviceAdapter.GetDevices().Where(d => d.State == DeviceState.Connected && d is IHeartRateDevice).FirstOrDefault();
|
||||
if (device != null)
|
||||
{
|
||||
return (IHeartRateDevice)device;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 功率设备
|
||||
/// </summary>
|
||||
protected IPowerDevice PowerDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
//if (_antConnector == null)
|
||||
//{
|
||||
// return null;
|
||||
//}
|
||||
var powerDevices = App.MainDeviceAdapter.GetDevices().Where(d => d.State == DeviceState.Connected && d is IPowerDevice).ToList();
|
||||
var power = powerDevices.FirstOrDefault(d => d.Sensor == SensorType.Power);
|
||||
if (power != null)
|
||||
{
|
||||
return (IPowerDevice)power;
|
||||
}
|
||||
|
||||
if (powerDevices.Any())
|
||||
{
|
||||
return (IPowerDevice)powerDevices.FirstOrDefault();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 踏频设备
|
||||
/// </summary>
|
||||
protected ICadenceDevice CadenceDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
//if (_antConnector == null)
|
||||
//{
|
||||
// return null;
|
||||
//}
|
||||
var cadences = App.MainDeviceAdapter.GetDevices().Where(d => d.State == DeviceState.Connected && d is ICadenceDevice).ToList();
|
||||
var cadence = cadences.FirstOrDefault(d => d.Sensor == SensorType.Cadence);
|
||||
if (cadence != null)
|
||||
{
|
||||
return (ICadenceDevice)cadence;
|
||||
}
|
||||
var spdCad = cadences.FirstOrDefault(d => d.Sensor == SensorType.SpeedCadence);
|
||||
if (spdCad != null)
|
||||
{
|
||||
return (ICadenceDevice)spdCad;
|
||||
}
|
||||
|
||||
if (cadences.Any())
|
||||
{
|
||||
return (ICadenceDevice)cadences.FirstOrDefault();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 设备交互
|
||||
|
||||
///// <summary>
|
||||
///// 设置骑行模式和骑行数据
|
||||
///// </summary>
|
||||
///// <param name="model">0自由骑,2阻力模式,3轨道模式</param>
|
||||
///// <param name="data"></param>
|
||||
//public void SetCyClingModelData(string model, double data)
|
||||
//{
|
||||
// if (recorderData == null)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// switch (model)
|
||||
// {
|
||||
// case "0":
|
||||
// recorderData.SendDataMode = SendDataMode.Freedom;
|
||||
// SeedFecWindResistance();
|
||||
// break;
|
||||
// case "1":
|
||||
// break;
|
||||
// case "2":
|
||||
// recorderData.SendDataMode = SendDataMode.Resistance;
|
||||
// SeedFecResistance(data);
|
||||
// //{
|
||||
// // recorderData.SlopeGrade = data;
|
||||
// // TrackResistance(data);
|
||||
// //}
|
||||
// break;
|
||||
// case "3":
|
||||
// recorderData.SendDataMode = SendDataMode.Track;
|
||||
// int index = Route.GetStepIndex(recorderData.EndDistance);
|
||||
// double grade = Route.GetPatchByIndex(index, false, recorderData.EndDistance);
|
||||
// recorderData.SlopeGrade = grade;
|
||||
|
||||
// var grade1 = this._sensitivity / 100D * grade;
|
||||
// //Trace.WriteLine("给设备发的坡度:"+grade, nameof(MapboxController));
|
||||
// TrackResistance(grade1);
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f513d183d5ffc8642a79905a41b074fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class EventDelegate : Singleton<EventDelegate>
|
||||
{
|
||||
public EventQueueSystem.EventDelegate<GameEvent> JoyStickUpHandler;
|
||||
//...其他的全局委托
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 033ce2de076bd6148abe8d18305d9d17
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,147 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class GameEvent { }
|
||||
|
||||
public class EventQueueSystem : MonoSingleton<EventQueueSystem>
|
||||
{
|
||||
public delegate void EventDelegate<T>(T e) where T : GameEvent;
|
||||
|
||||
private delegate void InternalEventDelegate(GameEvent e);
|
||||
|
||||
private Dictionary<Type, InternalEventDelegate> delegates = new Dictionary<Type, InternalEventDelegate>();
|
||||
private Dictionary<Delegate, InternalEventDelegate> delegateLookup = new Dictionary<Delegate, InternalEventDelegate>();
|
||||
private Dictionary<InternalEventDelegate, Delegate> delegateLookOnce = new Dictionary<InternalEventDelegate, Delegate>();
|
||||
|
||||
private Queue eventQueue = new Queue();
|
||||
|
||||
public bool bLimitQueueProcessing = false;
|
||||
public float limitQueueTime = 1f;
|
||||
|
||||
//注册侦听事件(持续)
|
||||
public static void AddListener<T>(EventDelegate<T> del) where T : GameEvent
|
||||
{
|
||||
Instance.AddDelegate(del);
|
||||
}
|
||||
|
||||
//注册侦听事件(一次)
|
||||
public static void AddListenerOnce<T>(EventDelegate<T> del) where T : GameEvent
|
||||
{
|
||||
var result = Instance.AddDelegate(del);
|
||||
if (result != null)
|
||||
Instance.delegateLookOnce[result] = del;
|
||||
}
|
||||
|
||||
//判定侦听事件是否存在
|
||||
public static bool HasListener<T>(EventDelegate<T> del) where T : GameEvent
|
||||
{
|
||||
return Instance.delegateLookup.ContainsKey(del);
|
||||
}
|
||||
|
||||
//移除侦听事件
|
||||
public static void RemoveListener<T>(EventDelegate<T> del) where T : GameEvent
|
||||
{
|
||||
if (Instance == null)
|
||||
return;
|
||||
if (Instance.delegateLookup.TryGetValue(del, out InternalEventDelegate eventDelegate))
|
||||
{
|
||||
if (Instance.delegates.TryGetValue(typeof(T), out InternalEventDelegate temp))
|
||||
{
|
||||
temp -= eventDelegate;
|
||||
if (temp == null)
|
||||
Instance.delegates.Remove(typeof(T));
|
||||
else
|
||||
Instance.delegates[typeof(T)] = temp;
|
||||
}
|
||||
Instance.delegateLookup.Remove(del);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveAll()
|
||||
{
|
||||
if (Instance != null)
|
||||
{
|
||||
Instance.delegates.Clear();
|
||||
Instance.delegateLookup.Clear();
|
||||
Instance.delegateLookOnce.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private InternalEventDelegate AddDelegate<T>(EventDelegate<T> del) where T : GameEvent
|
||||
{
|
||||
if (delegateLookup.ContainsKey(del))
|
||||
return null;
|
||||
void eventDelegate(GameEvent e) => del((T)e);
|
||||
delegateLookup[del] = eventDelegate;
|
||||
|
||||
if (delegates.TryGetValue(typeof(T), out InternalEventDelegate temp))
|
||||
delegates[typeof(T)] = temp += eventDelegate;
|
||||
else
|
||||
delegates[typeof(T)] = eventDelegate;
|
||||
return eventDelegate;
|
||||
}
|
||||
|
||||
//单个事件触发
|
||||
private static void TriggerEvent(GameEvent e)
|
||||
{
|
||||
var type = e.GetType();
|
||||
if (Instance.delegates.TryGetValue(type, out InternalEventDelegate eventDelegate))
|
||||
{
|
||||
eventDelegate.Invoke(e);
|
||||
//移除单一侦听
|
||||
foreach (InternalEventDelegate item in Instance.delegates[type].GetInvocationList())
|
||||
{
|
||||
if (Instance.delegateLookOnce.TryGetValue(item, out Delegate temp))
|
||||
{
|
||||
Instance.delegates[type] -= item;
|
||||
if (Instance.delegates[type] == null)
|
||||
Instance.delegates.Remove(type);
|
||||
Instance.delegateLookup.Remove(temp);
|
||||
Instance.delegateLookOnce.Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//外部调用的推入事件队列接口
|
||||
public static void QueueEvent(GameEvent e)
|
||||
{
|
||||
if (!Instance.delegates.ContainsKey(e.GetType()))
|
||||
return;
|
||||
Instance.eventQueue.Enqueue(e);
|
||||
}
|
||||
float timer = 0.0f;
|
||||
//事件队列触发处理
|
||||
void Update()
|
||||
{
|
||||
//float timer = 0.0f;
|
||||
//while (eventQueue.Count > 0)
|
||||
//{
|
||||
// if (bLimitQueueProcessing)
|
||||
// if (timer > limitQueueTime)
|
||||
// return;
|
||||
// var e = eventQueue.Dequeue() as GameEvent;
|
||||
// TriggerEvent(e);
|
||||
// if (bLimitQueueProcessing)
|
||||
// timer += Time.deltaTime;
|
||||
//}
|
||||
timer += Time.deltaTime;
|
||||
while (timer >= 1 && eventQueue.Count > 0)
|
||||
{
|
||||
var e = eventQueue.Dequeue() as GameEvent;
|
||||
TriggerEvent(e);
|
||||
timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
RemoveAll();
|
||||
eventQueue.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7adca7a71f7c6f4f91c5b09695140af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,89 @@
|
||||
using Assets.Scripts;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class FinalRankingItemScript : MonoBehaviour
|
||||
{
|
||||
private RawImage Head;
|
||||
private RawImage Country;
|
||||
private Text Name;
|
||||
private Text Power;
|
||||
private Text Timer;
|
||||
private Text Ratio;//功体比
|
||||
private Text Ranking;
|
||||
private Text HeartRate;
|
||||
|
||||
private int _userId = 0;
|
||||
public int UserId { get { return _userId; } }
|
||||
private Texture countryTexture;
|
||||
private void Awake()
|
||||
{
|
||||
Head = transform.Find("Head").GetComponent<RawImage>();
|
||||
Country = transform.Find("Country").GetComponent<RawImage>();
|
||||
Name = transform.Find("Name").GetComponent<Text>();
|
||||
HeartRate = transform.Find("Heart").GetComponent<Text>();
|
||||
Power = transform.Find("Power").GetComponent<Text>();
|
||||
Timer = transform.Find("Timer").GetComponent<Text>();
|
||||
Ratio = transform.Find("WKG").GetComponent<Text>();
|
||||
Ranking = transform.Find("Ranking").GetComponent<Text>();
|
||||
countryTexture = Resources.Load<Sprite>("Images/flag_China_Person").texture;
|
||||
}
|
||||
|
||||
public void setRatio(string ratio)
|
||||
{
|
||||
Ratio.text = ratio +"W/KG";
|
||||
}
|
||||
|
||||
public void setHead(string url)
|
||||
{
|
||||
Utils.DisplayImage(Head, url, true);
|
||||
var rect = ((RectTransform)Head.transform).rect;
|
||||
Material material = Instantiate(Resources.Load<Material>("UI/Material/RoundedCornersTextureMaterial"));
|
||||
material.SetVector(Shader.PropertyToID("_WidthHeightRadius"), new Vector4(rect.width, rect.height, rect.height, 0));
|
||||
Head.material = material;
|
||||
}
|
||||
|
||||
public void setCountry(Texture texture)
|
||||
{
|
||||
Country.texture = texture;
|
||||
}
|
||||
public void setName(string name)
|
||||
{
|
||||
Name.text = name;
|
||||
}
|
||||
|
||||
public void setPower(string power)
|
||||
{
|
||||
Power.text = power +"W";
|
||||
|
||||
}
|
||||
public void setTimer(string timer)
|
||||
{
|
||||
Timer.text = timer;
|
||||
}
|
||||
|
||||
public void setRanking(string ranking)
|
||||
{
|
||||
Ranking.text = ranking;
|
||||
}
|
||||
|
||||
public void setHeartRate(string heartRate)
|
||||
{
|
||||
if (!heartRate.Equals("0"))
|
||||
{
|
||||
HeartRate.text = heartRate + "bpm";
|
||||
}
|
||||
else
|
||||
{
|
||||
HeartRate.text = "--bpm";
|
||||
}
|
||||
}
|
||||
|
||||
public void setUserId(int userId)
|
||||
{
|
||||
_userId = userId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e64a5b2fb6d4f3418094195460237d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,163 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
[RequireComponent(typeof(Image))]
|
||||
public class GradientBackGround : MonoBehaviour
|
||||
{
|
||||
public enum GradientType
|
||||
{
|
||||
None,
|
||||
Vertical,
|
||||
VerticalDown,
|
||||
Horizontal,
|
||||
Diagonal
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class GradientColorNode
|
||||
{
|
||||
[Range(0, 1)]
|
||||
public float ratio = 0;
|
||||
public Color color = Color.white;
|
||||
|
||||
public GradientColorNode(float _ratio, Color _color)
|
||||
{
|
||||
ratio = _ratio;
|
||||
color = _color;
|
||||
}
|
||||
}
|
||||
|
||||
private Image bgImage;
|
||||
|
||||
[SerializeField, Header("渐变方式")]
|
||||
private GradientType gradientType = GradientType.Vertical;
|
||||
|
||||
[SerializeField, Header("渐变曲线(0~1)")]
|
||||
private AnimationCurve gradientCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(1, 1));
|
||||
|
||||
[SerializeField, Header("渐变颜色")]
|
||||
private List<GradientColorNode> gradientColorNodeList = new List<GradientColorNode>() { new GradientColorNode(0, Color.white), new GradientColorNode(1, Color.black) };
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
bgImage = GetComponent<Image>();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
SetGradientColor();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
//if (Input.GetKeyDown(KeyCode.Alpha1))
|
||||
//{
|
||||
// gradientType = GradientType.None;
|
||||
// SetGradientColor();
|
||||
//}
|
||||
//if (Input.GetKeyDown(KeyCode.Alpha2))
|
||||
//{
|
||||
// gradientType = GradientType.Vertical;
|
||||
// SetGradientColor();
|
||||
//}
|
||||
//if (Input.GetKeyDown(KeyCode.Alpha3))
|
||||
//{
|
||||
// gradientType = GradientType.Horizontal;
|
||||
// SetGradientColor();
|
||||
//}
|
||||
//if (Input.GetKeyDown(KeyCode.Alpha4))
|
||||
//{
|
||||
// gradientType = GradientType.Diagonal;
|
||||
// SetGradientColor();
|
||||
//}
|
||||
}
|
||||
|
||||
private void SetGradientColor()
|
||||
{
|
||||
//创建Texture2D
|
||||
Vector2Int imageSize = new Vector2Int(Screen.width, Screen.height);
|
||||
Texture2D texture2D = new Texture2D(imageSize.x, imageSize.y);
|
||||
//遍历像素点
|
||||
switch (gradientType)
|
||||
{
|
||||
case GradientType.Vertical:
|
||||
for (int y = 0; y < imageSize.y; y++)
|
||||
{
|
||||
Color pixelColor = GetColorByCurve(1.0f * y / imageSize.y);
|
||||
for (int x = 0; x < imageSize.x; x++)
|
||||
{
|
||||
texture2D.SetPixel(x, y, pixelColor);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GradientType.VerticalDown:
|
||||
for (int y = imageSize.y - 1; y > 0; y--)
|
||||
{
|
||||
Color pixelColor = GetColorByCurve(1.0f * y / imageSize.y);
|
||||
for (int x = imageSize.x - 1; x > 0; x--)
|
||||
{
|
||||
texture2D.SetPixel(x, y, pixelColor);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GradientType.Horizontal:
|
||||
for (int x = 0; x < imageSize.x; x++)
|
||||
{
|
||||
Color pixelColor = GetColorByCurve(1.0f * x / imageSize.x);
|
||||
for (int y = 0; y < imageSize.y; y++)
|
||||
{
|
||||
texture2D.SetPixel(x, y, pixelColor);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GradientType.Diagonal:
|
||||
for (int x = 0; x < imageSize.x; x++)
|
||||
{
|
||||
for (int y = 0; y < imageSize.y; y++)
|
||||
{
|
||||
Color pixelColor = GetColorByCurve(0.5f * x / imageSize.x + 0.5f * y / imageSize.y);
|
||||
texture2D.SetPixel(x, y, pixelColor);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (gradientColorNodeList.Count > 0)
|
||||
{
|
||||
Color pixelColor = gradientColorNodeList[0].color;
|
||||
for (int x = 0; x < imageSize.x; x++)
|
||||
{
|
||||
for (int y = 0; y < imageSize.y; y++)
|
||||
{
|
||||
texture2D.SetPixel(x, y, pixelColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
texture2D.Apply();
|
||||
//创建Sprite
|
||||
Sprite sprite = Sprite.Create(texture2D, new Rect(0, 0, imageSize.x, imageSize.y), new Vector2(0.5f, 0.5f));
|
||||
sprite.name = "GradientBg";
|
||||
if (bgImage != null)
|
||||
bgImage.sprite = sprite;
|
||||
}
|
||||
|
||||
private Color GetColorByCurve(float ratio)
|
||||
{
|
||||
for (int i = 1; i < gradientColorNodeList.Count; i++)
|
||||
{
|
||||
if (ratio < gradientColorNodeList[i].ratio)
|
||||
{
|
||||
float curveValue = (ratio - gradientColorNodeList[i - 1].ratio) / (gradientColorNodeList[i].ratio - gradientColorNodeList[i - 1].ratio);
|
||||
curveValue = gradientCurve.Evaluate(curveValue);
|
||||
return Color.Lerp(gradientColorNodeList[i - 1].color, gradientColorNodeList[i].color, curveValue);
|
||||
}
|
||||
}
|
||||
return Color.white;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96f78caa6b7570243a53bedbbb5f220c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,414 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using Assets.Scripts;
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class Helper
|
||||
{
|
||||
public static string CreateDirectoryIfNotExsit(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
public static void DelectDir(string srcPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(srcPath))
|
||||
return;
|
||||
DirectoryInfo dir = new DirectoryInfo(srcPath);
|
||||
FileSystemInfo[] fileinfo = dir.GetFileSystemInfos(); //返回目录中所有文件和子目录
|
||||
foreach (FileSystemInfo i in fileinfo)
|
||||
{
|
||||
if (i is DirectoryInfo) //判断是否文件夹
|
||||
{
|
||||
DirectoryInfo subdir = new DirectoryInfo(i.FullName);
|
||||
subdir.Delete(true); //删除子目录和文件
|
||||
}
|
||||
else
|
||||
{
|
||||
File.Delete(i.FullName); //删除指定文件
|
||||
}
|
||||
}
|
||||
//删除当前文件夹
|
||||
Directory.Delete(srcPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
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++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
double n = 0.25;
|
||||
if (_npinterval.Count == 0) return 0;
|
||||
return Math.Pow((_npinterval.Sum() / _npinterval.Count), n);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Ftp
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static int GetFtp()
|
||||
{
|
||||
return App.CurrentUser.FTP;
|
||||
}
|
||||
|
||||
public static string FormatTicks(int seconds)
|
||||
{
|
||||
int h, m, s;
|
||||
h = seconds / 3600;
|
||||
m = (seconds - (3600 * h)) / 60;
|
||||
s = seconds - (3600 * h + 60 * m);
|
||||
string H, M, S;
|
||||
H = M = S = string.Empty;
|
||||
if (h < 10)
|
||||
H = "0" + h;
|
||||
else
|
||||
H = h.ToString();
|
||||
if (m < 10)
|
||||
M = "0" + m;
|
||||
else
|
||||
M = m.ToString();
|
||||
if (s < 10)
|
||||
S = "0" + s;
|
||||
else
|
||||
S = s.ToString();
|
||||
return $"{H}:{M}:{S}";
|
||||
}
|
||||
public static string FormateMacAddress(string v)
|
||||
{
|
||||
try
|
||||
{
|
||||
//var s = Convert.ToInt64(v).ToString("x8").ToUpperInvariant();
|
||||
var array = v.ToCharArray();
|
||||
StringBuilder newLsit = new StringBuilder();
|
||||
List<string> li = new List<string>();
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if ((i+1) % 2 == 0 && i > 0)
|
||||
{
|
||||
li.Add(array[i-1].ToString()+ array[i].ToString());
|
||||
}
|
||||
}
|
||||
for (int i = li.Count() -1 ; i >= 0 ; i--)
|
||||
{
|
||||
newLsit.Append(li[i]);
|
||||
if (i > 0)
|
||||
{
|
||||
newLsit.Append(":");
|
||||
}
|
||||
}
|
||||
return newLsit.ToString();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 计算速度
|
||||
/// 参考 http://bikecalculator.com/index.html
|
||||
/// </summary>
|
||||
/// <param name="elevationv">海拔</param>
|
||||
/// <param name="gradev">坡度%</param>
|
||||
/// <param name="powerv">功率</param>
|
||||
/// <param name="rweightv">体重</param>
|
||||
/// <param name="bweightv">自行车重量</param>
|
||||
/// <returns>km/h</returns>
|
||||
public static double CalculateSpeed(double elevationv, double gradev, double powerv, double rweightv, double bweightv)
|
||||
{
|
||||
if (powerv < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (gradev < -10)
|
||||
{
|
||||
gradev = -10;
|
||||
}
|
||||
var tireValues = new double[] { 0.005, 0.004, 0.012 };
|
||||
var aeroValues = new double[] { 0.388, 0.445, 0.420, 0.300, 0.233, 0.200 };
|
||||
var units = 0;
|
||||
|
||||
//温度
|
||||
var temperaturev = 25;
|
||||
|
||||
//海拔
|
||||
//var elevationv = 100;
|
||||
|
||||
//坡度
|
||||
//var gradev = 6 * 0.01 * -1;
|
||||
|
||||
//风,转换成m/s
|
||||
var headwindv = 0 / 3.6;
|
||||
|
||||
var frontalArea = aeroValues[0];
|
||||
|
||||
var transv = 0.95; // no one knows what this is, so why bother presenting a choice?
|
||||
var rollingRes = tireValues[0];
|
||||
|
||||
//应该是空气密度
|
||||
var density = (1.293 - 0.00426 * temperaturev) * Math.Exp(-elevationv / 7000.0);
|
||||
|
||||
|
||||
//全空气阻力参数
|
||||
var a2 = 0.5 * frontalArea * density; // full air resistance parameter
|
||||
var twt = 9.8 * (rweightv + bweightv); // total weight in newtons
|
||||
var tres = twt * (gradev * 0.01 + rollingRes); // gravity and rolling resistance
|
||||
|
||||
//var powerv = 195;
|
||||
|
||||
var v = Newton(a2, headwindv, tres, transv, powerv) * 3.6;// convert to km/h
|
||||
|
||||
//Trace.WriteLine($"速度为:{ v }");
|
||||
|
||||
var t1 = makeDecimal2(v * (units == 1 ? 1.609 : 1.0));
|
||||
return double.Parse(t1, CultureInfo.InvariantCulture);
|
||||
}
|
||||
private static double Newton(double aero, double hw, double tr, double tran, double p)
|
||||
{
|
||||
var vel = 20D;
|
||||
var MAX = 10;
|
||||
var TOL = 0.05;
|
||||
for (int i = 0; i < MAX; i++)
|
||||
{
|
||||
var tv = vel + hw;
|
||||
var aeroEff = (tv > 0.0) ? aero : -aero; // wind in face, must reverse effect
|
||||
var f = vel * (aeroEff * tv * tv + tr) - tran * p; // the function
|
||||
var fp = aeroEff * (3.0 * vel + hw) * tv + tr; // the derivative
|
||||
var vNew = vel - f / fp;
|
||||
if (Math.Abs(vNew - vel) < TOL)
|
||||
{
|
||||
return vNew; // success
|
||||
}
|
||||
vel = vNew;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
private static string makeDecimal2(double value)
|
||||
{
|
||||
if (value != 0)
|
||||
{
|
||||
var x = Math.Round(value * 100);
|
||||
int d;
|
||||
if (x < 100)
|
||||
{
|
||||
d = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
d = Convert.ToInt32(Math.Floor(x / 100), CultureInfo.InvariantCulture);
|
||||
};
|
||||
var c = x % 100;
|
||||
var g = (c >= 10) ? "" : "0";
|
||||
return "" + d + "." + g + c;
|
||||
}
|
||||
return value.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decode google style polyline coordinates.
|
||||
/// </summary>
|
||||
/// <param name="encodedPoints"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<CoordinateEntity> Decode(string encodedPoints)
|
||||
{
|
||||
if (string.IsNullOrEmpty(encodedPoints))
|
||||
throw new ArgumentNullException("encodedPoints");
|
||||
|
||||
char[] polylineChars = encodedPoints.ToCharArray();
|
||||
int index = 0;
|
||||
|
||||
int currentLat = 0;
|
||||
int currentLng = 0;
|
||||
int next5bits;
|
||||
int sum;
|
||||
int shifter;
|
||||
|
||||
while (index < polylineChars.Length)
|
||||
{
|
||||
// calculate next latitude
|
||||
sum = 0;
|
||||
shifter = 0;
|
||||
do
|
||||
{
|
||||
next5bits = (int)polylineChars[index++] - 63;
|
||||
sum |= (next5bits & 31) << shifter;
|
||||
shifter += 5;
|
||||
} while (next5bits >= 32 && index < polylineChars.Length);
|
||||
|
||||
if (index >= polylineChars.Length)
|
||||
break;
|
||||
|
||||
currentLat += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1);
|
||||
|
||||
//calculate next longitude
|
||||
sum = 0;
|
||||
shifter = 0;
|
||||
do
|
||||
{
|
||||
next5bits = (int)polylineChars[index++] - 63;
|
||||
sum |= (next5bits & 31) << shifter;
|
||||
shifter += 5;
|
||||
} while (next5bits >= 32 && index < polylineChars.Length);
|
||||
|
||||
if (index >= polylineChars.Length && next5bits >= 32)
|
||||
break;
|
||||
|
||||
currentLng += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1);
|
||||
|
||||
yield return new CoordinateEntity
|
||||
{
|
||||
Latitude = Convert.ToDouble(currentLat) / 1E5,
|
||||
Longitude = Convert.ToDouble(currentLng) / 1E5
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encode it
|
||||
/// </summary>
|
||||
/// <param name="points"></param>
|
||||
/// <returns></returns>
|
||||
private static string Encode(IEnumerable<CoordinateEntity> points)
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
|
||||
var encodeDiff = (Action<int>)(diff =>
|
||||
{
|
||||
int shifted = diff << 1;
|
||||
if (diff < 0)
|
||||
shifted = ~shifted;
|
||||
|
||||
int rem = shifted;
|
||||
|
||||
while (rem >= 0x20)
|
||||
{
|
||||
str.Append((char)((0x20 | (rem & 0x1f)) + 63));
|
||||
|
||||
rem >>= 5;
|
||||
}
|
||||
|
||||
str.Append((char)(rem + 63));
|
||||
});
|
||||
|
||||
int lastLat = 0;
|
||||
int lastLng = 0;
|
||||
|
||||
foreach (var point in points)
|
||||
{
|
||||
int lat = (int)Math.Round(point.Latitude * 1E5);
|
||||
int lng = (int)Math.Round(point.Longitude * 1E5);
|
||||
|
||||
encodeDiff(lat - lastLat);
|
||||
encodeDiff(lng - lastLng);
|
||||
|
||||
lastLat = lat;
|
||||
lastLng = lng;
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
}
|
||||
public struct CoordinateEntity
|
||||
{
|
||||
public double Latitude;
|
||||
public double Longitude;
|
||||
public CoordinateEntity(double x, double y) { this.Latitude = x; this.Longitude = y; }
|
||||
}
|
||||
|
||||
public static async Task<byte[]> DownloadImgAsync(List<MapDataModel.Item> list)
|
||||
{
|
||||
var result = new List<CoordinateEntity>();
|
||||
var count = list.Count;
|
||||
int segement = (int)Math.Ceiling((double)(count / 1000D));
|
||||
|
||||
for (int i = 0; i <= count - 1; i++)
|
||||
{
|
||||
if (i % segement == 0)
|
||||
{
|
||||
result.Add(new CoordinateEntity
|
||||
{
|
||||
Latitude = Math.Round(list[i].Point[0], 6),
|
||||
Longitude = Math.Round(list[i].Point[1], 6),
|
||||
});
|
||||
}
|
||||
}
|
||||
return await DownloadImgAsync(result);
|
||||
}
|
||||
|
||||
public static async Task<byte[]> DownloadImgAsync(List<CoordinateEntity> list)
|
||||
{
|
||||
var polyline = Encode(list);
|
||||
var encodeline = UnityWebRequest.EscapeURL(polyline); //HttpUtility.UrlEncode(polyline);
|
||||
//获取封面图片
|
||||
var url = $"https://api.mapbox.com/styles/v1/juzetest/ckmkdjwsa1nvt17nr1ps4fqgs/static/path-4+fff-1({encodeline})/auto/1280x1280?access_token={App.MapBoxAccessToken}";
|
||||
HttpClient c = new HttpClient();
|
||||
var response = await c.GetAsync(url);
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
||||
{
|
||||
byte[] content = await response.Content.ReadAsByteArrayAsync();
|
||||
return content;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetMapboxApiUrl(List<MapDataModel.Item> list)
|
||||
{
|
||||
var result = new List<CoordinateEntity>();
|
||||
var count = list.Count;
|
||||
int segement = (int)Math.Ceiling((double)(count / 1000D));
|
||||
|
||||
for (int i = 0; i <= count - 1; i++)
|
||||
{
|
||||
if (i % segement == 0)
|
||||
{
|
||||
result.Add(new CoordinateEntity
|
||||
{
|
||||
Latitude = Math.Round(list[i].Point[0], 6),
|
||||
Longitude = Math.Round(list[i].Point[1], 6),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var polyline = Encode(result);
|
||||
var encodeline = UnityWebRequest.EscapeURL(polyline); //HttpUtility.UrlEncode(polyline);
|
||||
//获取封面图片
|
||||
var url = $"https://api.mapbox.com/styles/v1/juzetest/ckmkdjwsa1nvt17nr1ps4fqgs/static/path-4+fff-1({encodeline})/auto/1280x768?access_token={App.MapBoxAccessToken}&padding=200&pitch=30";
|
||||
return url;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba2d01db4eb55e54b830f8c931fc9cae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,242 @@
|
||||
using Mapbox.Unity.Map;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using Mapbox.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class InitMiniMapProvider : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
AbstractMap _map;
|
||||
[SerializeField]
|
||||
Camera _minicamera;
|
||||
[SerializeField]
|
||||
GameObject _player;
|
||||
CyclingController cyclingCotroller;
|
||||
public PlayerController playerController;
|
||||
GameObject _mipMapRoute;
|
||||
public RectTransform RectRoot;//rawImage
|
||||
TrailRenderer trail;
|
||||
void Start()
|
||||
{
|
||||
cyclingCotroller = FindObjectOfType<CyclingController>();
|
||||
//playerController = FindObjectOfType<PlayerController>();
|
||||
if (cyclingCotroller != null)
|
||||
{
|
||||
var mapdata = cyclingCotroller.GetMapData();
|
||||
//初始化map
|
||||
//var point = cyclingCotroller.GetCenterCoordinate();
|
||||
if (_map != null && mapdata !=null)
|
||||
{
|
||||
_map.OnInitialized += _map_OnInitialized;
|
||||
_map.OnUpdated += _map_OnUpdated;
|
||||
_map.Initialize(new Vector2d(mapdata.Center[0], mapdata.Center[1]), 12);
|
||||
var bbox = mapdata.Bbox;
|
||||
var targetbounds = new Vector2dBounds(new Vector2d(bbox[1], bbox[0]), new Vector2d(bbox[3], bbox[2]));
|
||||
var screenBounds = GetScreenBounds();
|
||||
var z = SetZoomToFitBounds(targetbounds, screenBounds);
|
||||
}
|
||||
RectRoot = transform.parent.Find("SingleUI/Panel/MiniMap/MiniMap").GetComponent<RectTransform>();
|
||||
}
|
||||
|
||||
trail = transform.parent.Find("Sphere").GetComponent<TrailRenderer>();
|
||||
trail.startWidth = 5f;
|
||||
trail.endWidth = 5f;
|
||||
trail.startColor = new Color(0.9764706f, 0.1882353f, 0.5254902f, 1f);
|
||||
trail.endColor = new Color(0.9764706f, 0.1882353f, 0.5254902f, 1f);
|
||||
}
|
||||
float timer = 0;
|
||||
private void Update()
|
||||
{
|
||||
if (playerController != null)
|
||||
{
|
||||
var tr = transform.parent.Find("SingleUI/Panel/MiniMap/MiniMap/arrow");
|
||||
tr.SetSiblingIndex(9999);
|
||||
var pos = _map.GeoToWorldPosition(playerController.Currentlatlong);
|
||||
pos.y += 15f;
|
||||
_player.transform.localPosition = pos;
|
||||
Vector2 vp2 = _minicamera.WorldToViewportPoint(_player.transform.localPosition);//将三维物体的世界坐标转换为视口坐标
|
||||
((RectTransform)tr.transform).anchoredPosition = new Vector2((vp2.x * RectRoot.sizeDelta.x) - (RectRoot.sizeDelta.x * 0.5f), (vp2.y * RectRoot.sizeDelta.y) - (RectRoot.sizeDelta.y * 0.5f));
|
||||
trail.enabled = playerController.GetStart();
|
||||
}
|
||||
timer += Time.deltaTime;
|
||||
|
||||
while (timer>=1)
|
||||
{
|
||||
CreateMiniPath();
|
||||
timer = 0;
|
||||
}
|
||||
}
|
||||
void CreateMiniPath()
|
||||
{
|
||||
if (playerController == null)
|
||||
return;
|
||||
var dat = new List<Vector3>();
|
||||
var mapData = cyclingCotroller.GetMapData();
|
||||
if (mapData != null)
|
||||
{
|
||||
var count = mapData.List.Count;
|
||||
var interval = Math.Max(Math.Ceiling(count / 100D), 1f);
|
||||
for (int i = 0; i < mapData.List.Count; i++)
|
||||
{
|
||||
if (i % interval == 0)
|
||||
{
|
||||
var point = mapData.List[i].Point;
|
||||
Vector3 item = _map.GeoToWorldPosition(new Vector2d(point[0], point[1]));
|
||||
item.y += 5f;
|
||||
if (playerController.CurrentIndex >= i)
|
||||
{
|
||||
dat.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
var feat = new VectorFeatureUnity();
|
||||
feat.Points.Add(dat);
|
||||
CreateRedLineRender(feat);//创建小地图路线
|
||||
}
|
||||
}
|
||||
|
||||
private bool init = false;
|
||||
private void _map_OnInitialized()
|
||||
{
|
||||
init = true;
|
||||
var visualizer = _map.MapVisualizer;
|
||||
visualizer.OnMapVisualizerStateChanged += (s) =>
|
||||
{
|
||||
if (s == ModuleState.Finished)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#region Camera 自适应
|
||||
/// <summary>
|
||||
/// https://github.com/mapbox/mapbox-unity-sdk/issues/1580
|
||||
/// </summary>
|
||||
/// <param name="targetBounds">路线的边界</param>
|
||||
/// <param name="screenBounds">小地图边界</param>
|
||||
private int SetZoomToFitBounds(Vector2dBounds targetBounds, Vector2dBounds screenBounds)
|
||||
{
|
||||
var targetLonDelta = targetBounds.East - targetBounds.West;
|
||||
var targetLatDelta = targetBounds.North - targetBounds.South;
|
||||
|
||||
var screenLonDelta = screenBounds.East - screenBounds.West;
|
||||
var screenLatDelta = screenBounds.North - screenBounds.South;
|
||||
|
||||
var zoomLatMultiplier = screenLatDelta / targetLatDelta;
|
||||
var zoomLonMultiplier = screenLonDelta / targetLonDelta;
|
||||
|
||||
var latZoom = Math.Log(zoomLatMultiplier, 2);
|
||||
var lonZoom = Math.Log(zoomLonMultiplier, 2);
|
||||
|
||||
var zoom = (float)(_map.Zoom + Math.Min(latZoom, lonZoom));
|
||||
|
||||
_map.SetZoom((float)Math.Floor(zoom));
|
||||
_map.UpdateMap();
|
||||
return (int)Math.Floor(zoom);
|
||||
}
|
||||
private Vector2dBounds GetScreenBounds()
|
||||
{
|
||||
var screenWidth = UnityEngine.Screen.width;
|
||||
var screenHeight = UnityEngine.Screen.height;
|
||||
|
||||
var sw_world = _minicamera.ViewportToWorldPoint(new Vector3(0.25f, 0.1f, 160));
|
||||
var sw = _map.WorldToGeoPosition(sw_world);
|
||||
var ne_world = _minicamera.ViewportToWorldPoint(new Vector3(0.75f, 0.9f, 90));
|
||||
var ne = _map.WorldToGeoPosition(ne_world);
|
||||
|
||||
return new Vector2dBounds(new Vector2d(sw.x, sw.y), new Vector2d(ne.x, ne.y));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 创建小地图路线
|
||||
private void _map_OnUpdated()
|
||||
{
|
||||
CreateMiniRoute();
|
||||
}
|
||||
void CreateMiniRoute()
|
||||
{
|
||||
var meshData = new MeshData();
|
||||
var dat = new List<Vector3>();
|
||||
var mapData = cyclingCotroller.GetMapData();
|
||||
if (mapData != null)
|
||||
{
|
||||
var count = mapData.List.Count;
|
||||
var interval = Math.Max(Math.Ceiling(count / 100D),1f);
|
||||
for (int i = 0; i < mapData.List.Count; i++)
|
||||
{
|
||||
if(i% interval == 0)
|
||||
{
|
||||
var point = mapData.List[i].Point;
|
||||
Vector3 item = _map.GeoToWorldPosition(new Vector2d(point[0], point[1]));
|
||||
item.y += 1f;
|
||||
dat.Add(item);
|
||||
}
|
||||
}
|
||||
var feat = new VectorFeatureUnity();
|
||||
feat.Points.Add(dat);
|
||||
CreateLineRender(feat);//创建小地图路线
|
||||
}
|
||||
}
|
||||
//创建小地图路线
|
||||
void CreateLineRender(VectorFeatureUnity feat)
|
||||
{
|
||||
if (_mipMapRoute != null)
|
||||
{
|
||||
_mipMapRoute.Destroy();
|
||||
}
|
||||
_mipMapRoute = new GameObject("MiniMapRoute");
|
||||
_mipMapRoute.transform.parent = transform;
|
||||
var lineRender = _mipMapRoute.AddComponent<LineRenderer>();
|
||||
|
||||
lineRender.material = Instantiate(Resources.Load<Material>("UI/Material/1"));
|
||||
var dat = feat.Points[0];
|
||||
lineRender.endColor = Color.white;
|
||||
lineRender.startColor = Color.white;
|
||||
//设置宽度
|
||||
lineRender.startWidth = 10f;
|
||||
lineRender.endWidth = 10f;
|
||||
lineRender.positionCount = dat.Count;
|
||||
lineRender.SetPositions(feat.Points[0].ToArray());
|
||||
lineRender.numCornerVertices = 20;
|
||||
lineRender.numCapVertices = 20;
|
||||
lineRender.loop = false;
|
||||
_mipMapRoute.layer = 9;
|
||||
}
|
||||
GameObject _mipMapPath;
|
||||
void CreateRedLineRender(VectorFeatureUnity feat)
|
||||
{
|
||||
if (_mipMapPath != null)
|
||||
{
|
||||
_mipMapPath.Destroy();
|
||||
}
|
||||
_mipMapPath = new GameObject("MiniMapPath");
|
||||
_mipMapPath.transform.parent = transform;
|
||||
var lineRender = _mipMapPath.AddComponent<LineRenderer>();
|
||||
|
||||
lineRender.material = Instantiate(Resources.Load<Material>("UI/Material/2"));
|
||||
var dat = feat.Points[0];
|
||||
lineRender.endColor = Color.red;
|
||||
lineRender.startColor = Color.red;
|
||||
//设置宽度
|
||||
lineRender.startWidth = 10f;
|
||||
lineRender.endWidth = 10f;
|
||||
lineRender.positionCount = dat.Count;
|
||||
lineRender.SetPositions(feat.Points[0].ToArray());
|
||||
lineRender.numCornerVertices = 20;
|
||||
lineRender.numCapVertices = 20;
|
||||
lineRender.loop = false;
|
||||
_mipMapPath.layer = 9;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e94e95c463c5914d99fb16ff1047af4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,282 @@
|
||||
using UnityEngine;
|
||||
using Mapbox.Unity.Map;
|
||||
using DG.Tweening;
|
||||
using UnityEngine.UI;
|
||||
using Assets.Scripts.Apis;
|
||||
using System;
|
||||
using Assets.Scripts;
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Collections;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
|
||||
//[ExecuteInEditMode]
|
||||
public class LoadingController : MonoBehaviour
|
||||
{
|
||||
#region GameObject
|
||||
Text mapName;
|
||||
AbstractMap _map;
|
||||
Text level;
|
||||
Text distance;
|
||||
Text elevaction;
|
||||
Text slope;
|
||||
Text rideNum;
|
||||
Text uploadByUserName;
|
||||
Text processText;
|
||||
Text mapDescText;
|
||||
RawImage head;
|
||||
RawImage country;
|
||||
RawImage mapCountry;
|
||||
RawImage mapRouteImage;
|
||||
RawImage altitudeGraph;
|
||||
Button rideNow;
|
||||
Button cancel;
|
||||
MapApi mapApi;
|
||||
GameObject panel;
|
||||
CanvasGroup canvasGroup;
|
||||
Transform mapRanking;
|
||||
Slider slider;
|
||||
#endregion
|
||||
GameObject loadingPanel;
|
||||
#region 属性
|
||||
float process = 0;//0-100 %
|
||||
#endregion
|
||||
CyclingController cyclingController;
|
||||
private void Start()
|
||||
{
|
||||
App.TextureCache.Clear();
|
||||
loadingPanel = transform.Find("Panel/LoadingPanel").gameObject;
|
||||
loadingPanel.showLoadingExtension();
|
||||
//InitGameObject();
|
||||
}
|
||||
public void InjectController(CyclingController controller)
|
||||
{
|
||||
cyclingController = controller;
|
||||
PFUIPanel mainPanel = transform.Find("Panel").GetComponent<PFUIPanel>();
|
||||
PFUIPanel modelPanel = transform.Find("ModalPanel").GetComponent<PFUIPanel>();
|
||||
cyclingController.SetUIManager(mainPanel, modelPanel);
|
||||
}
|
||||
//提供给主控制器初始化用
|
||||
public void Init(MapRoute route)
|
||||
{
|
||||
InitGameObject();
|
||||
InitGameObjectData(route);
|
||||
}
|
||||
//展示当前路书图片
|
||||
public void SetMapRouteImage(string url)
|
||||
{
|
||||
Utils.DisplayImage(mapRouteImage, url);
|
||||
}
|
||||
public void DrawMapRoute(MapDataModel mapData)
|
||||
{
|
||||
var url = Helper.GetMapboxApiUrl(mapData.List);
|
||||
if (App.TextureCache.ContainsKey(url))
|
||||
{
|
||||
mapRouteImage.texture = App.TextureCache[url];
|
||||
var canvasGroup = mapRouteImage.GetComponent<CanvasGroup>();
|
||||
canvasGroup.DOFade(1, 1);
|
||||
this.AddProcess(10);
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.DisplayImageAysnc(StartCoroutine, mapRouteImage, url, dowloadCallBack);
|
||||
this.AddProcess(10);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void dowloadCallBack(string url)
|
||||
{
|
||||
if (!App.TextureCache.ContainsKey(url))
|
||||
{
|
||||
App.TextureCache.Add(url, mapRouteImage.texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
App.TextureCache[url] = mapRouteImage.texture;
|
||||
}
|
||||
var canvasGroup = mapRouteImage.GetComponent<CanvasGroup>();
|
||||
canvasGroup.DOFade(1, 1);
|
||||
|
||||
}
|
||||
//设定当前loading进度
|
||||
public void AddProcess(float v)
|
||||
{
|
||||
process += v;
|
||||
slider.value = process;
|
||||
slider.onValueChanged.AddListener((f) =>
|
||||
{
|
||||
processText.text = $"{(f ).ToString("#0")}%";
|
||||
});
|
||||
|
||||
if (process == 100)
|
||||
{
|
||||
rideNow.interactable = true;
|
||||
rideNow.enabled = true;
|
||||
}
|
||||
}
|
||||
//创建排行榜
|
||||
public void CreateRankingList(List<MapRouteRanking> list)
|
||||
{
|
||||
var prefab = Resources.Load<GameObject>("UI/Prefab/Ride/RankingItem");
|
||||
var parent = transform.Find("Panel/MapRanking");
|
||||
var title = transform.Find("Panel/RankingTitle").gameObject;
|
||||
if (list.Count == 0)
|
||||
{
|
||||
title.SetActive(false);
|
||||
}
|
||||
foreach (var item in list)
|
||||
{
|
||||
GameObject newObj = (GameObject)Instantiate(prefab, parent);
|
||||
var selectPlayerItemScript = newObj.GetComponent<RankingItemScript>();
|
||||
selectPlayerItemScript.SetRanking(item.RowNumber.ToString());
|
||||
selectPlayerItemScript.SetName(item.NickName);
|
||||
selectPlayerItemScript.SetTimer(item.IsDNF?"DNF":item.TotalTime);
|
||||
selectPlayerItemScript.SetHead(item.WxHeadImg);
|
||||
var texture = cyclingController.GetCountryImageByCode(item.CountryCode);
|
||||
selectPlayerItemScript.SetCountry(texture);
|
||||
}
|
||||
}
|
||||
private void InitGameObject()
|
||||
{
|
||||
panel = transform.Find("Panel").gameObject;
|
||||
mapName = transform.Find("Panel/MapName").GetComponent<Text>();
|
||||
distance = transform.Find("Panel/Distance").GetComponent<Text>();
|
||||
level = transform.Find("Panel/level/Text").GetComponent<Text>();
|
||||
elevaction = transform.Find("Panel/Elevaction").GetComponent<Text>();
|
||||
slope = transform.Find("Panel/Slope").GetComponent<Text>();
|
||||
rideNum = transform.Find("Panel/RideNum").GetComponent<Text>();
|
||||
uploadByUserName = transform.Find("Panel/UploadByUserName").GetComponent<Text>();
|
||||
country = transform.Find("Panel/UploadByCountry").GetComponent<RawImage>();
|
||||
mapCountry = transform.Find("Panel/Country").GetComponent<RawImage>();
|
||||
|
||||
head = transform.Find("Panel/UploadByHead").GetComponent<RawImage>();
|
||||
mapRouteImage = transform.Find("Panel/MapRouteImage").GetComponent<RawImage>();
|
||||
altitudeGraph = transform.Find("Panel/AltitudeGraph").GetComponent<RawImage>();
|
||||
mapRanking = transform.Find("Panel/MapRanking");
|
||||
slider = transform.Find("Panel/Process").GetComponent<Slider>();
|
||||
processText = transform.Find("Panel/ProcessText").GetComponent<Text>();
|
||||
mapDescText = transform.Find("Panel/MapDesc").GetComponent<Text>();
|
||||
rideNow = transform.Find("Panel/RideNow").GetComponent<Button>();
|
||||
cancel = transform.Find("Panel/Cancel").GetComponent<Button>();
|
||||
var root = transform.parent;
|
||||
_map = root.Find("Map").GetComponent<AbstractMap>();
|
||||
canvasGroup = transform.GetComponent<CanvasGroup>();
|
||||
rideNow.enabled = false;
|
||||
rideNow.interactable = false;
|
||||
UIManager.AddEvent(rideNow.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, StartRide);
|
||||
UIManager.AddEvent(cancel.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, Cancel);
|
||||
|
||||
}
|
||||
void StartRide(BaseEventData baseEvent)
|
||||
{
|
||||
var checkAnt = cyclingController.CheckAnt();
|
||||
#if UNITY_EDITOR
|
||||
checkAnt = true;
|
||||
#endif
|
||||
if (!checkAnt)
|
||||
{
|
||||
var alert = (GameObject)Instantiate(Resources.Load("UI/Prefab/Ride/Alert"), panel.transform);
|
||||
alert.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
cyclingController.ReSetUIManager();
|
||||
cyclingController.GoContinueRide();
|
||||
//启用ridenow
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
depressFlag = true;
|
||||
}
|
||||
}
|
||||
void Cancel(BaseEventData baseEvent)
|
||||
{
|
||||
SceneManager.LoadScene("MainScene");
|
||||
}
|
||||
private void InitGameObjectData(MapRoute route)
|
||||
{
|
||||
if (route != null)
|
||||
{
|
||||
#region 绑定路书基本信息
|
||||
mapName.text = route.Name;
|
||||
level.text = route.Hard;
|
||||
elevaction.text = Math.Round(route.TotalClimb.GetValueOrDefault(0), 2).ToString() + "M";
|
||||
slope.text = Math.Round(route.AverageGrade, 2).ToString() + "%";
|
||||
rideNum.text = route.TheHeat.ToString();
|
||||
distance.text = route.Distance.ToString("f1") + "KM";
|
||||
mapDescText.text = route.Dec;
|
||||
var userList = ConfigHelper.mapApi.GetOnlineUserInfo(new int[] { route.UserId }).data;
|
||||
if (userList.Count > 0)
|
||||
{
|
||||
uploadByUserName.text = userList[0].Name;
|
||||
var countryUrl = App.Host + $"User/GetCountryImg?userid={userList[0].Id}";
|
||||
Utils.DisplayImage(head, userList[0].HeadImage);//头像
|
||||
|
||||
country.texture = cyclingController.GetCountryImageByCode(route.CountryCode);//上传者国家
|
||||
mapCountry.texture = cyclingController.GetCountryImageByName(userList[0].Country);//路书国家
|
||||
|
||||
Utils.DisplayImage(altitudeGraph, route.AltitudeGraph);//海拔图
|
||||
}
|
||||
#endregion
|
||||
StartCoroutine(HiddenLoading());
|
||||
#region 地图注册 排行榜等接口
|
||||
_map.OnInitialized += _map_OnInitialized;
|
||||
_map.OnEditorPreviewEnabled += OnEditorPreviewEnabled;
|
||||
_map.OnEditorPreviewDisabled += OnEditorPreviewDisabled;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
IEnumerator HiddenLoading()
|
||||
{
|
||||
yield return new WaitForSeconds(1f);
|
||||
loadingPanel.SetActive(false);
|
||||
}
|
||||
void _map_OnInitialized()
|
||||
{
|
||||
var visualizer = _map.MapVisualizer;
|
||||
visualizer.OnMapVisualizerStateChanged += (s) =>
|
||||
{
|
||||
if (s == ModuleState.Finished)
|
||||
{
|
||||
AddProcess(40);
|
||||
}
|
||||
};
|
||||
}
|
||||
void OnEditorPreviewEnabled()
|
||||
{
|
||||
//transform.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
void OnEditorPreviewDisabled()
|
||||
{
|
||||
//transform.gameObject.SetActive(true);
|
||||
}
|
||||
public float targetAlpha = 0f;
|
||||
public float alphaSpeed = 2.0f;
|
||||
private bool depressFlag = false;
|
||||
void Update()
|
||||
{
|
||||
if (canvasGroup == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetAlpha != canvasGroup.alpha && depressFlag)
|
||||
{
|
||||
canvasGroup.alpha = Mathf.Lerp(canvasGroup.alpha, targetAlpha, alphaSpeed * Time.deltaTime);
|
||||
if (Mathf.Abs(targetAlpha - canvasGroup.alpha) <= 0.01f)
|
||||
{
|
||||
canvasGroup.alpha = targetAlpha;
|
||||
}
|
||||
if (canvasGroup.alpha == 0)
|
||||
{
|
||||
transform.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad0bd6432a7a35f4e92c526e8e970857
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,68 @@
|
||||
using Assets.Scripts;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using DG.Tweening;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class MessagePanelScript : MonoBehaviour
|
||||
{
|
||||
CanvasGroup canvas;
|
||||
Text text;
|
||||
RawImage head;
|
||||
string Name ="";
|
||||
string url ="";
|
||||
bool run = false;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
canvas = transform.GetComponent<CanvasGroup>();
|
||||
EventQueueSystem.AddListener<JoinMessageEvent>(JoinHandler);
|
||||
text = transform.Find("Name").GetComponent<Text>();
|
||||
head = transform.Find("RawImage").GetComponent<RawImage>();
|
||||
}
|
||||
private void JoinHandler(JoinMessageEvent e)
|
||||
{
|
||||
Name = e.name;
|
||||
url = e.url;
|
||||
}
|
||||
float timer = 2f;
|
||||
private void Update()
|
||||
{
|
||||
timer -= Time.deltaTime;
|
||||
if (timer <= 0)//定时器 一秒执行一次
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Name))
|
||||
{
|
||||
text.text = Name;
|
||||
canvas.DOFade(1, 2);
|
||||
Name = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
canvas.DOFade(0, 2);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
Utils.DisplayImage(head, url, false);
|
||||
url = string.Empty;
|
||||
}
|
||||
timer = 2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class JoinMessageEvent : GameEvent
|
||||
{
|
||||
public string name;//人物名称
|
||||
public string url;//头像地址
|
||||
|
||||
public JoinMessageEvent(string name,string url)
|
||||
{
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 811cf43645936ee4da7d950ad83b55a0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,47 @@
|
||||
using Mapbox.Unity.Map;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class MiniMapPlayerController: MonoBehaviour
|
||||
{
|
||||
private AbstractPlayer _player;
|
||||
private AbstractMap _map;
|
||||
RectTransform RectRoot;
|
||||
GameObject arrow;
|
||||
Camera _minicamera;
|
||||
private void Awake()
|
||||
{
|
||||
_map = transform.parent.Find("MiniMap").GetComponent<AbstractMap>();
|
||||
_minicamera = transform.parent.Find("MiniCamera").GetComponent<Camera>();
|
||||
RectRoot = transform.parent.Find("SingleUI/Panel/MiniMap/MiniMap").GetComponent<RectTransform>();
|
||||
var parent = transform.parent.Find("SingleUI/Panel/MiniMap/MiniMap");
|
||||
arrow = Instantiate(Resources.Load<GameObject>("UI/Prefab/Ride/MiniArrow"), parent);
|
||||
}
|
||||
public void SetController(AbstractPlayer player)
|
||||
{
|
||||
_player = player;
|
||||
}
|
||||
float t = 1f;
|
||||
private void Update()
|
||||
{
|
||||
t -= Time.deltaTime;
|
||||
while (t < 0)
|
||||
{
|
||||
if (_player != null)
|
||||
{
|
||||
transform.localPosition = _map.GeoToWorldPosition(_player.Currentlatlong);
|
||||
var tr = arrow.GetComponent<RectTransform>();
|
||||
Vector2 vp2 = _minicamera.WorldToViewportPoint(transform.localPosition);//将三维物体的世界坐标转换为视口坐标
|
||||
tr.anchoredPosition = new Vector2((vp2.x * RectRoot.sizeDelta.x) - (RectRoot.sizeDelta.x * 0.5f), (vp2.y * RectRoot.sizeDelta.y) - (RectRoot.sizeDelta.y * 0.5f));
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyImmediate(arrow);
|
||||
//DestroyImmediate(gameObject);
|
||||
}
|
||||
t = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 287bd44099b0d56478ff1fe696796816
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdcb8176fafcd62448e8c70ed9d43074
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cab9cf5c3f47cbe498f0cab35b09125e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,135 @@
|
||||
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));
|
||||
}
|
||||
|
||||
public virtual DateTime Now
|
||||
{
|
||||
get
|
||||
{
|
||||
return UIManager.Now.GetDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string ShowTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return Helper.FormatTicks(Ticks);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 骑行函数(如果此方法不满足,可以在子类中重写此方法)
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
public virtual void Run(TargetData targetData)
|
||||
{
|
||||
//将当前用户的位置发送到udf服务
|
||||
SendUserPositionToServer();
|
||||
//OutModel outData = GetSelfTargetData(targetData);
|
||||
BeforeRunAfterPakcData();//执行前的函数
|
||||
}
|
||||
|
||||
/// <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);
|
||||
MapUDPService.Send(route.RouteInstance.Id, recorderData.BelongUserId, new double[] { point.Latitude, point.Longitude }, endDistance:recorderData.EndDistance,preDistance: recorderData.EndDistance, competitionId: recorderData.Competitionid);
|
||||
}
|
||||
else
|
||||
{
|
||||
MapUDPService.Send(route.RouteInstance.Id, recorderData.BelongUserId, route.Point.First().Reverse().ToArray(), competitionId: recorderData.Competitionid);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 执行前,数据打包后
|
||||
/// </summary>
|
||||
/// <param name="outData"></param>
|
||||
protected virtual void BeforeRunAfterPakcData() { }
|
||||
protected double SpeedToDistance(double speed)
|
||||
{
|
||||
return Math.Round(speed / 3600, 5, MidpointRounding.AwayFromZero);
|
||||
//return 0.08;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89d63056e2fd43e41b30635a0036ba33
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,331 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model.RiderModels;
|
||||
using Assets.Scripts;
|
||||
using Assets.Scripts.Apis;
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using Mapbox.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model.CyclingModels
|
||||
{
|
||||
public class CompetitionModel : BaseCycling
|
||||
{
|
||||
private Vector2d firstPoint { get; set; }
|
||||
public CompetitionRankingModel competitionRankingModel { get; set; }
|
||||
|
||||
private MapCompetitionApi mapCompetitionApi;
|
||||
|
||||
public MapCompetition mapCompetition;
|
||||
|
||||
private List<CompetitionRankingResultModel> mapWorkoutRecordRankings = new List<CompetitionRankingResultModel>();
|
||||
/// <summary>
|
||||
/// 第一个到终点的时间
|
||||
/// </summary>
|
||||
private DateTime? FirstEndTime { get; set; }
|
||||
|
||||
public override bool CanPause => false;
|
||||
|
||||
public override string ShowTime
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CanStart())
|
||||
{
|
||||
var second = Math.Ceiling((Now - mapCompetition.StartTime.ToLocalTime()).TotalSeconds);
|
||||
|
||||
var ts = TimeSpan.FromSeconds(second);
|
||||
return $"{ (int)ts.TotalHours }:{ts:mm}:{ts:ss}";
|
||||
}
|
||||
return "00:00:00";
|
||||
}
|
||||
}
|
||||
AbstractPlayer currentPlayer;
|
||||
public CompetitionModel(Route route1, RouteResultParam param,AbstractPlayer player)
|
||||
: base(route1, CyclingModel.Competition)
|
||||
{
|
||||
currentPlayer = player;//当前选中用户
|
||||
mapCompetitionApi = new MapCompetitionApi();
|
||||
//param.EndDistance = 18;
|
||||
recorderData = new RecorderDataModel()
|
||||
{
|
||||
CurrentUser = App.CurrentUser,
|
||||
//BelongUserId = PubCommData.CurrentUser.Id,
|
||||
Competitionid = param.CompetitionId??0,
|
||||
ContinueIndex = param.ContinueIndex == null ? 0 : (int)param.ContinueIndex + 1,
|
||||
ContinueMark = string.IsNullOrEmpty(param.ContinueMark) ? Guid.NewGuid().ToString() : param.ContinueMark,
|
||||
EndDistance = param.EndDistance == 0 ? 0 : param.EndDistance,
|
||||
IsCompleted = false,
|
||||
IsNeedRanking = true,
|
||||
CyclingState = CyclingStateEnum.Prepare,
|
||||
//ManufacturerId = ManufacturerId,
|
||||
CurrentRoute = route,
|
||||
CurrentRouteStartDistance = param.EndDistance == 0 ? 0 : param.EndDistance,
|
||||
//DeviceNumber = DeviceNumber,
|
||||
//AntModelId = antModelId
|
||||
};
|
||||
|
||||
IsRecord = true;
|
||||
|
||||
riders = new List<BaseRider>();
|
||||
var rider = new OnlineRiderModel()
|
||||
{
|
||||
NickName = App.CurrentUser.Nickname,
|
||||
UserId = App.CurrentUser.Id,
|
||||
WxHeadImg = App.CurrentUser.WxHeadImg,
|
||||
EndDistance = param.EndDistance == 0 ? 0 : param.EndDistance
|
||||
};
|
||||
if (recorderData.CurrentRouteStartDistance > 0)
|
||||
{
|
||||
rider.Point = _turfHelper.Along(param.EndDistance);
|
||||
}
|
||||
else
|
||||
{
|
||||
rider.Point = new GeoJSON.Net.Geometry.GeographicPosition(this.route.RouteInstance.Point[0], this.route.RouteInstance.Point[1]);
|
||||
}
|
||||
//riders.Add(rider);//剔除自己
|
||||
|
||||
var result = mapCompetitionApi.GetById(param.CompetitionId??0);
|
||||
if (result.result == false || result.data == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mapCompetition = result.data;
|
||||
FirstEndTime = mapCompetition.FirstEndTime;
|
||||
}
|
||||
|
||||
protected override void BeforeRunAfterPakcData()
|
||||
{
|
||||
//#region 设置第一名的坐标
|
||||
//if (!FirstEndTime.HasValue)
|
||||
//{
|
||||
// var firstItem = base.realRiders.OrderByDescending(w => w.NextDistance).FirstOrDefault();
|
||||
// if (firstItem != null)
|
||||
// {
|
||||
// firstPoint = new Vector2d(firstItem.Point.Latitude, firstItem.Point.Longitude);
|
||||
// }
|
||||
//}
|
||||
//#endregion
|
||||
|
||||
var userList = MapUDPService.GetCompetitionOnlineUsers(recorderData.Competitionid).OrderByDescending(u => u.IsCompleted).ThenByDescending(d => d.EndDistance);
|
||||
riders.RemoveAll(r => r.IsSelf == false);
|
||||
int index = 0;
|
||||
List<CompetitionRankingSortModel> sort = new List<CompetitionRankingSortModel>();
|
||||
|
||||
if (userList.Any())
|
||||
{
|
||||
var currentDistance = currentPlayer.TotalDistance;
|
||||
foreach (var item in userList)
|
||||
{
|
||||
#region 记录第一个冲线的时间
|
||||
if (item.IsCompleted && !FirstEndTime.HasValue)
|
||||
{
|
||||
FirstEndTime = Now;
|
||||
}
|
||||
#endregion
|
||||
|
||||
if (item.IsSelf == false)
|
||||
{
|
||||
riders.Add(new OnlineRiderModel
|
||||
{
|
||||
NickName = item.Name,
|
||||
UserId = item.Id,
|
||||
WxHeadImg = item.HeadImage,
|
||||
Point = new GeoJSON.Net.Geometry.GeographicPosition(item.Point[0], item.Point[1]),
|
||||
EndDistance = item.EndDistance,
|
||||
PreDistance = item.PreDistance
|
||||
});
|
||||
}
|
||||
|
||||
index++;
|
||||
double near = Math.Round(item.EndDistance - currentDistance,2); //Math.Round(TurfHelper.GetDistances(point, item.Point), 2);
|
||||
|
||||
sort.Add(new CompetitionRankingSortModel
|
||||
{
|
||||
Index = index,
|
||||
Name = item.Name,
|
||||
Near = near,
|
||||
KGWeight = Math.Round(item.WeightKg, 2).ToString(),
|
||||
Speed = Math.Round(item.Speed, 1),
|
||||
CountryImg = ConfigHelper.Host + $"User/GetCountryImg?userid={ item.Id }",
|
||||
UserId = item.Id,
|
||||
IsSelf = item.IsSelf
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#region 骑行结束,比赛结果展示数据
|
||||
var results = new List<CompetitionResultModel>();
|
||||
if (recorderData.IsCompleted || recorderData.Saved || mapCompetition.HasRecord)
|
||||
{
|
||||
var users1 = userList.Where(d => d.IsCompleted || d.Saved);
|
||||
if ((users1.Any() && users1.Any(d => mapWorkoutRecordRankings.All(u => u.UserId != d.Id)))
|
||||
|| mapWorkoutRecordRankings.All(u => u.UserId != recorderData.BelongUserId))
|
||||
{
|
||||
var rrr = mapCompetitionApi.GetRankingList(recorderData.Competitionid);
|
||||
if (rrr.result)
|
||||
{
|
||||
mapWorkoutRecordRankings = rrr.data;
|
||||
}
|
||||
}
|
||||
foreach (var ranking in mapWorkoutRecordRankings)
|
||||
{
|
||||
//var ranking = mapWorkoutRecordRankings.SingleOrDefault(r => r.UserId == item.Id);
|
||||
|
||||
var createTime = "";
|
||||
if (ranking != null)
|
||||
{
|
||||
createTime = ranking.CreateTime; //.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
results.Add(new CompetitionResultModel
|
||||
{
|
||||
Index = ranking.Index,
|
||||
Name = ranking.NickName,
|
||||
Weight = ranking?.Weight ?? 0,
|
||||
WeightKg = ranking?.WeightKg ?? 0,
|
||||
//Time = ranking?.TotalTime ?? "",
|
||||
Power = ranking?.AveragePower ?? 0,
|
||||
BicycleWeight = ranking?.BicycleWeight ?? 0,
|
||||
HeartRate = ranking?.AverageHeartRate ?? 0,
|
||||
DeviceType = ranking?.DeviceType ?? "",
|
||||
CreateTime = createTime,
|
||||
TripTime = ranking?.TripTime ?? "",
|
||||
CompleteTime = ranking?.CompleteTime,
|
||||
Gap = ranking?.Gap ?? ""
|
||||
});
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
competitionRankingModel = new CompetitionRankingModel
|
||||
{
|
||||
Sorts = sort,//骑行实时排名
|
||||
MyRanking = sort.FindIndex(n => n.UserId == currentPlayer.UserId) + 1,//切换人物显示对应人物的排名
|
||||
Total = sort.Count,//总人数
|
||||
Results = results//比赛结果列表
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 赛事模式有继续骑行,重写执行方法
|
||||
/// </summary>
|
||||
/// <param name="targetData"></param>
|
||||
public override void Run(TargetData targetData)
|
||||
{
|
||||
|
||||
#region 获取当前路线在线用户
|
||||
riders.RemoveAll(r => r.IsSelf == false);
|
||||
var onlineUsers = MapUDPService.GetCompetitionOnlineUsers(mapCompetition.Id).Where(d => d.IsSelf == false)
|
||||
.ToList();
|
||||
foreach (var item in onlineUsers)
|
||||
{
|
||||
riders.Add(new OnlineRiderModel()
|
||||
{
|
||||
NickName = item.Name,
|
||||
UserId = item.Id,
|
||||
WxHeadImg = item.HeadImage,
|
||||
Point = new GeoJSON.Net.Geometry.GeographicPosition(item.Point[0], item.Point[1]),
|
||||
EndDistance = item.EndDistance,
|
||||
PreDistance = item.PreDistance,
|
||||
WeightKg = item.WeightKg,
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
//TODO:接力赛
|
||||
////base.BeforeRun(targetData);
|
||||
//if (recorderData.CyclingState == CyclingStateEnum.Prepare)
|
||||
//{
|
||||
// if (recorderData.EndDistance != 0)
|
||||
// {
|
||||
// currentDistance = recorderData.EndDistance;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// currentDistance = 0;
|
||||
// }
|
||||
//}
|
||||
//else if (recorderData.CyclingState == CyclingStateEnum.Cycling)
|
||||
//{
|
||||
// currentDistance = recorderData.EndDistance + SpeedToDistance(targetData._Speed);
|
||||
//}
|
||||
base.Run(targetData);
|
||||
}
|
||||
|
||||
//显示结果当前用户保存或者产生第一名
|
||||
public bool CanShowResult()
|
||||
{
|
||||
return mapCompetition?.HasRecord ?? false || mapCompetition ?.FirstEndTime != null;
|
||||
}
|
||||
//关门时间到了退出骑行场景
|
||||
public bool CanQuit()
|
||||
{
|
||||
if (mapCompetition?.FirstEndTime.HasValue??false)
|
||||
{
|
||||
var closeDateTime = mapCompetition?.FirstEndTime.Value.ToLocalTime().AddMinutes(mapCompetition?.CloseTime??0 );
|
||||
return Now >= closeDateTime;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanStart()
|
||||
{
|
||||
if (mapCompetition == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//if (mapCompetition.CanStart)
|
||||
//{
|
||||
// return true;
|
||||
//}
|
||||
|
||||
if (mapCompetition.HasRecord)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//已结束
|
||||
if (mapCompetition.Status == 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (mapCompetition.StartTime.ToLocalTime() <= Now && mapCompetition.EndTime.ToLocalTime() > Now)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int StartCountdown()
|
||||
{
|
||||
if (CanStart()) return 0;
|
||||
return (int)Math.Floor((mapCompetition.StartTime.ToLocalTime() - Now).TotalSeconds);
|
||||
}
|
||||
/// <summary>
|
||||
/// 结束倒计时,bool值为true说明倒计时是关门时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public (int, bool) EndCountDown()
|
||||
{
|
||||
if (CanStart() == false) return (0, false);
|
||||
//if (recorderData.IsCompleted) return 0;
|
||||
var end1 = (int)Math.Floor((mapCompetition.EndTime.ToLocalTime() - Now).TotalSeconds);
|
||||
if (!FirstEndTime.HasValue)
|
||||
{
|
||||
return (end1, false);
|
||||
}
|
||||
//var end2 = (int)Math.Floor((FirstEndTime.Value - Now).TotalSeconds);
|
||||
var end2 = (int)Math.Floor((FirstEndTime.Value.AddMinutes(mapCompetition.CloseTime) - Now).TotalSeconds);
|
||||
if (end1 < end2)
|
||||
{
|
||||
return (end1, false);
|
||||
}
|
||||
//return Math.Min(end1, end2);
|
||||
return (end2, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44b357cbe9541fa448708b42ff5bf3d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model.RiderModels;
|
||||
using Assets.Scripts;
|
||||
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.CyclingModels
|
||||
{
|
||||
public class ReviewModel : BaseCycling
|
||||
{
|
||||
public List<MapRecordRanking> rankings;
|
||||
|
||||
public ReviewModel(Route route1, RouteResultParam param)
|
||||
: base(route1, CyclingModel.Review)
|
||||
{
|
||||
//rankings = service.GetMapRecordRankingsFromServe(param.RankingsId);
|
||||
riders = new List<BaseRider>();
|
||||
//riders.Add(new OnlineRiderModel()
|
||||
//{
|
||||
// NickName = App.CurrentUser.Nickname,
|
||||
// UserId = App.CurrentUser.Id,
|
||||
// WxHeadImg = App.CurrentUser.WxHeadImg,
|
||||
// Point = new GeoJSON.Net.Geometry.GeographicPosition(this.route.RouteInstance.Point[0], this.route.RouteInstance.Point[1])
|
||||
//});
|
||||
//foreach (var item in rankings)
|
||||
//{
|
||||
// riders.Add(new ReviewRiderModel()
|
||||
// {
|
||||
// NickName = item.NickName,
|
||||
// UserId = item.UserId,
|
||||
// WxHeadImg = item.WxHeadImg,
|
||||
// record = item.record,
|
||||
// Point = new GeoJSON.Net.Geometry.GeographicPosition(this.route.RouteInstance.Point[0], this.route.RouteInstance.Point[1])
|
||||
// });
|
||||
//}
|
||||
recorderData = new RecorderDataModel()
|
||||
{
|
||||
CurrentUser = App.CurrentUser,
|
||||
//BelongUserId = PubCommData.CurrentUser.Id,
|
||||
Competitionid = 0,
|
||||
ContinueIndex = 0,
|
||||
ContinueMark = Guid.NewGuid().ToString(),
|
||||
EndDistance = 0,
|
||||
PreDistance = 0,
|
||||
IsCompleted = false,
|
||||
IsNeedRanking = true,
|
||||
CyclingState = CyclingStateEnum.Prepare,
|
||||
//ManufacturerId = ManufacturerId,
|
||||
CurrentRoute = route,
|
||||
CurrentRouteStartDistance = 0,
|
||||
//DeviceNumber = DeviceNumber,
|
||||
//AntModelId = antModelId
|
||||
};
|
||||
|
||||
//recorderData = recorderData1;
|
||||
this.IsRecord = true;
|
||||
//riders = riders1;
|
||||
|
||||
}
|
||||
|
||||
public override void Run(TargetData targetData)
|
||||
{
|
||||
|
||||
#region 获取当前路线在线用户
|
||||
riders.RemoveAll(r => r.IsSelf == false);
|
||||
var onlineUsers = MapUDPService.GetOnlineUsers(recorderData.CurrentRoute.RouteInstance.Id).Where(d => d.IsSelf == false)
|
||||
.ToList();
|
||||
foreach (var item in onlineUsers)
|
||||
{
|
||||
riders.Add(new OnlineRiderModel()
|
||||
{
|
||||
NickName = item.Name,
|
||||
UserId = item.Id,
|
||||
WxHeadImg = item.HeadImage,
|
||||
Point = new GeoJSON.Net.Geometry.GeographicPosition(item.Point[0], item.Point[1]),
|
||||
EndDistance = item.EndDistance,
|
||||
PreDistance = item.PreDistance,
|
||||
WeightKg = item.WeightKg,
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
base.Run(targetData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 363f64631c874c84198aa481f8899911
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,89 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model.RiderModels;
|
||||
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.CyclingModels
|
||||
{
|
||||
public class SingleModel : BaseCycling
|
||||
{
|
||||
|
||||
public SingleModel(Route route,RouteResultParam param)
|
||||
: base(route, CyclingModel.Single)
|
||||
{
|
||||
this.IsRecord = true;
|
||||
recorderData = new RecorderDataModel()
|
||||
{
|
||||
CurrentUser = App.CurrentUser,
|
||||
Competitionid = 0,
|
||||
ContinueIndex = 0,
|
||||
ContinueMark = Guid.NewGuid().ToString(),
|
||||
EndDistance = 0,
|
||||
IsCompleted = false,
|
||||
IsNeedRanking = true,
|
||||
CyclingState = CyclingStateEnum.Prepare,
|
||||
CurrentRoute = route,
|
||||
CurrentRouteStartDistance = 0,
|
||||
StartTime = UIManager.Now.GetDateTime(),//DateTime.Now
|
||||
};
|
||||
|
||||
if (param != null)
|
||||
{
|
||||
recorderData.EndDistance = param.EndDistance;
|
||||
recorderData.CurrentRouteStartDistance = param.EndDistance;
|
||||
if (!string.IsNullOrWhiteSpace(param.ContinueMark))
|
||||
{
|
||||
recorderData.ContinueMark = param.ContinueMark;
|
||||
}
|
||||
else
|
||||
{
|
||||
param.ContinueMark = recorderData.ContinueMark;
|
||||
}
|
||||
recorderData.ContinueIndex = param.ContinueIndex.GetValueOrDefault(0);
|
||||
}
|
||||
|
||||
recorderData.PreDistance = recorderData.EndDistance;
|
||||
|
||||
riders = new List<BaseRider>();
|
||||
//var rider = new OnlineRiderModel()
|
||||
//{
|
||||
// NickName = App.CurrentUser.Nickname,
|
||||
// UserId = App.CurrentUser.Id,
|
||||
// WxHeadImg = App.CurrentUser.WxHeadImg + "?t=1",
|
||||
// //Point = new GeoJSON.Net.Geometry.GeographicPosition(this.route.RouteInstance.Point[0], this.route.RouteInstance.Point[1]),
|
||||
// EndDistance = recorderData.EndDistance
|
||||
//};
|
||||
//rider.Point = _turfHelper.Along(rider.EndDistance);
|
||||
|
||||
//riders.Add(rider);
|
||||
|
||||
}
|
||||
|
||||
public override void Run(TargetData targetData)
|
||||
{
|
||||
#region 获取当前路线在线用户
|
||||
riders.RemoveAll(r => r.IsSelf == false);
|
||||
var onlineUsers = MapUDPService.GetOnlineUsers(recorderData.CurrentRoute.RouteInstance.Id).Where(d => d.IsSelf == false)
|
||||
.ToList();
|
||||
foreach (var item in onlineUsers)
|
||||
{
|
||||
riders.Add(new OnlineRiderModel()
|
||||
{
|
||||
NickName = item.Name,
|
||||
UserId = item.Id,
|
||||
WxHeadImg = item.HeadImage,
|
||||
Point = new GeoJSON.Net.Geometry.GeographicPosition(item.Point[0], item.Point[1]),
|
||||
EndDistance = item.EndDistance,
|
||||
PreDistance = item.PreDistance,
|
||||
WeightKg = item.WeightKg,
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
base.Run(targetData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1057f786065eded488dd73a935cc1b93
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3d3dd3c4d6e2694eb9d94bc819a12f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,542 @@
|
||||
using GeoJSON.Net.Geometry;
|
||||
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 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 == App.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 int Id { 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 string Country { 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],CultureInfo.InvariantCulture),
|
||||
MemberId = Convert.ToInt32(list[1], CultureInfo.InvariantCulture),
|
||||
Point = new double[] { double.Parse(list[2].Split(':')[0], CultureInfo.InvariantCulture), double.Parse(list[2].Split(':')[1], CultureInfo.InvariantCulture) },
|
||||
IsCompleted = ToBoolean(list[3]),
|
||||
//exit = ToBoolean(list[4]),
|
||||
Speed = Convert.ToDouble(list[4], CultureInfo.InvariantCulture),
|
||||
PreDistance = Convert.ToDouble(list[5], CultureInfo.InvariantCulture),
|
||||
EndDistance = Convert.ToDouble(list[6], CultureInfo.InvariantCulture),
|
||||
WeightKg = Convert.ToDouble(list[7], CultureInfo.InvariantCulture),
|
||||
Competitionid = Convert.ToInt32(list[8], CultureInfo.InvariantCulture),
|
||||
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 == App.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 string Country { get; set; }
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5741018b26c4d94dbd42daf26d87f3f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,252 @@
|
||||
using Assets.Scripts;
|
||||
using Assets.Scripts.Apis;
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model
|
||||
{
|
||||
public class RecorderDataModel
|
||||
{
|
||||
//private readonly MapWorkoutService service = new MapWorkoutService();
|
||||
|
||||
public UserResultModel 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 string ManufacturerName { 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; }
|
||||
|
||||
public DateTime EndTime { get; set; }
|
||||
/// <summary>
|
||||
/// 是否已经保存成功
|
||||
/// </summary>
|
||||
public bool Saved { get; set; }
|
||||
|
||||
public int GlobalCyclingId { get; set; }
|
||||
|
||||
public void SaveWithLocalRecordAysnc(CyclingModel cyclingModel, RouteResultParam selectParam, string imageName,string recordId,string path)
|
||||
{
|
||||
Dictionary<MapInterruptRecord, List<string>> recordData = new Dictionary<MapInterruptRecord, List<string>>();
|
||||
if (RiderDatas.Count <= 0)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
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);
|
||||
|
||||
// AntManufacturer manufacturer = service.GetAntManufacturer(ManufacturerId).data;
|
||||
//var recordId = Guid.NewGuid().ToString();
|
||||
var ticks = RiderDatas.Last().Ticks;
|
||||
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 / App.CurrentUser.Weight, 2),
|
||||
Weight = App.CurrentUser.Weight,
|
||||
BicycleWeight = App.CurrentUser.BicycleWeight,
|
||||
ContinueMark = ContinueMark,
|
||||
ContinueIndex = ContinueIndex,
|
||||
IsDelete = false,
|
||||
MapCompetitionId = Competitionid,
|
||||
ManufacturerName = ManufacturerName,//manufacturer == null ? "" : manufacturer.Name,
|
||||
DeviceNumber = DeviceNumber,
|
||||
IsRanking = IsNeedRanking,
|
||||
CurrentRouteStartDistance = CurrentRouteStartDistance,
|
||||
ManufacturerId = ManufacturerId,
|
||||
AntModelId = AntModelId,
|
||||
StartTime = StartTime,
|
||||
CreateTime = EndTime, //StartTime.AddSeconds(ticks),
|
||||
Ticks = ticks,
|
||||
Mode = cyclingModel.ToString(),
|
||||
Param = Newtonsoft.Json.JsonConvert.SerializeObject(selectParam),
|
||||
GlobalCyclingId = 0,
|
||||
Source = "",
|
||||
};
|
||||
//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);
|
||||
//保存骑行记录txt
|
||||
|
||||
//var path = Helper.GetDataDir("MapWorkoutRecords" + "/" + interruptRecord.Id);
|
||||
//var path = PFConstants.MapWorkoutRecordFolder + "/" + interruptRecord.Id;
|
||||
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);
|
||||
}
|
||||
//图片
|
||||
if (!string.IsNullOrEmpty(imageName))
|
||||
{
|
||||
files.Add(imageName);
|
||||
}
|
||||
//持久化序列化对象
|
||||
var recordString = JsonConvert.SerializeObject(interruptRecord);
|
||||
var recordFilePath = path + "/" + "record" + ".txt";
|
||||
System.IO.File.WriteAllText(recordFilePath, recordString);
|
||||
|
||||
recordData.Add(interruptRecord, files);
|
||||
|
||||
SaveDataAysnc(recordData, path);
|
||||
}
|
||||
/// <summary>
|
||||
/// 保存数据
|
||||
/// </summary>
|
||||
/// <param name="base64Image"></param>
|
||||
/// <returns></returns>
|
||||
public void SaveDataAysnc(Dictionary<MapInterruptRecord, List<string>> data,string path)
|
||||
{
|
||||
if (data != null && data.Count > 0)
|
||||
{
|
||||
//var path = Helper.GetDataDir("MapWorkoutRecords");
|
||||
Task.Run(() => {
|
||||
var record = data.FirstOrDefault();
|
||||
MapInterruptRecordApi service = new MapInterruptRecordApi();
|
||||
var result = service.Add(record.Key, record.Value);
|
||||
|
||||
//删除文件
|
||||
try
|
||||
{
|
||||
if (result.result && Directory.Exists(path))
|
||||
{
|
||||
Helper.DelectDir(path);
|
||||
Saved = true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Log(e.Message);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11c5f863a5d0baa49b7b374090197f99
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts.Model
|
||||
{
|
||||
public class RideSetting
|
||||
{
|
||||
public double sensitivity { set; get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2bdb001023de8f942b52de4e72bc45e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7b3cc03af7b19e44b20d0b929a53d45
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 == App.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,61 @@
|
||||
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;
|
||||
public double WeightKg { 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:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b4a6fa5405752242a577299e27df510
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fab2eae6e723baa46ad8c972556f38c6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
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 _TotalClimb { 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 = Convert.ToInt32(split[0], CultureInfo.InvariantCulture); //int.Parse(split[0]);
|
||||
target._Power = Convert.ToDouble(split[1], CultureInfo.InvariantCulture);
|
||||
target._Speed = Convert.ToDouble(split[2], CultureInfo.InvariantCulture);// double.Parse(split[2]);
|
||||
target._Distance = Convert.ToDouble(split[3], CultureInfo.InvariantCulture); //double.Parse(split[3]);
|
||||
target._Cadence = Convert.ToDouble(split[4], CultureInfo.InvariantCulture); //double.Parse(split[4]);
|
||||
if (!string.IsNullOrWhiteSpace(split[5]) && split[5] != "null")
|
||||
{
|
||||
target._HeartRate = Convert.ToInt32(split[5], CultureInfo.InvariantCulture); //int.Parse(split[5]);
|
||||
}
|
||||
if (split.Length > 6)
|
||||
{
|
||||
target._Lat = Convert.ToDouble(split[6], CultureInfo.InvariantCulture); //double.Parse(split[6]);
|
||||
target._Lon = Convert.ToDouble(split[7], CultureInfo.InvariantCulture); //double.Parse(split[7]);
|
||||
//target._Bearing = double.Parse(split[8]);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79850d6cccee69445927e491750a500b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d977fd7941debf4b90f950a8fd3c0a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
|
||||
{
|
||||
private static T instance = null;
|
||||
|
||||
private static readonly object locker = new object();
|
||||
|
||||
private static bool bAppQuitting;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (bAppQuitting)
|
||||
{
|
||||
instance = null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
lock (locker)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = FindObjectOfType<T>();
|
||||
if (FindObjectsOfType<T>().Length > 1)
|
||||
{
|
||||
Debug.LogError("不应该存在多个单例!");
|
||||
return instance;
|
||||
}
|
||||
|
||||
if (instance == null)
|
||||
{
|
||||
var singleton = new GameObject();
|
||||
instance = singleton.AddComponent<T>();
|
||||
singleton.name = "(singleton)" + typeof(T);
|
||||
singleton.hideFlags = HideFlags.None;
|
||||
DontDestroyOnLoad(singleton);
|
||||
}
|
||||
else
|
||||
DontDestroyOnLoad(instance.gameObject);
|
||||
}
|
||||
instance.hideFlags = HideFlags.None;
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
bAppQuitting = false;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
bAppQuitting = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 018a42bd337f3c74789a75cc6973b979
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,42 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class NearByFactory : BaseListFactory
|
||||
{
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
cyclingController = FindObjectOfType<CyclingController>();
|
||||
playerController = FindObjectOfType<PlayerController>();
|
||||
nearByItem = Resources.Load<GameObject>("UI/Prefab/Ride/NearbyItem");
|
||||
nearByMajorItem = Resources.Load<GameObject>("UI/Prefab/Ride/NearbyMajorItem");
|
||||
}
|
||||
protected override void CreateList()
|
||||
{
|
||||
var nearList = MapUDPService.GetNearRiderData(pageIndex, pageSize, new double[] { playerController.Currentlatlong.x, playerController.Currentlatlong.y });
|
||||
totalPages = MapUDPService.GetNearRiderCount();
|
||||
for (int i = 0; i < nearList.Count(); i++)
|
||||
{
|
||||
Create(nearList[i]);
|
||||
}
|
||||
}
|
||||
private void Create(NearRiderModel item)
|
||||
{
|
||||
//创建
|
||||
GameObject prefabItem = item.IsSelf ? nearByMajorItem : nearByItem;
|
||||
GameObject newObj = (GameObject)Instantiate(prefabItem, transform);
|
||||
var nearByItemscript = newObj.GetComponent<NearByItemScript>();
|
||||
nearByItemscript.setUserId(item.Id);
|
||||
nearByItemscript.setName(item.Name);
|
||||
nearByItemscript.setRatio(item.KGWeight+"W/KG");
|
||||
nearByItemscript.setSpeed(item.Speed.ToString() + "KM/H");
|
||||
nearByItemscript.setHead(item.Headimage);
|
||||
nearByItemscript.setCountry(cyclingController.GetCountryImageByName(item.Country));
|
||||
nearByItemscript.setDistance(item.Near.ToString() + "KM");
|
||||
bufferSize++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1422da55067b129428f0a2833db916b9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class NearByHeadScript :MonoBehaviour
|
||||
{
|
||||
private Text Title;
|
||||
private Text OnlineUserNum;
|
||||
private void Start()
|
||||
{
|
||||
//Title = transform.Find("Title").GetComponent<Text>();
|
||||
//OnlineUserNum = transform.Find("NearByView/OnlineUserNum").GetComponent<Text>();
|
||||
}
|
||||
float t = 1;
|
||||
private void Update()
|
||||
{
|
||||
t -= Time.deltaTime;
|
||||
while (t < 0)
|
||||
{
|
||||
//OnlineUserNum.text = MapUDPService.GetNearRiderCount().ToString();
|
||||
t = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab770f3fae92ac1478b8a7c28eccb895
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,132 @@
|
||||
using Assets.Scripts;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class NearByItemScript : MonoBehaviour
|
||||
{
|
||||
private RawImage Head;
|
||||
private RawImage Country;
|
||||
private Text Name;
|
||||
private Text Speed;
|
||||
private Text Distance;
|
||||
private Text Ratio;//功体比
|
||||
|
||||
private int _userId = 0;
|
||||
public int UserId { get { return _userId; } }
|
||||
private string _headUrl=string.Empty;
|
||||
private string _countryUrl = string.Empty;
|
||||
private string _name = string.Empty;
|
||||
private string _speed = string.Empty;
|
||||
private string _distance = string.Empty;
|
||||
private string _ratio = string.Empty;
|
||||
private Texture countryTexture;
|
||||
private void Awake()
|
||||
{
|
||||
Head = transform.Find("Head").GetComponent<RawImage>();
|
||||
Country = transform.Find("Country").GetComponent<RawImage>();
|
||||
Name = transform.Find("Name").GetComponent<Text>();
|
||||
Speed = transform.Find("Speed").GetComponent<Text>();
|
||||
Distance = transform.Find("Distance").GetComponent<Text>();
|
||||
Ratio = transform.Find("Ratio").GetComponent<Text>();
|
||||
countryTexture = Resources.Load<Sprite>("Images/flag_China_Person").texture;
|
||||
}
|
||||
|
||||
public void setRatio(string ratio)
|
||||
{
|
||||
if (!_ratio.Equals(ratio))
|
||||
{
|
||||
Ratio.text = ratio;
|
||||
}
|
||||
}
|
||||
|
||||
public void setHead(string url)
|
||||
{
|
||||
if (!_headUrl.Equals(url))
|
||||
{
|
||||
//if (App.TextureCache.ContainsKey(url))
|
||||
//{
|
||||
// Head.texture = App.TextureCache[url];
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
Utils.DisplayImage(Head, url, true);
|
||||
//}
|
||||
|
||||
//Utils.DisplayImage(StartCoroutine, Head, url);
|
||||
//StartCoroutine(DownloadImage(Head, url));
|
||||
var rect = ((RectTransform)Head.transform).rect;
|
||||
Material material = Instantiate(Resources.Load<Material>("UI/Material/RoundedCornersTextureMaterial"));
|
||||
material.SetVector(Shader.PropertyToID("_WidthHeightRadius"), new Vector4(rect.width, rect.height, rect.height, 0));
|
||||
Head.material = material;
|
||||
}
|
||||
}
|
||||
//private void ImageCallBack(string url)
|
||||
//{
|
||||
// if (!App.TextureCache.ContainsKey(url))
|
||||
// App.TextureCache.Add(url, Head.texture);
|
||||
//}
|
||||
|
||||
//IEnumerator DownloadImage(RawImage img, string MediaUrl)
|
||||
//{
|
||||
// if (!App.TextureCache.ContainsKey(MediaUrl))
|
||||
// {
|
||||
// UnityWebRequest request = UnityWebRequestTexture.GetTexture(MediaUrl);
|
||||
// yield return request.SendWebRequest();
|
||||
// if (request.isNetworkError || request.isHttpError)
|
||||
// Debug.Log(request.error);
|
||||
// else
|
||||
// img.texture = ((DownloadHandlerTexture)request.downloadHandler).texture;
|
||||
|
||||
// App.TextureCache.Add(MediaUrl, img.texture);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// img.texture = App.TextureCache["MediaUrl"];
|
||||
// }
|
||||
//}
|
||||
|
||||
public void setCountry(Texture texture)
|
||||
{
|
||||
{
|
||||
Country.texture = texture;
|
||||
//Utils.DisplayImage(StartCoroutine, Country, url);
|
||||
//StartCoroutine(DownloadImage(Country, url));
|
||||
//var rect = ((RectTransform)Country.transform).rect;
|
||||
//Material material = Instantiate(Resources.Load<Material>("UI/Material/RoundedCornersTextureMaterial"));
|
||||
//material.SetVector(Shader.PropertyToID("_WidthHeightRadius"), new Vector4(rect.width, rect.height, rect.height, 0));
|
||||
//Country.material = material;
|
||||
}
|
||||
}
|
||||
public void setName(string name)
|
||||
{
|
||||
if (!_name.Equals(name))
|
||||
Name.text = name;
|
||||
}
|
||||
|
||||
public void setSpeed(string speed)
|
||||
{
|
||||
if (!_speed.Equals(speed))
|
||||
Speed.text = speed;
|
||||
}
|
||||
|
||||
public void setDistance(string distance)
|
||||
{
|
||||
if (!_distance.Equals(distance))
|
||||
Distance.text = distance;
|
||||
}
|
||||
|
||||
public void setUserId(int userId)
|
||||
{
|
||||
_userId = userId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44fc978b4005ef44da1bdb422373f314
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0b6448d57a2ab249a67f66c160c8293
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04b976b21b69ff640956ca0574491797
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,388 @@
|
||||
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, App.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, App.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)
|
||||
{
|
||||
var result = onlineUserHelper.OnlineUsers.Where(u => routeId.Contains(u.RouteId) && u.CompetitionId == 0).ToList();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//比赛中的人只能看到当前比赛的人
|
||||
public static List<OnlineUser> GetCompetitionOnlineUsers(int competitionId)
|
||||
{
|
||||
var result = onlineUserHelper.OnlineUsers.Where(u => u.CompetitionId == competitionId).ToList();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<OnlineUser> GetCompetitionOnlineRanking(int competitionId,int pageIndex = 1,int pageSize = 5)
|
||||
{
|
||||
var result = onlineUserHelper.OnlineUsers.Where(u => u.CompetitionId == competitionId).OrderByDescending(c=>c.EndDistance).ToList();
|
||||
|
||||
var list = result.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
|
||||
//TODO:
|
||||
return list;
|
||||
}
|
||||
|
||||
public static int GetNearRiderCount()
|
||||
{
|
||||
return onlineUserHelper.OnlineUsers.Count();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取附近的人(当前在线的所有人)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IList<NearRiderModel> 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 == App.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 = App.Host + $"User/GetCountryImg?userid={n.Item2.Id}",
|
||||
IsSelf = n.Item2.IsSelf,
|
||||
Id = n.Item2.Id,
|
||||
Country = n.Item2.Country,
|
||||
}).ToList();
|
||||
return nearData;
|
||||
//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 == App.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f01b9ae72517c36488f04fdbbb889f71
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 = App.TcpAddress;
|
||||
_tcpClient = new PfTcpClient(iPEndPoint.Address.ToString(), iPEndPoint.Port, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d27070ad7cfef3418e8f764a42c08a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 = App.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();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 170d4696cbfb82743a9189608d3a162a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class NoDeviceScript: MonoBehaviour
|
||||
{
|
||||
Button cancelButton;
|
||||
Button confirmButton;
|
||||
CyclingController cyclingController;
|
||||
private void Start()
|
||||
{
|
||||
cyclingController = FindObjectOfType<CyclingController>();
|
||||
cancelButton = transform.Find("CloseButton").GetComponent<Button>();
|
||||
confirmButton = transform.Find("SaveButton").GetComponent<Button>();
|
||||
UIManager.AddEvent(cancelButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, Cancel);
|
||||
UIManager.AddEvent(confirmButton.gameObject, UnityEngine.EventSystems.EventTriggerType.PointerClick, Confirm);
|
||||
}
|
||||
private void Cancel(BaseEventData baseEventData)
|
||||
{
|
||||
transform.gameObject.SetActive(false);
|
||||
}
|
||||
private void Confirm(BaseEventData baseEventData)
|
||||
{
|
||||
transform.gameObject.SetActive(false);
|
||||
var pFUIPanel = transform.parent.GetComponent<PFUIPanel>();
|
||||
cyclingController.ShowDevice(pFUIPanel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48e8de0b3f98fd343baced2ca18f9305
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,80 @@
|
||||
using DG.Tweening;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class NumberDotween:MonoBehaviour
|
||||
{
|
||||
private Sequence mScoreSequence;
|
||||
private Sequence mProgressSequence;
|
||||
private Text text;
|
||||
private float mOldScore = 0;
|
||||
private float mOldScoreNew = 0;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
//函数内初始化
|
||||
mScoreSequence = DOTween.Sequence();
|
||||
mProgressSequence = DOTween.Sequence();
|
||||
//函数内设置属性
|
||||
mScoreSequence.SetAutoKill(false);
|
||||
mProgressSequence.SetAutoKill(false);
|
||||
text = transform.GetComponent<Text>();
|
||||
}
|
||||
private double temp = 0;
|
||||
private int index = -1;
|
||||
private int indexNew = -1;
|
||||
public void AnimateNum(float newScore,double totalDistance,int currentIndex, int digit, string format,Image process)
|
||||
{
|
||||
if (currentIndex != indexNew)
|
||||
{
|
||||
indexNew = currentIndex;
|
||||
process.fillAmount = 1;
|
||||
StartCoroutine(CompleteFill(process));
|
||||
}
|
||||
else
|
||||
{
|
||||
mProgressSequence.Append(DOTween.To(delegate (float value)
|
||||
{
|
||||
process.fillAmount = (float)(value / totalDistance);
|
||||
}, mOldScoreNew, newScore, 1f));
|
||||
//将更新后的值记录下来, 用于下一次滚动动画
|
||||
mOldScoreNew = newScore;
|
||||
}
|
||||
}
|
||||
|
||||
public void AnimateNumText(float newScore, double totalDistance, int currentIndex, int digit, string format, Image process)
|
||||
{
|
||||
if (currentIndex != index)
|
||||
{
|
||||
text.text = string.Format(format, totalDistance);
|
||||
index = currentIndex;
|
||||
mOldScore = (float)totalDistance;
|
||||
}
|
||||
else
|
||||
{
|
||||
mScoreSequence.Append(DOTween.To(delegate (float value)
|
||||
{
|
||||
//if (value != newScore)
|
||||
{
|
||||
temp = Math.Round(value, digit);
|
||||
//向Text组件赋值
|
||||
text.text = string.Format(format, temp);
|
||||
}
|
||||
}, mOldScore, newScore, 1f));
|
||||
//将更新后的值记录下来, 用于下一次滚动动画
|
||||
mOldScore = newScore;
|
||||
}
|
||||
}
|
||||
IEnumerator CompleteFill(Image process)
|
||||
{
|
||||
yield return new WaitForSeconds(0.3f);
|
||||
mOldScoreNew = 0;
|
||||
process.fillAmount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc35dd113658adb47867d8c21c22fb4a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,185 @@
|
||||
using Assets.Scenes.Ride.Scripts.Model;
|
||||
using Assets.Scripts;
|
||||
using Assets.Scripts.Apis.Models;
|
||||
using ChartAndGraph;
|
||||
using DG.Tweening;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using System.Linq;
|
||||
|
||||
namespace Assets.Scenes.Ride.Scripts
|
||||
{
|
||||
public class OnlinePlayerController : AbstractPlayer
|
||||
{
|
||||
public PlayerController _playerController;
|
||||
RawImage head;
|
||||
Image arrowImage;
|
||||
GameObject infoPanel;
|
||||
Transform uiObject;
|
||||
|
||||
string nickName;
|
||||
string weightKgStr;
|
||||
|
||||
protected override void Init()
|
||||
{
|
||||
base.Init();
|
||||
currentlatlong = mainController.GetCenterCoordinate();
|
||||
_playerController = FindObjectOfType<PlayerController>();
|
||||
//创建UI
|
||||
uiObject = transform.parent.Find("SingleUI/Panel/ArrowList");
|
||||
arrowImage = Instantiate(Resources.Load<Image>("UI/Prefab/Ride/ReviewArrow"), uiObject);
|
||||
arrowImage.color = new Color(0.1529412f, 0.8745098f, 0.8901961f);
|
||||
}
|
||||
public override bool GetStart()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
protected override void Compute()
|
||||
{
|
||||
currentlatlong = mainController.Along(totalDistance);//下一个坐标
|
||||
|
||||
diff = Math.Round((totalDistance - _playerController.TotalDistance) * 1000, 0);
|
||||
}
|
||||
double diff = 0;
|
||||
public void SetDataSource(double _totalDistance, double _distance,string Name,double weightKg,int index=0)
|
||||
{
|
||||
totalDistance = _totalDistance;
|
||||
distance = _distance;
|
||||
speed = distance*3600;
|
||||
nickName = Name;
|
||||
weightKgStr = weightKg.ToString("f2") + "W/KG";
|
||||
CurrentIndex = index;
|
||||
}
|
||||
|
||||
private string headUrl;
|
||||
public void SetHead(string url )
|
||||
{
|
||||
headUrl = url;
|
||||
}
|
||||
|
||||
public void ShowInfoPanel(Vector3 playerScreenPos)
|
||||
{
|
||||
if (infoPanel == null)
|
||||
{
|
||||
infoPanel = Instantiate(Resources.Load<GameObject>("UI/Prefab/Ride/OnlineInfoPanel"), uiObject);
|
||||
}
|
||||
var headPos = infoPanel.transform.Find("Head").position;
|
||||
var infoPos = playerScreenPos + new Vector3(150f, 60f, 0f);
|
||||
((RectTransform)infoPanel.transform).position = infoPos;
|
||||
CreateInfoLine(playerScreenPos, headPos);
|
||||
var infoHead = infoPanel.transform.Find("Head").GetComponent<RawImage>();
|
||||
if (head != null)
|
||||
{
|
||||
infoHead.texture = head.texture;
|
||||
}
|
||||
var infoName = infoPanel.transform.Find("Name").GetComponent<Text>();
|
||||
infoName.text = nickName;
|
||||
|
||||
var infoDistance = infoPanel.transform.Find("Distance").GetComponent<Text>();
|
||||
if (_playerController != null)
|
||||
{
|
||||
infoDistance.text = diff > 0? $"+{diff}M" : $"{diff}M";
|
||||
}
|
||||
var infoWKG = infoPanel.transform.Find("WKG").GetComponent<Text>();
|
||||
infoWKG.text = weightKgStr;
|
||||
|
||||
var speedText = infoPanel.transform.Find("Speed").GetComponent<Text>();
|
||||
speedText.text = speed.ToString("f1")+"KM/H";
|
||||
}
|
||||
|
||||
public void RemoveSelf()
|
||||
{
|
||||
arrowImage.gameObject?.Destroy();
|
||||
headPanel?.Destroy();
|
||||
infoPanel?.Destroy();
|
||||
transform.gameObject.Destroy();
|
||||
}
|
||||
|
||||
protected override void AfterExcute()
|
||||
{
|
||||
var playerScreenPos = Camera.main.WorldToScreenPoint(transform.position);
|
||||
((RectTransform)arrowImage.transform).position = playerScreenPos;
|
||||
|
||||
if (IsShowInfo)
|
||||
{
|
||||
ShowInfoPanel(playerScreenPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (infoPanel == null)
|
||||
return;
|
||||
_directionsGO?.Destroy();
|
||||
infoPanel.transform.GetComponent<CanvasGroup>().DOFade(0, 1).onComplete += () => {
|
||||
IsShowInfo = false;
|
||||
infoPanel?.Destroy();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
GameObject _directionsGO;
|
||||
void CreateInfoLine(Vector3 startPos,Vector3 endPos)
|
||||
{
|
||||
if (_directionsGO != null)
|
||||
{
|
||||
_directionsGO.Destroy();
|
||||
}
|
||||
startPos = Camera.main.ScreenToWorldPoint(startPos);
|
||||
//endPos.x -= 120f;
|
||||
endPos = Camera.main.ScreenToWorldPoint(endPos);
|
||||
|
||||
_directionsGO = new GameObject("InfoLinerender");
|
||||
_directionsGO.transform.SetParent(transform);
|
||||
var lineRender = _directionsGO.AddComponent<LineRenderer>();
|
||||
//lineRender.material = new Material(Shader.Find("Sprites/Default"));
|
||||
lineRender.material = Resources.Load<Material>("UI/Material/4");
|
||||
lineRender.endColor = new Color(0.1529412f, 0.8745098f, 0.8901961f, 1f);
|
||||
lineRender.startColor = new Color(0.1529412f, 0.8745098f, 0.8901961f, 1f);
|
||||
|
||||
//设置宽度
|
||||
lineRender.startWidth = 0.2f;
|
||||
lineRender.endWidth = 0.2f;
|
||||
lineRender.positionCount = 2;
|
||||
lineRender.SetPositions(new Vector3[] { startPos, endPos });
|
||||
lineRender.loop = false;
|
||||
lineRender.numCapVertices = 10;
|
||||
lineRender.numCornerVertices = 10;
|
||||
}
|
||||
|
||||
protected override void MoveGraphHead()
|
||||
{
|
||||
var itemIndex = chartDataSourceScript.GetViewIndex(CurrentIndex);
|
||||
var m = graph.DataSource.GetPoint("Player 2", itemIndex);
|
||||
|
||||
graph.PointToWorldSpace(out Vector3 itemPosition, m.x, m.y, "Player 2");
|
||||
itemPosition.x -= 12f;
|
||||
itemPosition.y += 5f;
|
||||
|
||||
if (headPanel == null)
|
||||
{
|
||||
headPanel = Instantiate(Resources.Load<GameObject>("UI/Prefab/Ride/OnlineHeadPanel"));
|
||||
headPanel.transform.SetParent(graph.transform);
|
||||
headPanel.transform.localScale = new Vector3(0.8f, 0.8f, 0.8f);
|
||||
headPanel.transform.position = itemPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
headPanel.transform.position = new Vector3(itemPosition.x, itemPosition.y, 0);
|
||||
//headPanel.transform.DOMove(new Vector3(itemPosition.x, itemPosition.y, 0), 1);
|
||||
}
|
||||
|
||||
if (head == null)
|
||||
{
|
||||
head = headPanel.GetComponentInChildren<RawImage>();
|
||||
if (!string.IsNullOrEmpty(headUrl))
|
||||
{
|
||||
Utils.DisplayImage(head, headUrl, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
headPanel.transform.Find("DefaultHead").gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 281c3f68a13a427499876dec554c3223
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loaded 100 of 151 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user