Skip to content

Instantly share code, notes, and snippets.

@benanil
Created June 28, 2022 17:27
Show Gist options
  • Save benanil/92ef6b3c1805c966bbc37ca2c1c08c7d to your computer and use it in GitHub Desktop.
Save benanil/92ef6b3c1805c966bbc37ca2c1c08c7d to your computer and use it in GitHub Desktop.
using UnityEngine;
using System;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
// --- Stair System ---
internal class StairTimePair
{
public float time;
public bool Proceed() { time -= Time.deltaTime; return time < 0; }
public StairTimePair(float time) { this.time = time; }
}
public class WalkSystem
{
private readonly Transform jesusPos;
private Vector3 startPos;
private float targetX;
public WalkSystem(Transform jesusPos)
{
startPos = jesusPos.position;
targetX = startPos.x;
this.jesusPos = jesusPos;
}
public void Update(float speed)
{
startPos.x = Mathf.Lerp(jesusPos.position.x, targetX, Time.deltaTime * speed);
jesusPos.position = startPos;
}
public void Walk(float acelleration)
{
targetX -= acelleration * Time.deltaTime;
}
}
// --- Coin System ---
internal class MovingCoin
{
private const float DefaultLifetime = 1.5f;
public readonly TMPro.TextMeshProUGUI moneyText;
public readonly Transform transform;
public readonly Image image;
private readonly Vector3 targetPos3D;
private readonly Vector3 startPos3D;
public float time;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private float EaseIn(float t) { return t * t; }
public bool Evaluate(float dt)
{
float ellapsedTime = DefaultLifetime - time;
float t = 1 - EaseIn(ellapsedTime / DefaultLifetime);
time -= dt;
transform.position = Camera.main.WorldToScreenPoint(Vector3.LerpUnclamped(startPos3D, targetPos3D, 1-t));
image.color = new Color(1, 1, 1, t);
moneyText.color = new Color(1, 1, 1, t);
return time < 0;
}
public void Finish()
{
image.color = Color.white;
moneyText.color = Color.white;
transform.gameObject.SetActive(false);
}
public MovingCoin(Image coinImage, Vector3 characterPos, int earnedMoney)
{
characterPos += Vector3.down * 4.5f;
transform = coinImage.transform;
startPos3D = characterPos;
targetPos3D = characterPos + (Vector3.up * 2);
moneyText = transform.GetChild(0).GetComponent<TMPro.TextMeshProUGUI>();
moneyText.text = Character.FormatNumber(earnedMoney);
Vector3 screenPos = Camera.main.WorldToScreenPoint(characterPos);
transform.position = screenPos;
image = coinImage;
time = DefaultLifetime;
}
}
public class CoinSystem
{
public const int MaximumCoins = 33;
private readonly Queue<Image> coins = new Queue<Image> (MaximumCoins + 1);
private readonly Queue<MovingCoin> movingCoins = new Queue<MovingCoin> (MaximumCoins + 1);
public CoinSystem() { }
public void PoolCoin(Image coin)
{
coin.gameObject.SetActive(false);
coins.Enqueue(coin);
}
public void DisposeCurrentMovingCoins()
{
while(movingCoins.Count > 0)
{
MovingCoin movingCoin = movingCoins.Dequeue();
movingCoin.Finish();
coins.Enqueue(movingCoin.image);
}
}
public void MoveCoin(Vector3 characterPos, int moneyPerStair)
{
Image coin = coins.Dequeue();
coin.gameObject.SetActive(true);
movingCoins.Enqueue(new MovingCoin(coin, characterPos, moneyPerStair));
}
public void Update(float dt)
{
int removedCoins = 0;
foreach (MovingCoin coin in movingCoins)
{
// Lifetime Ended
if (coin.Evaluate(dt)) removedCoins++;
}
while (removedCoins-- > 0)
{
MovingCoin movingCoin = movingCoins.Dequeue();
movingCoin.Finish();
coins.Enqueue(movingCoin.image);
}
}
}
internal class MovingCombo
{
private const float DefaultLifetime = 2.0f;
public readonly Transform transform;
public readonly TMPro.TextMeshProUGUI text;
private readonly Vector3 targetPos;
private readonly Vector3 startPos;
public float time;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private float EaseIn(float t) { return t * t; }
public bool Evaluate(float dt)
{
float ellapsedTime = DefaultLifetime - time;
float t = 1 - EaseIn(ellapsedTime / DefaultLifetime);
time -= dt;
transform.position = Vector3.LerpUnclamped(startPos, targetPos, 1 - t);
transform.localScale = Vector3.LerpUnclamped(Vector3.one, Vector3.one * 1.2f, 1 - t);
text.color = new Color(1, 1, 1, t);
return time < 0;
}
public void Finish()
{
text.color = Color.white;
transform.gameObject.SetActive(false);
}
public MovingCombo(TMPro.TextMeshProUGUI coinText, Vector3 characterPos, int comboIndex)
{
characterPos += Vector3.down * 4.5f;
transform = coinText.transform;
startPos = Camera.main.WorldToScreenPoint(characterPos + (Vector3.up * 3));
targetPos = Camera.main.WorldToScreenPoint(characterPos + (Vector3.up * 5));
transform.localScale = Vector3.one;
coinText.text = Character.FormatNumber(comboIndex);
text = coinText;
transform.position = startPos;
time = DefaultLifetime;
}
}
public class ComboTextSystem
{
public const int MaximumCoins = 5;
private readonly Queue<TMPro.TextMeshProUGUI> coins = new Queue<TMPro.TextMeshProUGUI>(MaximumCoins + 1);
private readonly Queue<MovingCombo> movingTexts = new Queue<MovingCombo>(MaximumCoins + 1);
public void PoolCoin(TMPro.TextMeshProUGUI coin)
{
coin.gameObject.SetActive(false);
coins.Enqueue(coin);
}
public void DisposeCurrentMovingCoins()
{
while (movingTexts.Count > 0)
{
MovingCombo movingCoin = movingTexts.Dequeue();
movingCoin.Finish();
coins.Enqueue(movingCoin.text);
}
}
public void MoveCoin(Vector3 characterPos, int moneyPerStair)
{
TMPro.TextMeshProUGUI coin = coins.Dequeue();
coin.gameObject.SetActive(true);
movingTexts.Enqueue(new MovingCombo(coin, characterPos, moneyPerStair));
}
public void Update(float dt)
{
int removedCoins = 0;
foreach (MovingCombo coin in movingTexts)
{
// Lifetime Ended
if (coin.Evaluate(dt)) removedCoins++;
}
while (removedCoins-- > 0)
{
MovingCombo movingCoin = movingTexts.Dequeue();
movingCoin.Finish();
coins.Enqueue(movingCoin.text);
}
}
}
public class Biom
{
public const int BiomCount = 3;
public const uint Hell = 0, Forest = 1, Snow = 2;
}
public class InfiniteSystem
{
public const int MaximumChunks = 6;
private const float chunkOffset = 92.85f * 2.0f;
private Vector3 lastChunkPos;
private uint currentBiom = 0;
private int chunksPassed;
private int biomChangeInterval = 3;
private float biomStartX = -chunkOffset;
private float checkpointPosX;
private readonly Queue<PrayerGroup> prayers = new Queue<PrayerGroup>(3);
private readonly Queue<PrayerGroup> activePrayers = new Queue<PrayerGroup>(3);
private readonly Queue<Transform>[] chunks = new Queue<Transform>[Biom.BiomCount]
{
new Queue<Transform>(MaximumChunks + 1),
new Queue<Transform>(MaximumChunks + 1),
new Queue<Transform>(MaximumChunks + 1)
};
private readonly Queue<Transform> activeChunks = new Queue<Transform>(MaximumChunks + 1);
public void SetCurrentBiom(uint biom) { currentBiom = biom; }
public uint GetCurrentBiom() { return currentBiom; }
public float GetBiomStartX() { return biomStartX; }
public float TotalMetersToNextBiom;
public float MettersPassedSinceLastBiom(float jesusX)
{
return MathF.Abs(jesusX) - MathF.Abs(biomStartX);
}
// returns chunk that closest to player
public Transform GetCurrentChunk(float characterX)
{
Transform closest = null;
float closestX = float.MaxValue;
foreach (var chunk in activeChunks)
{
float dist = Mathf.Abs(characterX - chunk.position.x);
if (dist < closestX)
{
closestX = dist;
closest = chunk;
}
}
return closest;
}
public void SetBiom(uint biom) { currentBiom = biom; }
public void AddChunk(uint biom, Transform chunk)
{
chunks[biom].Enqueue(chunk);
chunk.gameObject.SetActive(false);
}
public void AddPrayer(PrayerGroup prayer)
{
prayers.Enqueue(prayer);
prayer.gameObject.SetActive(false);
}
private void PrepareCheckpoint(float fromBiomX)
{
checkpointPosX = fromBiomX - (50.5f);
PrayerGroup prayer = prayers.Dequeue();
prayer.gameObject.SetActive(true);
prayer.transform.position = new Vector3(checkpointPosX + 3.0f, prayer.transform.position.y, prayer.transform.position.z);
prayers.Enqueue(prayer);
activePrayers.Enqueue(prayer);
}
public void PlaceChunks()
{
lastChunkPos = new Vector3(chunkOffset, -8.2f, 0);
biomStartX = Character.instance.transform.position.x;
TotalMetersToNextBiom = 60.85f * biomChangeInterval;
SpawnChunk();
SpawnChunk();
PrepareCheckpoint(lastChunkPos.x);
currentBiom = (currentBiom + 1) % Biom.BiomCount;
SpawnChunk();
}
private void SpawnChunk()
{
Transform chunk = chunks[currentBiom].Dequeue();
chunk.position = lastChunkPos - new Vector3(chunkOffset, 0, 0);
chunk.gameObject.SetActive(true);
lastChunkPos = chunk.position;
activeChunks.Enqueue(chunk);
chunks[currentBiom].Enqueue(chunk);
}
public void Update(float characterX)
{
foreach (PrayerGroup prayer in activePrayers)
{
if (characterX - 35 <= prayer.transform.position.x)
{
Character.instance.CheckPoint();
PlayerPrefs.SetInt("BiomIndex" + Character.PV, (int)currentBiom);
prayer.PlacePrayers();
activePrayers.Dequeue();
biomStartX = characterX;
TotalMetersToNextBiom = (chunkOffset + 35.5f) * biomChangeInterval;
return;
}
}
foreach (Transform chunk in activeChunks)
{
if (chunk.position.x - 128 > characterX)
{
chunksPassed++;
SpawnChunk();
if (chunksPassed % biomChangeInterval == 0)
{
currentBiom = (currentBiom + 1) % Biom.BiomCount;
PrepareCheckpoint(lastChunkPos.x);
}
activeChunks.Dequeue();
chunk.gameObject.SetActive(false);
break;
}
}
}
}
internal class State
{
public const uint none = 0, playing = 1, moving = 2, dead = 4, paused = 8;
}
public class TirednessStage
{
public event Action OnDeactivate;
public event Action OnActivate;
public event Action<float> OnEvaluete;
public TirednessStage()
{
OnActivate += () => { };
OnDeactivate += () => { };
OnEvaluete += (_) => { };
}
public TirednessStage(Action onActivate, Action onDeactivate, Action<float> onEvaluete)
{
OnActivate += onActivate;
OnDeactivate += onDeactivate;
OnEvaluete += onEvaluete;
}
// proceed tiredness stage
public void Evaluete(float dt) { OnEvaluete(dt); }
public void Activate() { OnActivate(); }
public void Deactivate() { OnDeactivate(); }
}
public class Combo
{
public event Action OnActivate;
public event Action OnDeactivate;
public event Action<float> OnEvaluete;
public Combo()
{
OnActivate += () => {};
OnDeactivate += () => {};
OnEvaluete += (_) => { };
}
public Combo(Action onActivate, Action onDeactivate, Action<float> onEvaluete)
{
OnActivate += onActivate;
OnDeactivate += onDeactivate;
OnEvaluete += onEvaluete;
}
public void Evaluate(float dt) { OnEvaluete(dt); }
public void Activate() { OnActivate(); }
public void Deactivate() { OnDeactivate(); }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment