439 lines
16 KiB
C#
439 lines
16 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
public class GamePlayer : MonoBehaviour
|
|
{
|
|
public static GamePlayer Instance;
|
|
private readonly float spawnRate = 1f;
|
|
private float nextSpawnTime;
|
|
internal int score;
|
|
private int attempts;
|
|
private float boostLeft;
|
|
private float slownessLeft;
|
|
private float speedyLeft;
|
|
private float antiLeft;
|
|
private float goldenLeft;
|
|
[SerializeField] private Text scoreText;
|
|
[SerializeField] private Text boostText;
|
|
[SerializeField] internal AudioSource backgroundMusic;
|
|
[SerializeField] private GameObject berryParent;
|
|
|
|
[SerializeField] private Image bird;
|
|
[SerializeField] private GameObject berryTemplate;
|
|
[SerializeField] private Rigidbody2D rb;
|
|
[SerializeField] private RectTransform canvasRect;
|
|
[SerializeField] private BoxCollider2D groundCollider;
|
|
|
|
public readonly List<GameObject> berries = new List<GameObject>();
|
|
private readonly List<int> noGravityBerries = new List<int>();
|
|
private bool hasJumped = false;
|
|
|
|
internal bool IsGrounded()
|
|
{
|
|
CircleCollider2D birdCol = bird.GetComponent<CircleCollider2D>();
|
|
Vector2 feetPos = (Vector2)bird.transform.position + Vector2.down * (birdCol.radius + 0.05f);
|
|
|
|
return groundCollider.OverlapPoint(feetPos);
|
|
}
|
|
|
|
public void Awake()
|
|
{
|
|
Instance = this;
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
UpdateStats(0, 1);
|
|
}
|
|
|
|
void MoveBird()
|
|
{
|
|
float speedModifier = 1f;
|
|
bool doMoveRight = false;
|
|
bool doMoveLeft = false;
|
|
bool doJump = false;
|
|
bool doRestart = false;
|
|
if (boostLeft > 0f || speedyLeft > 0f) speedModifier = 1.39f;
|
|
else if (slownessLeft > 0f) speedModifier = 0.56f;
|
|
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.J))
|
|
{
|
|
doMoveLeft = true;
|
|
}
|
|
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.L))
|
|
{
|
|
doMoveRight = true;
|
|
}
|
|
if (Input.GetKey(KeyCode.Space) || Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.W) ||
|
|
Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.K) ||
|
|
Input.GetKey(KeyCode.I) || Input.GetMouseButton(0))
|
|
{
|
|
doJump = true;
|
|
}
|
|
if (Input.GetKey(KeyCode.R))
|
|
{
|
|
doRestart = true;
|
|
}
|
|
if (doMoveLeft && !doMoveRight)
|
|
{
|
|
bird.transform.position += new Vector3(-(576f * (speedModifier * canvasRect.lossyScale.x) * Time.deltaTime), 0f, 0f);
|
|
ClampPosition(bird);
|
|
bird.transform.localScale = new Vector3(1f, 1f, 1f);
|
|
}
|
|
if (doMoveRight && !doMoveLeft)
|
|
{
|
|
bird.transform.position += new Vector3(576f * (speedModifier * canvasRect.lossyScale.x) * Time.deltaTime, 0f, 0f);
|
|
ClampPosition(bird);
|
|
bird.transform.localScale = new Vector3(-1f, 1f, 1f);
|
|
}
|
|
if (doMoveLeft || doMoveRight) groundCollider.transform.position = new Vector2(bird.transform.position.x, groundCollider.transform.position.y);
|
|
if (doJump && IsGrounded() && !hasJumped)
|
|
{
|
|
hasJumped = true;
|
|
AudioSource.PlayClipAtPoint(Resources.Load<AudioClip>("Sounds/Jump"), Camera.main.transform.position, 0.75f);
|
|
if (boostLeft > 0f || speedyLeft > 0f) rb.velocity = new Vector2(rb.velocity.x, 480f * canvasRect.lossyScale.y);
|
|
else if (slownessLeft > 0f) rb.velocity = new Vector2(rb.velocity.x, 300f * canvasRect.lossyScale.y);
|
|
else rb.velocity = new Vector2(rb.velocity.x, 380f * canvasRect.lossyScale.y);
|
|
}
|
|
if (!IsGrounded()) hasJumped = false;
|
|
if (doRestart)
|
|
{
|
|
if (score != 0) Respawn();
|
|
}
|
|
if (antiLeft > 0f || goldenLeft > 0f)
|
|
{
|
|
List<string> berryTags = new List<string>() { "NormalBerry", "SlowBerry", "UltraBerry", "SpeedyBerry", "RandomBerry", "AntiBerry", "GoldenBerry" };
|
|
if (antiLeft > 0f) berryTags.Add("PoisonBerry");
|
|
|
|
float scale = (canvasRect.lossyScale.x + canvasRect.lossyScale.y) / 2f;
|
|
float radius = antiLeft > 0f ? 250f * scale : 325f * scale;
|
|
float speed = antiLeft > 0f ? (300f * scale * Time.deltaTime) : -(420f * scale * Time.deltaTime);
|
|
|
|
foreach (string tag in berryTags)
|
|
{
|
|
foreach (var berry in GameObject.FindGameObjectsWithTag(tag))
|
|
{
|
|
RectTransform berryRect = berry.GetComponent<RectTransform>();
|
|
Vector3 dir = berryRect.position - bird.GetComponent<RectTransform>().position;
|
|
|
|
if (dir.magnitude < radius)
|
|
{
|
|
berryRect.position += speed * dir.normalized;
|
|
ClampPosition(berry.GetComponent<Image>());
|
|
noGravityBerries.Add(berry.GetInstanceID());
|
|
}
|
|
else noGravityBerries.Remove(berry.GetInstanceID());
|
|
}
|
|
}
|
|
}
|
|
else if (noGravityBerries.Count() != 0) noGravityBerries.Clear();
|
|
}
|
|
|
|
void ClampPosition(Image image)
|
|
{
|
|
RectTransform birdRect = image.GetComponent<RectTransform>();
|
|
float halfW = canvasRect.rect.width / 2f;
|
|
float halfBirdW = birdRect.rect.width / 2f;
|
|
|
|
Vector2 pos = birdRect.anchoredPosition;
|
|
pos.x = Mathf.Clamp(pos.x, -halfW + halfBirdW, halfW - halfBirdW);
|
|
birdRect.anchoredPosition = pos;
|
|
}
|
|
|
|
void SpawnBerries()
|
|
{
|
|
if (Time.time < nextSpawnTime)
|
|
{
|
|
return;
|
|
}
|
|
if (speedyLeft > 0)
|
|
{
|
|
nextSpawnTime = Time.time + 1f / (spawnRate * 1.875f);
|
|
}
|
|
else
|
|
{
|
|
nextSpawnTime = Time.time + 1f / spawnRate;
|
|
}
|
|
float spawnProbability = UnityEngine.Random.value;
|
|
Image newBerry = Instantiate(berryTemplate).GetComponent<Image>();
|
|
newBerry.transform.SetParent(berryParent.transform, false);
|
|
|
|
if (spawnProbability <= 0.425f)
|
|
{
|
|
newBerry.sprite = Resources.Load<Sprite>("Berries/Berry");
|
|
newBerry.tag = "NormalBerry";
|
|
}
|
|
else if (spawnProbability <= 0.60f)
|
|
{
|
|
newBerry.sprite = Resources.Load<Sprite>("Berries/PoisonBerry");
|
|
newBerry.tag = "PoisonBerry";
|
|
}
|
|
else if (spawnProbability <= 0.65f)
|
|
{
|
|
newBerry.sprite = Resources.Load<Sprite>("Berries/SlowBerry");
|
|
newBerry.tag = "SlowBerry";
|
|
}
|
|
else if (spawnProbability <= 0.75f)
|
|
{
|
|
newBerry.sprite = Resources.Load<Sprite>("Berries/UltraBerry");
|
|
newBerry.tag = "UltraBerry";
|
|
}
|
|
else if (spawnProbability <= 0.85f)
|
|
{
|
|
newBerry.sprite = Resources.Load<Sprite>("Berries/SpeedyBerry");
|
|
newBerry.tag = "SpeedyBerry";
|
|
}
|
|
else if (spawnProbability <= 0.90f)
|
|
{
|
|
newBerry.sprite = Resources.Load<Sprite>("Berries/BerryNoColor");
|
|
newBerry.tag = "RandomBerry";
|
|
RainbowImage randomBerryRainbowImage = newBerry.gameObject.AddComponent<RainbowImage>();
|
|
randomBerryRainbowImage.frequency = 5f;
|
|
}
|
|
else if (spawnProbability <= 0.95f)
|
|
{
|
|
newBerry.sprite = Resources.Load<Sprite>("Berries/AntiBerry");
|
|
newBerry.tag = "AntiBerry";
|
|
}
|
|
else
|
|
{
|
|
newBerry.sprite = Resources.Load<Sprite>("Berries/GoldenBerry");
|
|
newBerry.tag = "GoldenBerry";
|
|
}
|
|
|
|
float spawnPositionX = UnityEngine.Random.Range(-(canvasRect.rect.width / 2 - newBerry.rectTransform.rect.width), canvasRect.rect.width / 2 - newBerry.rectTransform.rect.width);
|
|
newBerry.transform.localPosition = new Vector3(spawnPositionX, (canvasRect.rect.height / 2) + newBerry.rectTransform.rect.height, 0f);
|
|
newBerry.gameObject.SetActive(true);
|
|
|
|
berries.Add(newBerry.gameObject);
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (rb.gravityScale != 100f * canvasRect.lossyScale.y) rb.gravityScale = 100f * canvasRect.lossyScale.y;
|
|
|
|
SpawnBerries();
|
|
MoveBird();
|
|
if (boostLeft > 0f)
|
|
{
|
|
boostLeft -= Time.deltaTime;
|
|
boostText.text = "Boost expires in " + string.Format("{0:0.0}", boostLeft) + "s";
|
|
}
|
|
else if (slownessLeft > 0f)
|
|
{
|
|
slownessLeft -= Time.deltaTime;
|
|
boostText.text = "Slowness expires in " + string.Format("{0:0.0}", slownessLeft) + "s";
|
|
}
|
|
else if (speedyLeft > 0f)
|
|
{
|
|
speedyLeft -= Time.deltaTime;
|
|
boostText.text = "Speed expires in " + string.Format("{0:0.0}", speedyLeft) + "s";
|
|
}
|
|
else if (antiLeft > 0f)
|
|
{
|
|
antiLeft -= Time.deltaTime;
|
|
boostText.text = "Berry repellent expires in " + string.Format("{0:0.0}", antiLeft) + "s";
|
|
}
|
|
else if (goldenLeft > 0f)
|
|
{
|
|
goldenLeft -= Time.deltaTime;
|
|
boostText.text = "Berry magnet expires in " + string.Format("{0:0.0}", goldenLeft) + "s";
|
|
}
|
|
else
|
|
{
|
|
boostText.text = "";
|
|
}
|
|
foreach (GameObject berry in berries.ToList())
|
|
{
|
|
if (berry == null)
|
|
{
|
|
berries.Remove(berry);
|
|
continue;
|
|
}
|
|
if (berry.GetComponent<RectTransform>().anchoredPosition.y < -(canvasRect.rect.height / 2) - berry.GetComponent<RectTransform>().rect.height)
|
|
{
|
|
noGravityBerries.Remove(berry.GetInstanceID());
|
|
Destroy(berry);
|
|
}
|
|
else
|
|
{
|
|
CircleCollider2D birdCol = bird.GetComponent<CircleCollider2D>();
|
|
CircleCollider2D berryCol = berry.GetComponent<CircleCollider2D>();
|
|
|
|
Vector2 birdPos = bird.transform.position;
|
|
Vector2 berryPos = berry.transform.position;
|
|
|
|
float distance = Vector2.Distance(birdPos, berryPos);
|
|
float radiusSum = (birdCol.radius / 2) + (berryCol.radius / 2);
|
|
|
|
if (distance <= radiusSum)
|
|
{
|
|
switch (berry.tag)
|
|
{
|
|
case "NormalBerry":
|
|
DoNormalBerry(berry);
|
|
break;
|
|
case "PoisonBerry":
|
|
DoPoisonBerry();
|
|
break;
|
|
case "SlowBerry":
|
|
DoSlowBerry(berry);
|
|
break;
|
|
case "UltraBerry":
|
|
DoUltraBerry(berry);
|
|
break;
|
|
case "SpeedyBerry":
|
|
DoSpeedyBerry(berry);
|
|
break;
|
|
case "RandomBerry":
|
|
DoRandomBerry(berry);
|
|
break;
|
|
case "AntiBerry":
|
|
DoAntiBerry(berry);
|
|
break;
|
|
case "GoldenBerry":
|
|
DoGoldenBerry(berry);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (berry != null) berry.GetComponent<Rigidbody2D>().velocity = noGravityBerries.Contains(berry.GetInstanceID()) ? Vector2.zero : new Vector2(0f, speedyLeft == 0.0f ? (-300f * canvasRect.lossyScale.y) : (-550f * canvasRect.lossyScale.y));
|
|
}
|
|
}
|
|
|
|
void Respawn()
|
|
{
|
|
bird.GetComponent<RectTransform>().anchoredPosition = new Vector3(0f, 64f, 0f);
|
|
groundCollider.GetComponent<RectTransform>().anchoredPosition = new Vector2(0f, -2.5f);
|
|
bird.transform.localScale = new Vector3(1f, 1f, 1f);
|
|
rb.velocity = new Vector3();
|
|
score = 0;
|
|
boostLeft = 0f;
|
|
slownessLeft = 0f;
|
|
speedyLeft = 0f;
|
|
antiLeft = 0f;
|
|
UpdateStats(0, 1);
|
|
|
|
foreach (GameObject berry in berries) Destroy(berry);
|
|
berries.Clear();
|
|
noGravityBerries.Clear();
|
|
}
|
|
|
|
void UpdateStats(int scoreAddAmount, int attemptAddAmount)
|
|
{
|
|
score += scoreAddAmount;
|
|
attempts += attemptAddAmount;
|
|
scoreText.text = string.Format("Score: {0} \u2022 Attempts: {1}", score, attempts);
|
|
}
|
|
|
|
void DoNormalBerry(GameObject berry)
|
|
{
|
|
AudioSource.PlayClipAtPoint(Resources.Load<AudioClip>("Sounds/Eat"), Camera.main.transform.position, 1.2f);
|
|
berries.Remove(berry);
|
|
noGravityBerries.Remove(berry.GetInstanceID());
|
|
Destroy(berry);
|
|
UpdateStats(1, 0);
|
|
}
|
|
|
|
void DoPoisonBerry()
|
|
{
|
|
AudioSource.PlayClipAtPoint(Resources.Load<AudioClip>("Sounds/Death"), Camera.main.transform.position, 1.2f);
|
|
Respawn();
|
|
UpdateStats(0, 0);
|
|
}
|
|
|
|
void DoSlowBerry(GameObject berry)
|
|
{
|
|
AudioSource.PlayClipAtPoint(Resources.Load<AudioClip>("Sounds/Downgrade"), Camera.main.transform.position, 0.35f);
|
|
berries.Remove(berry);
|
|
noGravityBerries.Remove(berry.GetInstanceID());
|
|
Destroy(berry);
|
|
boostLeft = 0f;
|
|
slownessLeft = 10f;
|
|
speedyLeft = 0f;
|
|
antiLeft = 0f;
|
|
goldenLeft = 0f;
|
|
if (score > 0)
|
|
{
|
|
UpdateStats(-1, 0);
|
|
}
|
|
}
|
|
|
|
void DoUltraBerry(GameObject berry)
|
|
{
|
|
AudioSource.PlayClipAtPoint(Resources.Load<AudioClip>("Sounds/Powerup"), Camera.main.transform.position, 0.35f);
|
|
berries.Remove(berry);
|
|
noGravityBerries.Remove(berry.GetInstanceID());
|
|
Destroy(berry);
|
|
speedyLeft = 0f;
|
|
antiLeft = 0f;
|
|
goldenLeft = 0f;
|
|
if (slownessLeft > 0f)
|
|
{
|
|
slownessLeft = 0f;
|
|
UpdateStats(1, 0);
|
|
}
|
|
else
|
|
{
|
|
boostLeft += 10f;
|
|
UpdateStats(5, 0);
|
|
}
|
|
}
|
|
|
|
void DoSpeedyBerry(GameObject berry)
|
|
{
|
|
AudioSource.PlayClipAtPoint(Resources.Load<AudioClip>("Sounds/SpeedyPowerup"), Camera.main.transform.position, 0.35f);
|
|
berries.Remove(berry);
|
|
noGravityBerries.Remove(berry.GetInstanceID());
|
|
Destroy(berry);
|
|
boostLeft = 0f;
|
|
slownessLeft = 0f;
|
|
speedyLeft = 10f;
|
|
antiLeft = 0f;
|
|
goldenLeft = 0f;
|
|
UpdateStats(10, 0);
|
|
}
|
|
|
|
void DoRandomBerry(GameObject berry)
|
|
{
|
|
Action[] funcs = {
|
|
() => DoNormalBerry(berry),
|
|
() => DoSlowBerry(berry),
|
|
() => DoUltraBerry(berry),
|
|
() => DoSpeedyBerry(berry),
|
|
() => DoAntiBerry(berry),
|
|
() => DoGoldenBerry(berry)
|
|
};
|
|
funcs[UnityEngine.Random.Range(0, funcs.Length)]();
|
|
}
|
|
|
|
void DoAntiBerry(GameObject berry)
|
|
{
|
|
AudioSource.PlayClipAtPoint(Resources.Load<AudioClip>("Sounds/Downgrade"), Camera.main.transform.position, 0.35f);
|
|
berries.Remove(berry);
|
|
noGravityBerries.Remove(berry.GetInstanceID());
|
|
Destroy(berry);
|
|
boostLeft = 0f;
|
|
slownessLeft = 0f;
|
|
speedyLeft = 0f;
|
|
antiLeft = 10f;
|
|
goldenLeft = 0f;
|
|
UpdateStats(0, 0);
|
|
}
|
|
|
|
void DoGoldenBerry(GameObject berry)
|
|
{
|
|
AudioSource.PlayClipAtPoint(Resources.Load<AudioClip>("Sounds/Powerup"), Camera.main.transform.position, 0.35f);
|
|
berries.Remove(berry);
|
|
noGravityBerries.Remove(berry.GetInstanceID());
|
|
Destroy(berry);
|
|
boostLeft = 0f;
|
|
slownessLeft = 0f;
|
|
speedyLeft = 0f;
|
|
antiLeft = 0f;
|
|
goldenLeft = 10f;
|
|
UpdateStats(4, 0);
|
|
}
|
|
} |