-
-
Save CoffeepotCoder/5fb5b4b2ffdd0a86ced3163921f95468 to your computer and use it in GitHub Desktop.
Chronobelt: Into the Beyond
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
/// <summary> | |
/// Defines the dimensions of the belt, and populates it with rubble | |
/// </summary> | |
public class RubbleBelt : MonoBehaviour | |
{ | |
[Header("Orbit Config")] | |
[SerializeField] CircleCollider2D _collider; | |
[SerializeField] OrbitalLine _orbitalLine; | |
[SerializeField] float _radiusOffset; | |
[SerializeField] float _posVariance; | |
[SerializeField] float _orbitSpeed = 0.25f; | |
[SerializeField] float _orbitSpeedMax = 2.75f; | |
[SerializeField] float _orbitSpeedStep = 0.5f; | |
[SerializeField] int _rubbleInOrbit; | |
[SerializeField] GameObject[] _rubblePrefabs; | |
void Start() | |
{ | |
var radius = GetComponent<CircleCollider2D>().radius + _radiusOffset; | |
var degree = 360 / _rubbleInOrbit; | |
GetComponent<OrbitalLine>().DrawCircle(radius); | |
for (int i = 0; i <= _rubbleInOrbit; i++) | |
{ | |
var spoke = new GameObject($"Rubble ({i})"); | |
spoke.transform.parent = transform; | |
spoke.transform.localPosition = Vector3.zero; | |
spoke.transform.localEulerAngles = new Vector3(0, 0, degree * i); | |
var rubble = Instantiate(_rubblePrefabs[Random.Range(0, _rubblePrefabs.Length)], spoke.transform); | |
rubble.transform.localPosition = new Vector3(Random.Range(-_posVariance, _posVariance), Random.Range(-_posVariance, _posVariance) + radius, 1f); | |
} | |
transform.localEulerAngles = Vector3.forward * Random.Range(0, 360); | |
var step = Mathf.CeilToInt(_orbitSpeedMax / _orbitSpeedStep); | |
_orbitSpeed = _orbitSpeedStep * Random.Range(-step, step); | |
if (_orbitSpeed == 0 || _orbitSpeed % 0.5f == 0) | |
_orbitSpeed += 0.25f; | |
} | |
void Update() | |
=> transform.Rotate(0, 0, _orbitSpeed * Time.deltaTime); | |
void OnMouseOver() | |
{ | |
_orbitSpeed = Mathf.Clamp(_orbitSpeed - Input.mouseScrollDelta.y * _orbitSpeedStep, -_orbitSpeedMax, _orbitSpeedMax); | |
if (_orbitSpeed == 0f) | |
_orbitSpeed = 0.25f * -Input.mouseScrollDelta.y; | |
} | |
void OnValidate() | |
{ | |
_collider = GetComponent<CircleCollider2D>(); | |
_orbitalLine = GetComponent<OrbitalLine>(); | |
_orbitalLine.DrawCircle(_collider.radius + _radiusOffset); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
/// <summary> | |
/// Self-disabling and Self-randomizing space rocks | |
/// </summary> | |
public class Rubble : MonoBehaviour | |
{ | |
Vector3 _rotationStep; | |
SpriteRenderer _renderer; | |
CircleCollider2D _collider; | |
void OnEnable() | |
{ | |
_collider = GetComponent<CircleCollider2D>(); | |
_renderer = GetComponent<SpriteRenderer>(); | |
_renderer.flipX = Random.Range(0, 2) == 0; | |
transform.localScale = Vector3.one * Random.Range(0.75f, 1.25f); | |
_rotationStep = Vector3.forward * Random.Range(-1f, 1f); | |
} | |
void FixedUpdate() | |
{ | |
if (_renderer.isVisible) | |
transform.Rotate(_rotationStep); | |
} | |
void OnBecameInvisible() | |
=> _collider.enabled = false; | |
void OnBecameVisible() | |
=> _collider.enabled = true; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
/// <summary> | |
/// Draws a circle along the RubbleBelt orbital radius as an interactive visual guide for the player | |
/// </summary> | |
[RequireComponent(typeof(LineRenderer))] | |
public class OrbitalLine : MonoBehaviour | |
{ | |
public void DrawCircle(float radius) | |
{ | |
var segments = 360; | |
var line = gameObject.GetComponent<LineRenderer>(); | |
line.useWorldSpace = false; | |
line.positionCount = segments + 1; | |
var pointCount = segments + 1; // add extra point to make startpoint and endpoint the same to close the circle | |
var points = new Vector3[pointCount]; | |
for (int i = 0; i < pointCount; i++) | |
{ | |
var rad = Mathf.Deg2Rad * (i * 360f / segments); | |
points[i] = new Vector3(Mathf.Sin(rad) * radius, Mathf.Cos(rad) * radius, 0); | |
} | |
line.SetPositions(points); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.UI; | |
/// <summary> | |
/// Deploys colonists along their forward vector at a variable interval | |
/// Displays remaining colonists with a text UI element | |
/// </summary> | |
public class ColonistSpawner : MonoBehaviour | |
{ | |
[Header("Dependencies")] | |
[SerializeField] GameObject _colonistPrefab; | |
[SerializeField] AudioClip[] _deploymentClips; | |
[SerializeField] AudioSource _source; | |
[SerializeField] Text _colonistText; | |
[Header("Configuration")] | |
[SerializeField] float _mouseDeltaSensitivity = 0.25f; | |
[SerializeField] float _colonistSpeedMin = .5f; | |
[SerializeField] float _colonistSpeedMax = 2.5f; | |
[SerializeField] float _colonistSpeed = 1f; | |
[SerializeField] float _spawnInterval = 5f; | |
[SerializeField] internal int _colonistsRemaining = 10; | |
float _spawnTimer; | |
void OnMouseOver() | |
{ | |
if (Input.mouseScrollDelta != Vector2.zero) | |
{ | |
_colonistSpeed = Mathf.Clamp(_colonistSpeed + Input.mouseScrollDelta.y * _mouseDeltaSensitivity, _colonistSpeedMin, _colonistSpeedMax); | |
var colonists = GetComponentsInChildren<Rigidbody2D>(); | |
foreach (var colonist in colonists) | |
colonist.velocity = colonist.transform.up * _colonistSpeed; | |
} | |
} | |
void Start() | |
=> _spawnTimer = Random.Range(0f, _colonistSpeedMin); | |
void Update() | |
{ | |
if (_colonistsRemaining > 0 && (_spawnTimer += Time.deltaTime) >= _spawnInterval / _colonistSpeed) | |
{ | |
_colonistText.text = $"{--_colonistsRemaining}"; | |
_source.PlayOneShot(_deploymentClips[Random.Range(0, _deploymentClips.Length)]); | |
_spawnTimer = Random.Range(0f, 0.25f); | |
var colonist = Instantiate(_colonistPrefab, transform); | |
colonist.transform.Rotate(Vector3.forward * Random.Range(-2.5f, 2.5f)); | |
var rb = colonist.GetComponent<Rigidbody2D>(); | |
rb.velocity = colonist.transform.up * _colonistSpeed; | |
colonist.transform.localPosition = Vector3.forward; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
/// <summary> | |
/// Colonists that reach the surface contribute to player score | |
/// </summary> | |
public class Colonist : MonoBehaviour | |
{ | |
[SerializeField] GameObject _explosionPrefab; | |
[SerializeField] SpriteRenderer _renderer; | |
void OnCollisionEnter2D(Collision2D collision) | |
{ | |
if (collision.gameObject.CompareTag("Planet")) | |
{ | |
FindObjectOfType<ScoreKeeper>().AddScore(); | |
GetComponent<Rigidbody2D>().velocity = Vector2.zero; | |
transform.SetParent(collision.gameObject.transform); | |
Destroy(gameObject, 1f); | |
return; | |
} | |
Instantiate(_explosionPrefab, transform.position, Quaternion.identity); | |
Destroy(gameObject); | |
} | |
void OnCollisionStay2D(Collision2D collision) | |
=> _renderer.color = Color.Lerp(_renderer.color, Color.clear, Time.deltaTime); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
/// <summary> | |
/// Draws a line along the forward vector of the Spawner as an interactive visual guide for the player | |
/// </summary> | |
public class TrajectoryLine : MonoBehaviour | |
{ | |
[SerializeField] float _lineLength = 2.5f; | |
[SerializeField] LineRenderer _line; | |
void Start() | |
{ | |
_line.SetPosition(0, transform.position); | |
_line.SetPosition(1, transform.position + transform.up * _lineLength); | |
} | |
void OnValidate() | |
{ | |
_line = GetComponent<LineRenderer>(); | |
Start(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
/// <summary> | |
/// Emphasizes LineRenderer when under the mouse pointer | |
/// </summary> | |
[RequireComponent(typeof(LineRenderer))] | |
public class LineMouseModifier : MonoBehaviour | |
{ | |
[SerializeField] Color _mouseOverColorStart; | |
[SerializeField] Color _mouseOverColorEnd; | |
[SerializeField] float _mouseOverWidth; | |
[SerializeField] Color _mouseExitColorStart; | |
[SerializeField] Color _mouseExitColorEnd; | |
[SerializeField] float _mouseExitWidth; | |
[SerializeField] float _lerpRate = 2.5f; | |
Color _targetColorStart, _targetColorEnd = Color.clear; | |
float _targetWidth = 0f; | |
LineRenderer _line; | |
void Start() | |
{ | |
_line = GetComponent<LineRenderer>(); | |
_targetColorStart = _mouseExitColorStart; | |
_targetColorEnd = _mouseExitColorEnd; | |
_targetWidth = _mouseExitWidth; | |
} | |
void Update() | |
{ | |
_line.startColor = Color.Lerp(_line.startColor, _targetColorStart, _lerpRate * Time.deltaTime); | |
_line.endColor = Color.Lerp(_line.endColor, _targetColorEnd, _lerpRate * Time.deltaTime); | |
_line.startWidth = Mathf.Lerp(_line.startWidth, _targetWidth, _lerpRate * Time.deltaTime); | |
_line.endWidth = Mathf.Lerp(_line.endWidth, _targetWidth, _lerpRate * Time.deltaTime); | |
} | |
void OnMouseEnter() | |
{ | |
_targetColorStart = _mouseOverColorStart; | |
_targetColorEnd = _mouseOverColorEnd; | |
_targetWidth = _mouseOverWidth; | |
} | |
void OnMouseExit() | |
{ | |
_targetColorStart = _mouseExitColorStart; | |
_targetColorEnd = _mouseExitColorEnd; | |
_targetWidth = _mouseExitWidth; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.SceneManagement; | |
using UnityEngine.UI; | |
/// <summary> | |
/// Tracks and displays score | |
/// </summary> | |
public class ScoreKeeper : MonoBehaviour | |
{ | |
ColonistSpawner[] _spawners; | |
int _totalColonists; | |
int _colonistsSaved = 0; | |
int _highScore; | |
Text _scoreText; | |
void Start() | |
{ | |
_spawners = FindObjectsOfType<ColonistSpawner>(); | |
foreach (var spawner in _spawners) | |
_totalColonists += spawner._colonistsRemaining; | |
_scoreText = GetComponent<Text>(); | |
_highScore = PlayerPrefs.GetInt(SceneManager.GetActiveScene().name, 0); | |
_scoreText.text = $"{_colonistsSaved:00} / {_totalColonists:00} (Best: {_highScore:00} / {_totalColonists:00}"; | |
} | |
void OnDisable() | |
{ | |
if (_colonistsSaved > PlayerPrefs.GetInt(SceneManager.GetActiveScene().name, 0)) | |
PlayerPrefs.SetInt(SceneManager.GetActiveScene().name, _colonistsSaved); | |
} | |
internal void AddScore() | |
{ | |
if (++_colonistsSaved > _highScore) | |
_highScore = _colonistsSaved; | |
_scoreText.text = $"{_colonistsSaved:00} / {_totalColonists:00} (Best: {_highScore:00} / {_totalColonists:00}"; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.SceneManagement; | |
/// <summary> | |
/// Manages game logic and flow | |
/// </summary> | |
internal class GameManager : MonoBehaviour | |
{ | |
static GameManager Instance; | |
[SerializeField] GameObject _pauseMenu; | |
void Awake() | |
{ | |
if (Instance == null) | |
{ | |
Instance = this; | |
DontDestroyOnLoad(gameObject); | |
} | |
else Destroy(gameObject); | |
Time.timeScale = _pauseMenu.activeSelf ? 0 : 1; | |
} | |
void Update() | |
{ | |
if (Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.Space)) | |
TogglePause(); | |
} | |
public void TogglePause() | |
{ | |
_pauseMenu.SetActive(!_pauseMenu.activeSelf); | |
Time.timeScale = _pauseMenu.activeSelf ? 0 : 1; | |
} | |
public void LoadScene(int index) | |
=> SceneManager.LoadScene(index); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment