using System.Collections.Generic;
using UnityEngine;
namespace Magisterka.BulletHell
{
///
/// Handles individual bullet lifetime, movement, and collision dispatching.
///
[RequireComponent(typeof(SpriteRenderer))]
public class Bullet : MonoBehaviour
{
private static readonly Dictionary SpriteCache = new Dictionary();
[SerializeField] private float radius = 0.22f;
[SerializeField] private float despawnBounds = 14f;
private SpriteRenderer _spriteRenderer;
private CircleCollider2D _collider;
private Rigidbody2D _body;
private BulletPool _ownerPool;
private Vector2 _direction;
private float _speed;
private float _damage;
private Faction _ownerFaction;
public bool BelongsToEnemy => _ownerFaction == Faction.Enemy;
public BulletPool OwnerPool => _ownerPool;
public static Bullet Create(BulletPool pool, Color tint, Faction faction)
{
var go = new GameObject("Bullet" + faction, typeof(SpriteRenderer));
var bullet = go.AddComponent();
bullet.Initialize(pool, tint, faction);
return bullet;
}
private void Initialize(BulletPool pool, Color tint, Faction faction)
{
_ownerPool = pool;
_ownerFaction = faction;
_spriteRenderer = GetComponent();
_spriteRenderer.sprite = GetOrCreateSprite(tint);
_spriteRenderer.color = tint;
_body = gameObject.AddComponent();
_body.gravityScale = 0f;
_body.isKinematic = true;
_body.interpolation = RigidbodyInterpolation2D.Interpolate;
_collider = gameObject.AddComponent();
_collider.isTrigger = true;
_collider.radius = radius;
gameObject.layer = LayerMask.NameToLayer("Default");
gameObject.SetActive(false);
}
public void Configure(Vector2 direction, float speed, float damage, Faction faction)
{
_direction = direction.normalized;
_speed = speed;
_damage = damage;
_ownerFaction = faction;
}
private void Update()
{
transform.position += (Vector3)(_direction * (_speed * Time.deltaTime));
if (Mathf.Abs(transform.position.x) > despawnBounds || Mathf.Abs(transform.position.y) > despawnBounds)
{
Despawn();
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (!other.TryGetComponent(out Health health))
{
return;
}
if (health.Faction == _ownerFaction)
{
return;
}
if (health.Faction == Faction.Player && PlayerController.Instance != null && PlayerController.Instance.IsInvulnerable())
{
return;
}
health.ApplyDamage(_damage, transform.position);
Despawn();
}
public void Despawn()
{
_ownerPool?.Return(this);
}
private static Sprite GetOrCreateSprite(Color tint)
{
if (SpriteCache.TryGetValue(tint, out var sprite))
{
return sprite;
}
const int size = 16;
var texture = new Texture2D(size, size, TextureFormat.RGBA32, false) { filterMode = FilterMode.Point };
var pixels = new Color[size * size];
for (int i = 0; i < pixels.Length; i++)
{
pixels[i] = tint;
}
texture.SetPixels(pixels);
texture.Apply();
sprite = Sprite.Create(texture, new Rect(0, 0, size, size), new Vector2(0.5f, 0.5f), 100f);
SpriteCache[tint] = sprite;
return sprite;
}
}
}