using UnityEngine; using System.Collections; using AppleHills.Core.Settings; using Core; namespace Minigames.DivingForPictures { /// /// Collision behavior that bumps the player toward the center of the trench. /// Uses trigger-based collision detection with coroutine-based bump timing. /// public class TileBumpCollision : PlayerCollisionBehavior { private Coroutine _bumpCoroutine; protected override void HandleCollisionResponse(Collider2D obstacle) { // Check if the obstacle is on the TrenchTileLayer if (obstacle.gameObject.layer != _devSettings.TrenchTileLayer) { // If not on the trench tile layer, don't process the collision Logging.Debug($"[TileBumpCollision] Ignored collision with object on layer {obstacle.gameObject.layer} (expected {_devSettings.TrenchTileLayer})"); return; } // Use bump mode from developer settings switch (_devSettings.BumpMode) { case BumpMode.Impulse: StartImpulseBump(); break; case BumpMode.SmoothToCenter: StartSmoothMoveToCenter(); break; } Logging.Debug($"[TileBumpCollision] Collision handled with {_devSettings.BumpMode} mode"); } /// /// Starts an impulse bump toward the center with force-based distance /// private void StartImpulseBump() { if (playerCharacter == null) return; float currentX = playerCharacter.transform.position.x; // Calculate bump distance based on force and current position float directionToCenter = currentX > 0 ? -1f : 1f; // Direction toward center // Calculate target position - closer to center based on bump force float bumpDistance = _gameSettings.BumpForce * 0.2f; // Scale factor for distance float targetX = currentX + (directionToCenter * bumpDistance); // Clamp to center if we would overshoot if ((currentX > 0 && targetX < 0) || (currentX < 0 && targetX > 0)) { targetX = 0f; } float bumpDuration = 0.5f; // Fixed duration for impulse StartBump(currentX, targetX, bumpDuration); Logging.Debug($"[TileBumpCollision] Starting impulse bump from X={currentX} to X={targetX} (force={_gameSettings.BumpForce})"); } /// /// Starts smooth movement to the center /// private void StartSmoothMoveToCenter() { if (playerCharacter == null) return; float currentX = playerCharacter.transform.position.x; float distanceToCenter = Mathf.Abs(currentX); float targetX = 0f; // Always move to center float bumpDuration = distanceToCenter / _gameSettings.SmoothMoveSpeed; // Duration based on distance and speed StartBump(currentX, targetX, bumpDuration); Logging.Debug($"[TileBumpCollision] Starting smooth move to center from X={currentX} (speed={_gameSettings.SmoothMoveSpeed}, duration={bumpDuration:F2}s)"); } /// /// Common bump initialization using coroutines /// private void StartBump(float startX, float targetX, float duration) { // Stop any existing bump if (_bumpCoroutine != null) { StopCoroutine(_bumpCoroutine); _bumpCoroutine = null; } // Start bump coroutine _bumpCoroutine = StartCoroutine(BumpCoroutine(startX, targetX, duration)); } /// /// Coroutine that handles the bump movement over time /// private IEnumerator BumpCoroutine(float startX, float targetX, float duration) { float elapsedTime = 0f; while (elapsedTime < duration) { elapsedTime += Time.deltaTime; // Calculate progress and apply curve float progress = elapsedTime / duration; float curveValue = _devSettings.BumpCurve.Evaluate(progress); // Interpolate position float currentX = Mathf.Lerp(startX, targetX, curveValue); // Apply the position to the player character if (playerCharacter != null) { Vector3 currentPos = playerCharacter.transform.position; currentPos.x = Mathf.Clamp(currentX, _gameSettings.ClampXMin, _gameSettings.ClampXMax); playerCharacter.transform.position = currentPos; } yield return null; } // Ensure we end exactly at target if (playerCharacter != null) { Vector3 currentPos = playerCharacter.transform.position; float clampedTargetX = Mathf.Clamp(targetX, _gameSettings.ClampXMin, _gameSettings.ClampXMax); playerCharacter.transform.position = new Vector3(clampedTargetX, currentPos.y, currentPos.z); } // Bump finished _bumpCoroutine = null; Logging.Debug("[TileBumpCollision] Bump movement completed"); } } }