2026-04-29 10:13:09 +07:00
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
public class BallShooter : MonoBehaviour
|
|
|
|
|
{
|
2026-05-12 01:22:46 +07:00
|
|
|
public GameObject ballPrefab;
|
|
|
|
|
public Transform shootPoint;
|
2026-04-29 10:13:09 +07:00
|
|
|
public float shootForce = 500f;
|
2026-05-12 01:22:46 +07:00
|
|
|
public float upwardForce = 200f;
|
2026-05-11 21:35:39 +07:00
|
|
|
|
2026-05-12 01:22:46 +07:00
|
|
|
[Header("Audio")]
|
|
|
|
|
public System.Collections.Generic.List<AudioClip> shootSounds;
|
|
|
|
|
|
2026-05-11 21:35:39 +07:00
|
|
|
[Header("Shooting Limit")]
|
2026-05-12 01:22:46 +07:00
|
|
|
public float shootCooldown = 1f;
|
2026-05-11 21:35:39 +07:00
|
|
|
private float nextShootTime = 0f;
|
2026-05-12 19:45:57 +07:00
|
|
|
|
2026-05-12 01:22:46 +07:00
|
|
|
|
|
|
|
|
public void FlickShoot(Vector2 swipeDelta, float swipeTime)
|
|
|
|
|
{
|
|
|
|
|
if (swipeDelta.y <= 0) return;
|
|
|
|
|
|
|
|
|
|
float speed = (swipeDelta.y / Screen.height) / Mathf.Max(swipeTime, 0.05f);
|
|
|
|
|
float forceMultiplier = Mathf.Clamp(speed * 1.5f, 0.6f, 2.5f);
|
|
|
|
|
|
|
|
|
|
float horizontalShift = (swipeDelta.x / Screen.width) * 1.5f;
|
|
|
|
|
Vector3 shootDirection = Camera.main.transform.forward + Camera.main.transform.right * horizontalShift;
|
|
|
|
|
shootDirection.Normalize();
|
|
|
|
|
|
|
|
|
|
float finalForce = shootForce * forceMultiplier;
|
|
|
|
|
float finalUpForce = upwardForce * (forceMultiplier * 0.8f);
|
2026-05-11 21:35:39 +07:00
|
|
|
|
2026-05-12 01:22:46 +07:00
|
|
|
PerformShoot(shootDirection, finalForce, finalUpForce);
|
|
|
|
|
|
|
|
|
|
#if UNITY_ANDROID || UNITY_IOS
|
|
|
|
|
Handheld.Vibrate();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void PerformShoot(Vector3 direction, float force, float upForce)
|
|
|
|
|
{
|
|
|
|
|
if (Time.time < nextShootTime) return;
|
2026-05-11 21:35:39 +07:00
|
|
|
nextShootTime = Time.time + shootCooldown;
|
|
|
|
|
|
2026-05-12 01:22:46 +07:00
|
|
|
// Lấy ngẫu nhiên 1 trong các âm thanh ném
|
|
|
|
|
if (AudioPool.Instance != null && shootSounds != null && shootSounds.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
AudioClip randomClip = shootSounds[Random.Range(0, shootSounds.Count)];
|
|
|
|
|
AudioPool.Instance.PlaySound(randomClip, 0.8f, true);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-04 14:52:40 +07:00
|
|
|
Vector3 spawnPosition = Camera.main.transform.position
|
|
|
|
|
+ Camera.main.transform.forward * 0.5f
|
|
|
|
|
- Camera.main.transform.up * 0.2f;
|
|
|
|
|
|
|
|
|
|
GameObject newBall = Instantiate(ballPrefab, spawnPosition, Camera.main.transform.rotation);
|
|
|
|
|
newBall.transform.SetParent(null);
|
|
|
|
|
|
2026-05-11 21:35:39 +07:00
|
|
|
BouncyBall ballScript = newBall.GetComponent<BouncyBall>();
|
|
|
|
|
if (ballScript != null)
|
|
|
|
|
{
|
|
|
|
|
ballScript.shotPosition = Camera.main.transform.position;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-04 14:52:40 +07:00
|
|
|
Rigidbody rb = newBall.GetComponent<Rigidbody>();
|
|
|
|
|
if (rb != null)
|
|
|
|
|
{
|
2026-05-12 01:22:46 +07:00
|
|
|
rb.AddForce(direction * force + Vector3.up * upForce);
|
2026-05-04 14:52:40 +07:00
|
|
|
}
|
2026-04-29 10:13:09 +07:00
|
|
|
|
|
|
|
|
Destroy(newBall, 5f);
|
|
|
|
|
}
|
2026-05-12 01:22:46 +07:00
|
|
|
}
|