ProjectSquareBall/Assets/Scripts/ProtoTyping/BallPathTest.cs
2024-10-13 16:13:44 +05:30

154 lines
4.8 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallPathTest : MonoBehaviour
{
public AudioSource audioToSync;
public List<float> allHits = new List<float>();
public LineRenderer line;
public Transform mover;
public float horizontalSpeed = 1f;
public float gravity = -9f;
public float gravityWhenUpwardMult = 1f;
public float maxFallSpeed = 10;
public AnimationCurve bouncingEfficiencyGraph = new AnimationCurve();
// public float bouncingEfficiency =0.4f;
public float changeDirCloseThresh = 0.1f;
public Vector2 velocity;
public bool simulate = false;
public GameObject bouncerPrefab;
public Transform bouncerParent;
void OnValidate()
{
if (simulate)
{
Simulate();
simulate = false;
}
}
float timer = 0;
public List<float> hitsCache = new List<float>();
List<Vector3> pointsHistory = new List<Vector3>();
List<BounceData> hitPointsHistory = new List<BounceData>();
void Start()
{
Reset(Time.time);
}
void Reset(float time){
velocity = new Vector2(horizontalSpeed, 0);
mover.transform.position = Vector2.zero;
hitsCache = new List<float>();
hitsCache.AddRange(allHits);
pointsHistory= new List<Vector3>();
hitPointsHistory= new List<BounceData>();
prevTime=time;
timer =0;
}
// Update is called once per frame
void Update()
{
ManualUpdate(Time.time);
}
float prevTime;
bool ManualUpdate(float time){
float dt = time - prevTime;
prevTime = time;
timer += dt;
audioToSync.time = time;
if(hitsCache.Count <= 1){return true;}
velocity += new Vector2(0, gravity*dt * (velocity.y > 0 ? gravityWhenUpwardMult : 1));
if (timer > hitsCache[0])
{
float timeToNextHit = hitsCache[1]-hitsCache[0];//(hitsCache.Count >1)?1:0
Debug.Log($"hit: {timeToNextHit}, velocity : {velocity}");
BounceData bounceData = new BounceData();
bounceData.point = mover.position;
bounceData.prevVelocity = velocity;
//Bounce
hitsCache.RemoveAt(0);
bool changeDir= timeToNextHit < changeDirCloseThresh;
float bouncingEfficiency = bouncingEfficiencyGraph.Evaluate(Mathf.Abs(velocity.y)/maxFallSpeed);
velocity = new Vector2(velocity.x * (changeDir ? -1 : 1), velocity.y * -bouncingEfficiency * (changeDir ? 0:1));
bounceData.newVelocity = velocity;
hitPointsHistory.Add(bounceData);
}
velocity = new Vector2(velocity.x, velocity.y < -maxFallSpeed ? -maxFallSpeed : velocity.y);
mover.transform.position += (Vector3)velocity * dt;
pointsHistory.Add(mover.transform.position);
return false;
}
void Simulate(){
float fps = 60;
float totalLength = allHits[allHits.Count-1];
float curFrame =0;
Reset(0);
//Purge existing bouncing plats
bouncerParent.PurgeChildrenEdit();
int totalFrames = Mathf.CeilToInt(totalLength * fps);
while(curFrame < totalFrames){
if(ManualUpdate(curFrame/fps)){
break;
}
curFrame++;
}
line.positionCount = pointsHistory.Count;
line.SetPositions(pointsHistory.ToArray());
foreach(BounceData data in hitPointsHistory){
GameObject newPlat = Instantiate(bouncerPrefab, bouncerParent);
newPlat.transform.position = data.point;
newPlat.transform.rotation = Quaternion.AngleAxis(CalculateWallAngle(data.prevVelocity,data.newVelocity), Vector3.forward);
}
}
public static float CalculateWallAngle(Vector2 previousVelocity, Vector2 newVelocity)
{
// Normalize velocities to ignore the speed and just focus on direction
Vector2 previousDir = previousVelocity.normalized;
Vector2 newDir = newVelocity.normalized;
// The reflection vector is the difference between the two normalized velocities
Vector2 reflectionVector = newDir - previousDir;
// Calculate the wall normal using reflection law (midpoint of incoming and outgoing angles)
Vector2 wallNormal = Vector2.Perpendicular(reflectionVector).normalized;
// Calculate the angle of the wall from the wall's normal
float wallAngle = Mathf.Atan2(wallNormal.y, wallNormal.x) * Mathf.Rad2Deg;
// Make sure the angle is between 0 and 360 degrees
if (wallAngle < 0) wallAngle += 360;
return wallAngle;
}
}
[System.Serializable]
public struct BounceData{
public Vector3 point;
public Vector2 prevVelocity;
public Vector2 newVelocity;
}