You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ReactRacetrack/Assets/Scripts/PlayerPathRunner.cs

239 lines
7.1 KiB
C#

1 month ago
using System;
1 month ago
using System.Collections.Generic;
1 month ago
using UnityEngine;
using DG.Tweening;
using DG.Tweening.Plugins.Core.PathCore;
1 month ago
using UnityEngine.SceneManagement;
1 month ago
public class PlayerPathRunner : MonoBehaviour
{
1 month ago
[Header("Speed Settings")]
1 month ago
public float baseSpeed = 2f;
public float maxSpeed = 10f;
1 month ago
public float acceleration = 5f;
public float constantSpeed = 5f; // Speed to use when not in tap mode
[Header("Tap Speed Mode")]
public bool useTapToMove = true;
1 month ago
public float tapWindowSeconds = 0.5f;
1 month ago
[Header("Jump Settings")]
public float jumpPower = 2f;
public float jumpDuration = 0.5f;
public float jumpDistance = 3f; // Distance in world units
1 month ago
[Header("Path Setup")]
public DOTweenPath pathSource;
1 month ago
public bool faceMovementDirection = true;
public float rotationSpeed = 10f;
1 month ago
[Header("Hurdle Setup")]
public List<Transform> hurdles; // Assign all hurdles here
private List<float> tapTimestamps = new();
1 month ago
private float currentSpeed = 0f;
private float pathPosition = 0f;
private Vector3[] drawPoints;
private Path bakedPath;
1 month ago
private bool isJumping = false;
private System.Action onJumpComplete;
1 month ago
private void Awake()
{
Application.targetFrameRate = 120;
}
void Start()
{
if (pathSource == null)
{
Debug.LogError("Path Source not assigned!");
return;
}
1 month ago
// Bake DOTween path (we pause immediately)
1 month ago
transform.DOPath(pathSource.wps.ToArray(), 1f, pathSource.pathType, pathSource.pathMode)
.SetOptions(pathSource.isClosedPath)
.SetEase(Ease.Linear)
.SetLookAt(0)
.Pause();
drawPoints = pathSource.GetDrawPoints();
if (drawPoints == null || drawPoints.Length < 2)
{
Debug.LogError("Draw points not generated properly.");
}
1 month ago
// Initialize speed based on mode
if (!useTapToMove)
{
currentSpeed = constantSpeed;
}
}
1 month ago
void Update()
{
1 month ago
// Don't process normal movement if jumping
if (isJumping) return;
1 month ago
if (useTapToMove)
{
HandleInput();
UpdateSpeed();
}
else
{
// In constant mode, set speed directly without acceleration
currentSpeed = constantSpeed;
}
MoveOnPath();
1 month ago
}
void HandleInput()
{
if (Input.GetMouseButtonDown(0) || Input.touchCount > 0)
{
tapTimestamps.Add(Time.time);
}
}
void UpdateSpeed()
{
float cutoff = Time.time - tapWindowSeconds;
tapTimestamps.RemoveAll(t => t < cutoff);
float tps = tapTimestamps.Count / tapWindowSeconds;
1 month ago
float targetSpeed = Mathf.Clamp(baseSpeed + tps, baseSpeed, maxSpeed);
1 month ago
currentSpeed = Mathf.MoveTowards(currentSpeed, targetSpeed, acceleration * Time.deltaTime);
}
void MoveOnPath()
{
if (drawPoints == null || drawPoints.Length < 2) return;
1 month ago
float speed = currentSpeed / 50f;
1 month ago
pathPosition += speed * Time.deltaTime;
pathPosition %= 1f;
1 month ago
UpdatePositionOnPath(pathPosition);
}
void UpdatePositionOnPath(float normalizedPosition)
{
float floatIndex = normalizedPosition * (drawPoints.Length - 1);
1 month ago
int iA = Mathf.FloorToInt(floatIndex);
int iB = Mathf.Min(iA + 1, drawPoints.Length - 1);
float t = floatIndex - iA;
Vector3 pos = Vector3.Lerp(drawPoints[iA], drawPoints[iB], t);
transform.position = pos;
1 month ago
// Handle rotation to face movement direction
if (faceMovementDirection && iB < drawPoints.Length)
{
Vector3 direction = drawPoints[iB] - drawPoints[iA];
direction.y = 0; // Keep rotation only on Y axis (no tilting)
if (direction != Vector3.zero)
{
Quaternion targetRotation = Quaternion.LookRotation(direction);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
}
}
1 month ago
}
1 month ago
public void TriggerJump(System.Action onComplete = null)
{
if (isJumping) return;
Debug.Log("🦘 Jump triggered in PlayerPathRunner!");
isJumping = true;
onJumpComplete = onComplete;
// Calculate how much to advance on the path based on world distance
float pathLength = CalculateTotalPathLength();
float jumpPercentage = jumpDistance / pathLength;
// Calculate end position on path
float targetPathPosition = pathPosition + jumpPercentage;
targetPathPosition %= 1f; // Wrap around if needed
// Get world positions for start and end
Vector3 startPos = transform.position;
Vector3 endPos = GetWorldPositionAtPathPosition(targetPathPosition);
// Do the jump
transform.DOJump(endPos, jumpPower, 1, jumpDuration)
.SetEase(Ease.OutQuad)
1 month ago
.OnUpdate(() => {
// Update rotation during jump to face the landing direction
if (faceMovementDirection)
{
Vector3 jumpDirection = GetDirectionAtPathPosition(targetPathPosition);
if (jumpDirection != Vector3.zero)
{
Quaternion targetRot = Quaternion.LookRotation(jumpDirection);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, rotationSpeed * Time.deltaTime);
}
}
})
1 month ago
.OnComplete(() => {
// Update our path position to match where we jumped to
pathPosition = targetPathPosition;
isJumping = false;
Debug.Log("Jump completed!");
onJumpComplete?.Invoke();
onJumpComplete = null;
});
}
float CalculateTotalPathLength()
{
float totalLength = 0f;
for (int i = 0; i < drawPoints.Length - 1; i++)
{
totalLength += Vector3.Distance(drawPoints[i], drawPoints[i + 1]);
}
return totalLength;
}
Vector3 GetWorldPositionAtPathPosition(float normalizedPos)
{
float floatIndex = normalizedPos * (drawPoints.Length - 1);
int iA = Mathf.FloorToInt(floatIndex);
int iB = Mathf.Min(iA + 1, drawPoints.Length - 1);
float t = floatIndex - iA;
return Vector3.Lerp(drawPoints[iA], drawPoints[iB], t);
}
1 month ago
Vector3 GetDirectionAtPathPosition(float normalizedPos)
{
float floatIndex = normalizedPos * (drawPoints.Length - 1);
int iA = Mathf.FloorToInt(floatIndex);
int iB = Mathf.Min(iA + 1, drawPoints.Length - 1);
Vector3 direction = drawPoints[iB] - drawPoints[iA];
direction.y = 0; // Keep only horizontal direction
return direction.normalized;
}
1 month ago
public float GetCurrentSpeed()
1 month ago
{
1 month ago
return currentSpeed;
1 month ago
}
1 month ago
public bool IsJumping()
{
return isJumping;
}
1 month ago
public void GoToMainMenu()
{
SceneManager.LoadScene(0);
}
1 month ago
}