Files
GeoSusGame/Assets/GameManager/GameManager_Input.cs

254 lines
9.8 KiB
C#

using UnityEngine;
using GeoSus.Client;
using System;
using System.Collections;
namespace Subsystems
{
internal class CoroutineHost : MonoBehaviour
{
public CoroutineHost() { }
}
internal enum GPSState
{
Uninitialized,
Initializing,
Running,
Failed
}
public static class PositonExtensions
{
public static Position ToLocal(this Position position, Position center)
{
double latDiff = position.Lat - center.Lat;
double lonDiff = position.Lon - center.Lon;
double metersPerDegreeLat = 111320.0;
double metersPerDegreeLon = 111320.0 * Math.Cos(center.Lat * Math.PI / 180.0);
float x = (float)(lonDiff * metersPerDegreeLon);
float z = (float)(latDiff * metersPerDegreeLat);
return new Position(z, x);
}
public static Vector3 ToLocalVector3(this Position position, Position center)
{
return position.ToLocal(center).ToVector3(); //TODO: Implementace v subsystemech
}
public static Vector3 ToVector3(this Position position)
{
return new Vector3((float)position.Lon, 0, (float)position.Lat); //TODO: Implementace v subsystemech
}
public static double DistanceTo(this Vector3 pos, Vector3 other)
{
return Math.Sqrt((other.x - pos.x) * (other.x - pos.x) + (other.z - pos.z) * (other.z - pos.z));
}
}
public class GameManager_Input
{
private GameClient _gameClient;
private Position _currentPosition;
private Position _lastSentPosition;
private GameObject _player;
private bool _testMode;
private GPSState _GPSState = GPSState.Uninitialized;
private float _speed = 0.00001f;
private Position _mapCenter;
private CoroutineHost _coroutineHost = new CoroutineHost();
public GameManager_Input(GameClient gameClient, GameObject player, bool testMode)
{
_gameClient = gameClient;
_player = player;
_testMode = testMode;
}
public void positionCheck()
{
try
{
if (_gameClient.CurrentLobbyState.Phase == GamePhase.Playing)
{
if (_testMode)
{
if (_currentPosition == null || _currentPosition == new Position(0, 0))
{
//Init blok
_currentPosition = _gameClient.CurrentLobbyState.MapData.Center;
_mapCenter = _gameClient.CurrentLobbyState.MapData.Center;
_lastSentPosition = _currentPosition;
}
TestPlayerPosition();
}
else
{
if (_GPSState == GPSState.Uninitialized)
{
_coroutineHost.StartCoroutine(InitiallizeGPS());
return;
}
else if (_GPSState == GPSState.Initializing)
{
return;
}
else if (_GPSState == GPSState.Running)
{
try
{
if (_currentPosition != _lastSentPosition)
{
_gameClient.UpdatePosition(_currentPosition);
_lastSentPosition = _currentPosition;
_player.transform.position = _currentPosition.ToLocalVector3(_mapCenter);
_player.transform.rotation = Quaternion.Euler(0, (float)CalculateHeading(_lastSentPosition.ToLocalVector3(_mapCenter), _currentPosition.ToLocalVector3(_mapCenter)), 0);
}
}
catch (Exception ex)
{
Debug.Log(ex);
}
}
else
{
Debug.Log("GPS failed, trying again...");
_GPSState = GPSState.Uninitialized;
}
}
}
}
catch (NullReferenceException ex) { Debug.Log(ex); }
}
private void TestPlayerPosition()
{
double x = Input.GetAxis("Horizontal");
double y = Input.GetAxis("Vertical");
Debug.Log($"Input: {x}, {y}");
_currentPosition = new Position( _lastSentPosition.Lat + y * _speed, _lastSentPosition.Lon + x * _speed);
Debug.Log($"Current Position: {_currentPosition.Lat}, {_currentPosition.Lon}");
var localCurrent = _currentPosition.ToLocalVector3(_mapCenter);
Debug.Log($"Local Current Position: {localCurrent}");
var heading = CalculateHeading(_lastSentPosition.ToLocalVector3(_mapCenter), localCurrent);
if (heading != null)
{
Debug.Log($"Heading: {heading}");
_player.transform.rotation = Quaternion.Euler(0, (float)heading, 0);
}
_player.transform.position = localCurrent;
try
{
if (_currentPosition != _lastSentPosition)
{
_gameClient.UpdatePosition(_currentPosition);
_lastSentPosition = _currentPosition;
}
}
catch
{
_gameClient.UpdatePosition(_currentPosition);
_lastSentPosition = _currentPosition;
}
}
private double? CalculateHeading(Vector3 first, Vector3 second)
{
double? heading = null;
if ((first - second).magnitude == 0)
{
return null;
}
else if (first.x == second.x && first.z < second.z)
{
return 0;
}
else if (first.x == second.x && first.z > second.z)
{
return 180;
}
else if (first.x > second.x && first.z == second.z)
{
return 270;
}
else if (first.x < second.x && first.z == second.z)
{
return 90;
}
else if (first.x < second.x && first.z < second.z)
{
heading = Math.Asin((second.z - first.z) / first.DistanceTo(second));
return (heading * 180) / Math.PI;
}
else if (first.x < second.x && first.z > second.z)
{
heading = Math.Asin((second.z - first.z) / first.DistanceTo(second));
return (heading * 180) / Math.PI + 180;
}
else if (first.x > second.x && first.z < second.z)
{
heading = Math.Asin((second.z - first.z) / first.DistanceTo(second));
return (heading * 180) / Math.PI - 90;
}
else if (first.x > second.x && first.z > second.z)
{
heading = Math.Asin((second.z - first.z) / first.DistanceTo(second));
return (heading * 180) / Math.PI - 90;
}
else
{
return heading;
}
}
IEnumerator InitiallizeGPS()
{
_GPSState = GPSState.Initializing;
if (!Input.location.isEnabledByUser)
{
Debug.LogError("Location not enabled on device or app does not have permission to access location");
}
// Starts the location service.
float desiredAccuracyInMeters = 10f;
float updateDistanceInMeters = 10f;
Input.location.Start(desiredAccuracyInMeters, updateDistanceInMeters);
// Waits until the location service initializes
int maxWait = 20;
while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
{
yield return new WaitForSeconds(1);
maxWait--;
}
// If the service didn't initialize in 20 seconds this cancels location service use.
if (maxWait < 1)
{
_GPSState = GPSState.Failed;
Debug.LogError("Timed out");
yield break;
}
_GPSState = GPSState.Running;
yield return _coroutineHost.StartCoroutine(GPSService());
}
IEnumerator GPSService()
{
// Check if the user has location service enabled.
// If the connection failed this cancels location service use.
if (Input.location.status == LocationServiceStatus.Failed)
{
Debug.LogError("Unable to determine device location");
yield break;
}
else
{
// If the connection succeeded, this retrieves the device's current location and displays it in the Console window.
_currentPosition = new Position(Input.location.lastData.latitude, Input.location.lastData.longitude);
Debug.Log("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp);
yield return new WaitForSeconds(5f);
}
// Stops the location service if there is no need to query location updates continuously.
yield return _coroutineHost.StartCoroutine(GPSService());
}
}
}