122 lines
3.9 KiB
C#
122 lines
3.9 KiB
C#
using Core;
|
|
using Core.Lifecycle;
|
|
using Core.Settings;
|
|
using UnityEngine;
|
|
|
|
namespace Minigames.BirdPooper
|
|
{
|
|
/// <summary>
|
|
/// Poop projectile that falls straight down with manual gravity.
|
|
/// Destroys when off-screen or hitting targets (Phase 5).
|
|
/// </summary>
|
|
[RequireComponent(typeof(Rigidbody2D))]
|
|
[RequireComponent(typeof(Collider2D))]
|
|
public class PoopProjectile : ManagedBehaviour
|
|
{
|
|
private IBirdPooperSettings settings;
|
|
private float verticalVelocity; // Current downward velocity
|
|
private const float GravityAcceleration = 20f; // Gravity acceleration (units/s²)
|
|
|
|
internal override void OnManagedAwake()
|
|
{
|
|
base.OnManagedAwake();
|
|
|
|
// Tag as Projectile for target detection
|
|
if (!gameObject.CompareTag("Projectile"))
|
|
{
|
|
gameObject.tag = "Projectile";
|
|
}
|
|
|
|
// Load settings
|
|
settings = GameManager.GetSettingsObject<IBirdPooperSettings>();
|
|
if (settings == null)
|
|
{
|
|
Debug.LogError("[PoopProjectile] BirdPooperSettings not found!");
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
|
|
// Initialize velocity with settings speed as starting velocity
|
|
verticalVelocity = settings.PoopFallSpeed;
|
|
|
|
// Verify Rigidbody2D configuration
|
|
Rigidbody2D rb = GetComponent<Rigidbody2D>();
|
|
if (rb != null)
|
|
{
|
|
rb.bodyType = RigidbodyType2D.Kinematic; // Kinematic = manual control, no physics
|
|
rb.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
|
|
}
|
|
|
|
// Find and set all colliders to trigger (we use OnTriggerEnter2D)
|
|
Collider2D[] colliders = GetComponentsInChildren<Collider2D>(true);
|
|
foreach (Collider2D col in colliders)
|
|
{
|
|
if (!col.isTrigger)
|
|
{
|
|
col.isTrigger = true;
|
|
Debug.Log($"[PoopProjectile] Set collider '{col.name}' to trigger");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (settings != null)
|
|
{
|
|
ApplyGravity();
|
|
FallDown();
|
|
CheckBounds();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apply gravity acceleration to velocity.
|
|
/// </summary>
|
|
private void ApplyGravity()
|
|
{
|
|
// Increase downward velocity over time (gravity acceleration)
|
|
verticalVelocity += GravityAcceleration * Time.deltaTime;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Manual downward movement using current velocity.
|
|
/// </summary>
|
|
private void FallDown()
|
|
{
|
|
// Move straight down at current velocity
|
|
transform.position += Vector3.down * verticalVelocity * Time.deltaTime;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if projectile is off-screen and should be destroyed.
|
|
/// </summary>
|
|
private void CheckBounds()
|
|
{
|
|
if (transform.position.y < settings.PoopDestroyYPosition)
|
|
{
|
|
Destroy(gameObject);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Trigger collision detection for targets (Phase 5).
|
|
/// Uses OnTriggerEnter2D with trigger collider.
|
|
/// </summary>
|
|
private void OnTriggerEnter2D(Collider2D other)
|
|
{
|
|
if (other.CompareTag("Target"))
|
|
{
|
|
// Notify target it was hit
|
|
Target target = other.GetComponent<Target>();
|
|
if (target != null)
|
|
{
|
|
target.OnHitByProjectile();
|
|
}
|
|
|
|
Destroy(gameObject);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|