LD50/Assets/Scripts/Player.cs
2022-04-05 02:09:50 +02:00

276 lines
9.1 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Player : Manager<Player>
{
public float ThrustForce = 10; // in m/s^2
public float SteeringFactor = 10.0f;
public float UprightMultiplier = 10.0f;
public float DragForce = 0.75f;
public AnimationCurve SlopeDragCurve;
public Vector3 horizontalVelocity = Vector2.zero;
private BoxCollider BenchBoxCollider;
[SerializeField]
private ParticleSystem thrusterParticleSystemLeft;
[SerializeField]
private ParticleSystem thrusterParticleSystemRight;
public ParticleSystem Explosion;
[SerializeField]
private float dynamiteCountdownStart = 3.0f;
private float dynamiteCountDown;
private bool disableInput = false;
public float DynamiteCountDown => dynamiteCountDown;
public float Fuel = 1.0f;
public float FuelConsumptionPerSecond = 0.01f;
public float FuelConsumptionPerSecondBase = 0.01f;
private float score = 0.0f;
public float Score => score;
public LayerMask RayLayerMask;
IEnumerator SecondDelayInterval()
{
while(true)
{
yield return new WaitForSeconds(1.0f);
if(dynamiteCountDown > 0)
{
if(horizontalVelocity.magnitude < 0.1f)
{
dynamiteCountDown -= 1.0f;
AudioManager.Instance.GetAudioSource(AudioClip.CountdownBeep).Play();
}
else
{
dynamiteCountDown = dynamiteCountdownStart;
}
}
if(dynamiteCountDown <= 0)
{
disableInput = true;
dynamiteCountDown = 0;
if(GameStateManager.Instance.GameState == GameState.Play)
{
Debug.Log("GameStateChange => Play => GameOver");
GameStateManager.Instance.SetGameState(GameState.GameOver);
}
}
}
}
private AudioSource audioSourceSledge;
private AudioSource audioSourceSpin;
private AudioSource audioSourceRoar;
protected void Start()
{
GameStateManager.Instance.OnGameStateChangedEvent.AddListener(OnGameStateChanged);
BenchBoxCollider = GetComponentInChildren<BoxCollider>();
dynamiteCountDown = dynamiteCountdownStart;
audioSourceSpin = AudioManager.Instance.GetAudioSource(AudioClip.TurbineSpin);
audioSourceRoar = AudioManager.Instance.GetAudioSource(AudioClip.TurbineRoar);
audioSourceSledge = AudioManager.Instance.GetAudioSource(AudioClip.SnowSlideSledge);
}
public void OnGameStateChanged(GameState newState, GameState oldState)
{
Debug.Log("OnGameStateChanged "+newState);
if(newState == GameState.Play)
{
StartCoroutine(SecondDelayInterval());
}
}
protected void OnDestroy()
{
GameStateManager.Instance.OnGameStateChangedEvent.RemoveListener(OnGameStateChanged);
}
void FixedUpdate()
{
var gamepad = Gamepad.current;
float throttle = 0;
float steering = 0;
Vector3 localVelocity = this.transform.InverseTransformDirection(horizontalVelocity);
if(!disableInput)
{
throttle += (Keyboard.current.wKey.ReadValue()) + (Keyboard.current.sKey.ReadValue() * -1.0f);
steering += (Keyboard.current.dKey.ReadValue()) + (Keyboard.current.aKey.ReadValue() * -1.0f);
if(gamepad != null)
{
float throttleR = gamepad.rightTrigger.ReadValue();
float throttleL = gamepad.leftTrigger.ReadValue() * -1.0f;
throttle += throttleL + throttleR;
steering += gamepad.leftStick.ReadValue().x;
if(Vector3.Dot(Vector3.forward, localVelocity) < -0.1f)
steering *= -1.0f;
}
}
audioSourceRoar.volume = Mathf.Abs(throttle) * 0.75f;
audioSourceRoar.pitch = 1.05f;
audioSourceSledge.volume = Mathf.Clamp(horizontalVelocity.magnitude, 0.0f, 1.0f);
Fuel -= (Mathf.Abs(throttle) * FuelConsumptionPerSecond + FuelConsumptionPerSecondBase) * Time.fixedDeltaTime;
if(Fuel <= 0)
{
Fuel = 0;
disableInput = true;
}
if(disableInput)
{
audioSourceSpin.volume = 0.0f;
audioSourceRoar.volume = 0.0f;
}
float baseEmission = disableInput ? 0 : 0.1f;
thrusterParticleSystemLeft.emissionRate = (baseEmission + (1.0f - baseEmission) * (throttle - steering * -1.0f)) * 300.0f;
thrusterParticleSystemRight.emissionRate = (baseEmission + (1.0f - baseEmission) * (throttle - steering)) * 300.0f;
this.transform.Rotate(this.transform.up, steering * SteeringFactor * Time.fixedDeltaTime, Space.World);
Vector3 forward = this.transform.forward;
Vector3 horizontalForward = Vector3.Scale(new Vector3(1.0f, 0.0f, 1.0f), forward);
score = Mathf.Round(this.transform.position.z * 1000.0f) / 1000.0f;
horizontalVelocity += this.transform.forward * throttle * ThrustForce * Time.fixedDeltaTime;
horizontalVelocity -= horizontalVelocity * DragForce * Time.fixedDeltaTime;
UIManagerGame.Instance.Fuel = Fuel;
UIManagerGame.Instance.CountdownSeconds = (int)dynamiteCountDown;
UIManagerGame.Instance.Score = score;
this.transform.position += horizontalVelocity;
float OFFSET = 0.5f;
int OFFSET_COUNT_X = 4;
int OFFSET_COUNT_Y = 4;
// TODO: Find better way to smoothly slide across the terrain without bump distortions
int TOTAL_OFFSET_COUNT = OFFSET_COUNT_X * OFFSET_COUNT_Y;
Vector3[] floorRaycastOffsets = new Vector3[TOTAL_OFFSET_COUNT];
for(int x=0;x<OFFSET_COUNT_X; x++)
{
for(int y=0;y<OFFSET_COUNT_Y; y++)
{
float offsetX = ((2.0f / (OFFSET_COUNT_X-1)) * x) - 1.0f;
float offsetY = ((2.0f / (OFFSET_COUNT_Y-1)) * y) - 1.0f;
Vector3 offset = Vector3.up * OFFSET + Vector3.Scale((BenchBoxCollider.size / 2), new Vector3(offsetX, 0.0f, offsetY));
floorRaycastOffsets[x*OFFSET_COUNT_X+y] = offset;
}
}
Vector3[] floorRaycastHitOffsets = new Vector3[TOTAL_OFFSET_COUNT];
Vector3 averageNormal = Vector3.zero;
Vector3 averagePosition = Vector3.zero;
int hitCount = 0;
for(int n=0;n<floorRaycastHitOffsets.Length;n++)
{
Vector3 offset = floorRaycastOffsets[n];
RaycastHit hitInfo;
bool raycastHit = Physics.Raycast(this.transform.TransformPoint(offset), -this.transform.up, out hitInfo, 1000.0f, RayLayerMask.value);
if(raycastHit)
{
hitCount++;
floorRaycastHitOffsets[n] = hitInfo.point;
averageNormal += hitInfo.normal;
averagePosition += hitInfo.point;
}
}
averageNormal *= (1.0f / hitCount);
averagePosition *= (1.0f / hitCount);
if(hitCount == 0)
{
return;
}
Vector3 right = Vector3.Cross(averageNormal, this.transform.forward);
Quaternion rot = Quaternion.AngleAxis(90.0f, right);
Quaternion newRot = this.transform.rotation;
newRot.SetLookRotation(rot * averageNormal, averageNormal);
this.transform.rotation = newRot;
this.transform.position = averagePosition + this.transform.up * 1.0f;
Vector3 slope = Quaternion.AngleAxis(90.0f, Vector3.Cross(Vector3.up, averageNormal).normalized) * averageNormal;
float slopeMagnitude = Vector3.Scale(averageNormal, new Vector3(1.0f, 0.0f, 1.0f)).magnitude;
horizontalVelocity += slope.normalized * Physics.gravity.magnitude * Time.fixedDeltaTime * 0.1f * SlopeDragCurve.Evaluate(slopeMagnitude);
Debug.DrawRay(this.transform.position, slope, Color.yellow);
Debug.DrawRay(this.transform.position, horizontalForward, Color.green);
Debug.DrawRay(this.transform.position, rot * averageNormal, Color.red);
Debug.DrawRay(this.transform.position, averageNormal, Color.blue);
Debug.DrawRay(this.transform.position, right, Color.magenta);
}
protected void OnTriggerEnter(Collider collider)
{
Obstacle o = collider.gameObject.GetComponent<Obstacle>();
if(o != null)
{
o.OnHit(this.gameObject);
if(o.HitRecoilForce != 0.0f)
{
this.horizontalVelocity += -(collider.transform.position - this.transform.position).normalized * o.HitRecoilForce;
}
this.Fuel -= o.DamageOnHit;
}
PickupItem pu = collider.gameObject.GetComponent<PickupItem>();
if(pu != null && pu.PickedUp == false)
{
this.Fuel += pu.Fuel;
if(this.Fuel > 1.0f)
this.Fuel = 1.0f;
pu.OnPickup();
if(disableInput)
disableInput = false;
}
}
}