- Added Black Horse And The Cherry Tree by KT Tunstall to the horse playlist. - Added Buckin' My Horse by Sir Mix-A-Lot to the horse playlist.
172 lines
4.8 KiB
C#
172 lines
4.8 KiB
C#
|
|
using UdonSharp;
|
|
using UnityEngine;
|
|
using VRC.SDKBase;
|
|
using VRC.Udon;
|
|
|
|
namespace myro.arcade
|
|
{
|
|
public class Fruit : UdonSharpBehaviour
|
|
{
|
|
public Rigidbody RigidbodyInstance;
|
|
public MeshRenderer MeshRendererInstance;
|
|
public CapsuleCollider FruitCollider;
|
|
|
|
private short _rank = 0;
|
|
|
|
private MelonGameLoop _melonGameLoopInstance;
|
|
|
|
private const float TARGET_COLLIDER_RADIUS = 0.5f;
|
|
private float _currentColliderRadius;
|
|
private float _gravityMultiplicator;
|
|
private bool _hadCollision;
|
|
|
|
#region Game Over Detection
|
|
private float _yAxisLimit; //If one fruit stays above that limit for more than a second, the game is lost
|
|
private float _startTimeAboveLimit;
|
|
|
|
private void CheckGameOver()
|
|
{
|
|
if (!_hadCollision)
|
|
{
|
|
return;
|
|
}
|
|
if (transform.localPosition.y - transform.localScale.x / 2.0f < _yAxisLimit
|
|
|| RigidbodyInstance.velocity.magnitude > 0.5f * transform.lossyScale.x)
|
|
{
|
|
//everything is alright
|
|
_startTimeAboveLimit = 0;
|
|
}
|
|
else if (_startTimeAboveLimit == 0
|
|
&& transform.localPosition.y - transform.localScale.x / 2.0f >= _yAxisLimit
|
|
&& RigidbodyInstance.velocity.magnitude <= 0.5f * transform.lossyScale.x)
|
|
{
|
|
//Dangerously close to a game over
|
|
_startTimeAboveLimit = Time.time;
|
|
}
|
|
else if (Time.time - _startTimeAboveLimit > 1.0f && _melonGameLoopInstance.GetGameState() != GameState.FINISH)
|
|
{
|
|
_melonGameLoopInstance.GameOver();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
public void Construct(Transform parent, MelonGameLoop melonGameLoopInstance, short rank, float gameScale, float yAxisLimit, bool isFused)
|
|
{
|
|
transform.parent = parent;
|
|
FruitCollider.enabled = false;
|
|
RigidbodyInstance.isKinematic = true;
|
|
|
|
_hadCollision = isFused;
|
|
_yAxisLimit = yAxisLimit;
|
|
|
|
_currentColliderRadius = TARGET_COLLIDER_RADIUS;
|
|
|
|
_gravityMultiplicator = gameScale;
|
|
_melonGameLoopInstance = melonGameLoopInstance;
|
|
|
|
RigidbodyInstance.drag = 0;
|
|
RigidbodyInstance.angularDrag = 1f;
|
|
|
|
SetRank(rank);
|
|
SetScaleAndRotation();
|
|
}
|
|
|
|
public short GetRank()
|
|
{
|
|
return _rank;
|
|
}
|
|
|
|
public void SetRank(short rank)
|
|
{
|
|
_rank = rank;
|
|
float fruitScale = 0.22f + rank * 0.147272f;
|
|
transform.localScale = Vector3.one * fruitScale;
|
|
RigidbodyInstance.mass = 1;
|
|
_melonGameLoopInstance.SetTextureOffset(MeshRendererInstance.material, rank);
|
|
}
|
|
|
|
private void SetScaleAndRotation()
|
|
{
|
|
FruitCollider.radius = _currentColliderRadius;
|
|
transform.localEulerAngles = new Vector3(0, 0, transform.localEulerAngles.z);
|
|
}
|
|
|
|
public void DropFruit()
|
|
{
|
|
FruitCollider.enabled = true;
|
|
RigidbodyInstance.isKinematic = false;
|
|
RigidbodyInstance.collisionDetectionMode = CollisionDetectionMode.Continuous;
|
|
|
|
_currentColliderRadius = TARGET_COLLIDER_RADIUS * 0.5f;
|
|
FruitCollider.contactOffset = 0.0001f; //Using the script "ColliderParameterSetter" didn't worked, so I am setting it here.
|
|
SetScaleAndRotation();
|
|
}
|
|
|
|
#region Unity Events
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
if (!enabled)
|
|
return;
|
|
|
|
//Local velocity contraint
|
|
Vector3 localVelocity = transform.parent.InverseTransformDirection(RigidbodyInstance.velocity);
|
|
localVelocity.z = 0;
|
|
RigidbodyInstance.velocity = transform.parent.TransformDirection(localVelocity);
|
|
|
|
//Gravity on the local space
|
|
RigidbodyInstance.AddForce(transform.parent.up * -5f * _gravityMultiplicator * RigidbodyInstance.mass);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
CheckGameOver();
|
|
_currentColliderRadius += (TARGET_COLLIDER_RADIUS - _currentColliderRadius) * Time.deltaTime * 3f;
|
|
|
|
//Local rotation contraint
|
|
SetScaleAndRotation();
|
|
|
|
//Local position contraint
|
|
transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y, 0);
|
|
}
|
|
|
|
private void OnCollisionEnter(Collision collision)
|
|
{
|
|
if (gameObject.activeSelf && enabled)
|
|
{
|
|
if (_rank != 10)
|
|
{
|
|
Fruit anotherFruit = collision.gameObject.GetComponent<Fruit>();
|
|
if (anotherFruit && _rank == anotherFruit.GetRank() && collision.gameObject.activeSelf)
|
|
{
|
|
_melonGameLoopInstance.DestroyFruit(this);
|
|
_melonGameLoopInstance.DestroyFruit(anotherFruit);
|
|
_melonGameLoopInstance.IncrementComboAndPlayAudio();
|
|
gameObject.SetActive(false);
|
|
anotherFruit.gameObject.SetActive(false);
|
|
|
|
Fruit newFruit = _melonGameLoopInstance.InstantiateNewFruitAt((short)(_rank + 1), true);
|
|
newFruit.transform.localPosition = (anotherFruit.transform.localPosition + transform.localPosition) / 2.0f;
|
|
newFruit.DropFruit();
|
|
}
|
|
else if (!_hadCollision)
|
|
{
|
|
_melonGameLoopInstance.SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, nameof(_melonGameLoopInstance.PlayCollisionAudio));
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
if (!_hadCollision)
|
|
{
|
|
_melonGameLoopInstance.ReadyForNextFruit();
|
|
_hadCollision = true;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|