237 lines
8.0 KiB
C#
Executable File
237 lines
8.0 KiB
C#
Executable File
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
|
|
public class ShipControls : MonoBehaviour {
|
|
public Camera aim;
|
|
public Timing timing;
|
|
|
|
SpaceRaceInput input;
|
|
|
|
Rigidbody rigidBody;
|
|
|
|
Vector3 initialPosition;
|
|
Vector3 initialForce;
|
|
Quaternion initialAim;
|
|
|
|
ForceMode forceMode;
|
|
Vector3 thrust;
|
|
Vector3 strafe;
|
|
|
|
// Camera Controls
|
|
float camPitch;
|
|
float camYaw;
|
|
float clampAngle = 90.0f;
|
|
|
|
public PowerUnit powerUnit = new();
|
|
|
|
void Start() {
|
|
Cursor.lockState = CursorLockMode.Locked;
|
|
rigidBody = GetComponent<Rigidbody>();
|
|
|
|
// just stop the body from being affected by rotation for now
|
|
// until the 3p camera is in to explain why
|
|
rigidBody.freezeRotation = true;
|
|
|
|
initialPosition = rigidBody.transform.position;
|
|
initialAim = rigidBody.transform.rotation;
|
|
initialForce = Vector3.forward;
|
|
|
|
thrust = Vector3.zero;
|
|
strafe = Vector3.zero;
|
|
|
|
camPitch = initialAim.eulerAngles.x;
|
|
camYaw = initialAim.eulerAngles.y;
|
|
forceMode = ForceMode.Acceleration;
|
|
|
|
SetupActions();
|
|
Respawn();
|
|
}
|
|
|
|
// to minimise input lag we poll for the thrust vector every frame and set it
|
|
// same with the camera, we always look around
|
|
void Update() {
|
|
// hot reloading fks up the input
|
|
if (input == null) Start();
|
|
|
|
UpdateCamera();
|
|
thrust = getThrust();
|
|
}
|
|
|
|
void FixedUpdate() {
|
|
// when you hit the trigger... GO
|
|
// needs to be done here in fixedUpdate because otherwise the input is checked on every frame
|
|
// so they will have already hit the button before this tick and they actually start moving
|
|
// aka ripoff
|
|
bool shouldBegin = !timing.timerEnabled && (thrust != Vector3.zero || strafe != Vector3.zero);
|
|
if (shouldBegin) Begin();
|
|
|
|
// the ship being propelled forward
|
|
// this is in world space because of the xform from the camera pos
|
|
//
|
|
rigidBody.AddForce(thrust, forceMode);
|
|
|
|
// moving side to side
|
|
// this is relative because it's easy to just multiply by the strafe vector
|
|
rigidBody.AddRelativeForce(strafe, forceMode);
|
|
|
|
// rotating towards the camera's orientation
|
|
// not being done by a force because of strange behaviour
|
|
// needs investigation
|
|
float step = powerUnit.Stabilisation * Time.fixedDeltaTime;
|
|
|
|
// stop the ship jiggling because of micro camera movement
|
|
if (Quaternion.Angle(aim.transform.rotation, rigidBody.rotation) > 1f)
|
|
rigidBody.rotation = Quaternion.RotateTowards(transform.rotation, aim.transform.rotation, step);
|
|
|
|
if (timing.timerEnabled) {
|
|
powerUnit.Tick();
|
|
}
|
|
}
|
|
|
|
void UpdateCamera() {
|
|
// there's some hokey scaling that went on with the old input
|
|
// we were originally using
|
|
|
|
// in the action mapping the mouse is scaled by 0.05
|
|
// delta *= 0.5f; // Account for scaling applied directly in Windows code by old input system.
|
|
// delta *= 0.1f; // Account for sensitivity setting on old Mouse X and Y axes.
|
|
// def needs to be configurable
|
|
|
|
Vector2 lookDelta = input.ship.look.ReadValue<Vector2>();
|
|
camYaw += lookDelta.x;
|
|
camPitch -= lookDelta.y;
|
|
camPitch = Mathf.Clamp(camPitch, -clampAngle, clampAngle);
|
|
aim.transform.eulerAngles = new Vector3(camPitch, camYaw, 0.0f);
|
|
}
|
|
|
|
// if you are decelerating you can't accelerate as well
|
|
// otherwise you can flip the ship around and
|
|
// decelerate + accelerate against the velocity vector
|
|
// aka cheating?
|
|
Vector3 getThrust() {
|
|
float accelerateInput = input.ship.accelerate.ReadValue<float>();
|
|
float decelerateInput = input.ship.decelerate.ReadValue<float>();
|
|
|
|
// decelerates the ship against the direction it is moving
|
|
if (decelerateInput > 0f) {
|
|
// the velocity is already in world space so we just invert it
|
|
return rigidBody.velocity.normalized * -1f * powerUnit.Deceleration * decelerateInput;
|
|
}
|
|
|
|
// thrust in the direction of the camera
|
|
if (accelerateInput > 0f)
|
|
// transform from the camera's forward vector into world space
|
|
return aim.transform.TransformDirection(Vector3.forward) * powerUnit.Acceleration * accelerateInput;
|
|
|
|
return Vector3.zero;
|
|
}
|
|
|
|
public void Respawn() {
|
|
// IMPORTANT
|
|
// stop the timer before we move the ship or anything
|
|
// otherwise it might generate a checkpoint time
|
|
// for the final sector
|
|
timing.StopTimer();
|
|
|
|
thrust = new Vector3(0.0f, 0.0f, 0.0f);
|
|
transform.position = initialPosition;
|
|
rigidBody.transform.forward = initialForce;
|
|
rigidBody.velocity = new Vector3(0f, 0f, 0f);
|
|
rigidBody.angularVelocity = new Vector3(0f, 0f, 0f);
|
|
rigidBody.transform.rotation = initialAim;
|
|
aim.transform.rotation = initialAim;
|
|
|
|
camPitch = initialAim.eulerAngles.x;
|
|
camYaw = initialAim.eulerAngles.y;
|
|
|
|
powerUnit.Reset();
|
|
}
|
|
|
|
// stuff we have to do right as they come off the line
|
|
void Begin() {
|
|
timing.StartTimer();
|
|
}
|
|
|
|
public float Speed() {
|
|
return rigidBody.velocity.magnitude;
|
|
}
|
|
|
|
public void Damage(float amt, string src) {
|
|
Debug.Log($"Damage {amt} from {src}");
|
|
|
|
bool destroyed = powerUnit.ShieldReduce(amt);
|
|
if (destroyed) {
|
|
Debug.Log($"Ddddestroyed by {src}");
|
|
Respawn();
|
|
}
|
|
}
|
|
|
|
void Deploy(Output output) {
|
|
powerUnit.Deploy(output);
|
|
}
|
|
|
|
// I prefer doing it this way than registering the callbacks etc
|
|
// the control of the actions is more granular
|
|
// plus the callbacks don't have to be public, bonus
|
|
void SetupActions() {
|
|
if (input == null)
|
|
input = new SpaceRaceInput();
|
|
|
|
input.ship.Enable();
|
|
|
|
// we have to update strafe the whole time it's being pressed
|
|
// including setting it back to zero when released
|
|
input.ship.strafe.started += OnStrafe;
|
|
input.ship.strafe.performed += OnStrafe;
|
|
input.ship.strafe.canceled += OnStrafe;
|
|
|
|
// these we only care about the initial press
|
|
input.ship.respawn.started += OnRespawn;
|
|
input.ship.quit.started += OnQuit;
|
|
input.ship.powerUnit1.started += OnPowerUnit1;
|
|
input.ship.powerUnit2.started += OnPowerUnit2;
|
|
input.ship.powerUnit3.started += OnPowerUnit3;
|
|
input.ship.powerUnit4.started += OnPowerUnit4;
|
|
}
|
|
|
|
void OnStrafe(InputAction.CallbackContext ctx) {
|
|
Vector2 str = ctx.ReadValue<Vector2>();
|
|
strafe = new Vector3(str.x, str.y, 0f) * powerUnit.Strafing;
|
|
}
|
|
|
|
void OnQuit(InputAction.CallbackContext ctx) => Application.Quit();
|
|
void OnRespawn(InputAction.CallbackContext ctx) => Respawn();
|
|
|
|
void OnPowerUnit1(InputAction.CallbackContext ctx) => Deploy(Output.Acceleration);
|
|
void OnPowerUnit2(InputAction.CallbackContext ctx) => Deploy(Output.Deceleration);
|
|
void OnPowerUnit3(InputAction.CallbackContext ctx) => Deploy(Output.Strafing);
|
|
void OnPowerUnit4(InputAction.CallbackContext ctx) => Deploy(Output.Shield);
|
|
|
|
void OnDrawGizmosSelected() {
|
|
if (Application.isPlaying == false)
|
|
return;
|
|
|
|
Gizmos.color = Color.red;
|
|
Vector3 right = aim.transform.TransformDirection(Vector3.right) * 10;
|
|
Gizmos.DrawRay(transform.position, right);
|
|
|
|
Gizmos.color = Color.green;
|
|
Vector3 direction = aim.transform.TransformDirection(Vector3.up) * 10;
|
|
Gizmos.DrawRay(transform.position, direction);
|
|
|
|
Gizmos.color = Color.blue;
|
|
Vector3 forward = aim.transform.TransformDirection(Vector3.forward) * 10;
|
|
Gizmos.DrawRay(transform.position, forward);
|
|
|
|
Gizmos.color = Color.yellow;
|
|
Vector3 velocity = rigidBody.velocity;
|
|
Gizmos.DrawRay(transform.position, velocity);
|
|
|
|
Gizmos.color = Color.cyan;
|
|
Gizmos.DrawRay(transform.position, thrust);
|
|
}
|
|
} |