236 lines
6.8 KiB
C#
236 lines
6.8 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
using Random = UnityEngine.Random;
|
|
|
|
public class CatchMinigameManager : MonoBehaviour
|
|
{
|
|
private int _score;
|
|
public int Score
|
|
{
|
|
get => _score;
|
|
set
|
|
{
|
|
_score = value;
|
|
scoreText.text = "Score: " + _score + " / " + minimalScore;
|
|
}
|
|
}
|
|
|
|
private int _netAttempts;
|
|
|
|
public int NetAttempts
|
|
{
|
|
get => _netAttempts;
|
|
set
|
|
{
|
|
_netAttempts = value;
|
|
netAttemptText.text = "Netten over: " + (maxNetAttempts - value) + " / " + maxNetAttempts;
|
|
}
|
|
}
|
|
|
|
public float minSpawnForce = 100;
|
|
public float maxSpawnForce = 400;
|
|
|
|
public Transform leftSpawnPoint;
|
|
public Transform rightSpawnPoint;
|
|
|
|
public Collider duckCaughtCollider;
|
|
|
|
public TMP_Text scoreText;
|
|
public TMP_Text netAttemptText;
|
|
[FormerlySerializedAs("MInigameInstruction")] public MinigameInstruction minigameInstruction;
|
|
|
|
public float netCooldown = 0.5f;
|
|
public float netVelocity = 10f;
|
|
public Vector3 netDisplacement = Vector3.up * 4;
|
|
|
|
public int maxNetAttempts = 5;
|
|
public int minimalScore = 20;
|
|
|
|
public GameObject net;
|
|
|
|
public ParticleSystem duckCollectEffect;
|
|
|
|
// When ducks leave the river bounds, they're disabled
|
|
public Bounds riverBounds;
|
|
|
|
public float avgSpawnsPerSecond = 5;
|
|
|
|
public Transform duckParent;
|
|
public Transform duckCollectEffectParent;
|
|
public FloatingDuckController floatingDuckPrefab;
|
|
|
|
public event EventHandler<MiniGameResult> MinigameFinished;
|
|
|
|
private List<FloatingDuckController> activeDucks = new List<FloatingDuckController>();
|
|
private Queue<FloatingDuckController> floatingDuckPool = new Queue<FloatingDuckController>();
|
|
|
|
private Queue<ParticleSystem> duckCollectEffectPool = new Queue<ParticleSystem>();
|
|
|
|
private bool _netMoving = false;
|
|
|
|
private static CatchMinigameManager _instance;
|
|
public static CatchMinigameManager Instance
|
|
{
|
|
get { return _instance; }
|
|
private set { _instance = value; }
|
|
}
|
|
|
|
public CatchMinigameManager()
|
|
{
|
|
Instance = this;
|
|
}
|
|
|
|
public void ResetMinigame()
|
|
{
|
|
Score = 0;
|
|
NetAttempts = 0;
|
|
|
|
for (var i = 0; i < activeDucks.Count; i++)
|
|
{
|
|
floatingDuckPool.Enqueue(activeDucks[i]);
|
|
activeDucks[i].gameObject.SetActive(false);
|
|
}
|
|
activeDucks.Clear();
|
|
|
|
minigameInstruction.Show();
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
var spawnChance = Time.deltaTime * avgSpawnsPerSecond;
|
|
if (Random.value <= spawnChance)
|
|
{
|
|
var left = leftSpawnPoint.position;
|
|
var right = rightSpawnPoint.position;
|
|
var diff = left - right;
|
|
var pos = right + (diff * Random.value);
|
|
|
|
FloatingDuckController duck;
|
|
if (floatingDuckPool.Count > 0)
|
|
{
|
|
duck = floatingDuckPool.Dequeue();
|
|
var duckTransform = duck.transform;
|
|
duckTransform.position = pos;
|
|
duckTransform.rotation = Quaternion.identity;
|
|
duck.initialForce = Vector3.left * ((maxSpawnForce - minSpawnForce) * Random.value);
|
|
|
|
duck.gameObject.SetActive(true);
|
|
}
|
|
else
|
|
{
|
|
duck = Instantiate(floatingDuckPrefab, pos, Quaternion.identity, duckParent);
|
|
duck.initialForce = Vector3.left * ((maxSpawnForce - minSpawnForce) * Random.value);
|
|
duck.duckCaughtCollider = duckCaughtCollider;
|
|
|
|
duck.DuckCaught += (obj, args) =>
|
|
{
|
|
Score++;
|
|
DisableDuck(duck);
|
|
if (duckCollectEffect != null)
|
|
{
|
|
ParticleSystem effect;
|
|
if (duckCollectEffectPool.Count > 0)
|
|
{
|
|
effect = duckCollectEffectPool.Dequeue();
|
|
effect.gameObject.SetActive(true);
|
|
effect.transform.position = duck.transform.position;
|
|
}
|
|
else
|
|
{
|
|
effect = Instantiate(duckCollectEffect, duck.transform.position, duckCollectEffect.transform.rotation, duckCollectEffectParent);
|
|
}
|
|
effect.Play();
|
|
StartCoroutine(PoolEffectWhenFinished(effect));
|
|
}
|
|
};
|
|
}
|
|
|
|
activeDucks.Add(duck);
|
|
}
|
|
|
|
for (var i = 0; i < activeDucks.Count; i++)
|
|
{
|
|
var duck = activeDucks[i];
|
|
if (!riverBounds.Contains(duck.transform.position))
|
|
{
|
|
DisableDuck(i);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
if (Input.GetMouseButtonDown(0) && !_netMoving)
|
|
{
|
|
// Activate the net
|
|
NetAttempts++;
|
|
StartCoroutine(MoveNet());
|
|
}
|
|
|
|
if (!_netMoving && NetAttempts >= maxNetAttempts)
|
|
{
|
|
// Minigame finished
|
|
if (MinigameFinished != null)
|
|
{
|
|
MinigameFinished.Invoke(this, Score >= minimalScore ? MiniGameResult.Success : MiniGameResult.Failed);
|
|
}
|
|
}
|
|
}
|
|
|
|
private IEnumerator PoolEffectWhenFinished(ParticleSystem effect)
|
|
{
|
|
while (effect.isPlaying)
|
|
{
|
|
yield return null;
|
|
}
|
|
effect.gameObject.SetActive(false);
|
|
duckCollectEffectPool.Enqueue(effect);
|
|
}
|
|
|
|
private void DisableDuck(FloatingDuckController duck)
|
|
{
|
|
DisableDuck(activeDucks.IndexOf(duck));
|
|
}
|
|
|
|
private void DisableDuck(int i)
|
|
{
|
|
var duck = activeDucks[i];
|
|
activeDucks.RemoveAt(i);
|
|
duck.gameObject.SetActive(false);
|
|
floatingDuckPool.Enqueue(duck);
|
|
}
|
|
|
|
private IEnumerator MoveNet()
|
|
{
|
|
_netMoving = true;
|
|
var totalTime = netDisplacement.magnitude / netVelocity;
|
|
var time = 0f;
|
|
var originalNetPosition = net.transform.position;
|
|
while (time < totalTime)
|
|
{
|
|
time += Time.deltaTime;
|
|
net.transform.position = originalNetPosition + (netDisplacement * (time / totalTime));
|
|
yield return null;
|
|
}
|
|
|
|
time = 0f;
|
|
while (time < netCooldown)
|
|
{
|
|
time += Time.deltaTime;
|
|
net.transform.position = originalNetPosition + netDisplacement - (netDisplacement * (time / netCooldown));
|
|
yield return null;
|
|
}
|
|
|
|
net.transform.position = originalNetPosition;
|
|
|
|
_netMoving = false;
|
|
}
|
|
}
|
|
|
|
public enum MiniGameResult
|
|
{
|
|
Success, Failed
|
|
}
|