125 lines
3.2 KiB
C#
125 lines
3.2 KiB
C#
using Godot;
|
|
using System;
|
|
|
|
public partial class Projectile : Area2D
|
|
{
|
|
// === 子弹属性 ===
|
|
[Export] public float Speed = 500f; // 子弹速度(像素/秒)
|
|
[Export] public float LifeTime = 2f; // 子弹存在时间(秒)
|
|
[Export] public int Damage = 10; // 子弹伤害值
|
|
[Export] public Texture2D ProjectileTexture; // 子弹视觉纹理
|
|
|
|
// === 内部状态 ===
|
|
public Vector2 Direction = Vector2.Right; // 子弹方向(由武器设置)
|
|
public Node2D From; // 子弹所有者(用于避免自伤)
|
|
|
|
private Timer _lifeTimer; // 生命周期计时器
|
|
private Sprite2D _visualSprite; // 视觉精灵节点
|
|
|
|
public override void _Ready()
|
|
{
|
|
// === 初始化视觉表现 ===
|
|
SetupVisualRepresentation();
|
|
|
|
// === 初始化生命周期计时器 ===
|
|
SetupLifeTimer();
|
|
|
|
// === 连接碰撞信号 ===
|
|
BodyEntered += OnBodyEntered;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置子弹视觉表现
|
|
/// </summary>
|
|
private void SetupVisualRepresentation()
|
|
{
|
|
// 尝试获取现有的精灵节点
|
|
_visualSprite = GetNodeOrNull<Sprite2D>("VisualSprite");
|
|
|
|
// 如果不存在则创建
|
|
if (_visualSprite == null && ProjectileTexture != null)
|
|
{
|
|
_visualSprite = new Sprite2D();
|
|
_visualSprite.Name = "VisualSprite";
|
|
AddChild(_visualSprite);
|
|
}
|
|
|
|
// 应用纹理到视觉精灵
|
|
if (_visualSprite != null && ProjectileTexture != null)
|
|
{
|
|
_visualSprite.Texture = ProjectileTexture;
|
|
}
|
|
|
|
// 根据方向旋转子弹
|
|
if (Direction != Vector2.Zero)
|
|
{
|
|
Rotation = Mathf.Atan2(Direction.Y, Direction.X);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置生命周期计时器
|
|
/// </summary>
|
|
private void SetupLifeTimer()
|
|
{
|
|
_lifeTimer = new Timer();
|
|
AddChild(_lifeTimer);
|
|
_lifeTimer.WaitTime = LifeTime;
|
|
_lifeTimer.OneShot = true; // 单次触发模式
|
|
_lifeTimer.Timeout += OnLifeTimerTimeout;
|
|
_lifeTimer.Start();
|
|
}
|
|
|
|
public override void _PhysicsProcess(double delta)
|
|
{
|
|
float deltaF = (float)delta;
|
|
|
|
// 移动子弹
|
|
GlobalPosition += Direction * Speed * deltaF;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 生命周期计时器回调
|
|
/// </summary>
|
|
private void OnLifeTimerTimeout()
|
|
{
|
|
// 子弹超时自动销毁
|
|
Destroy();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 碰撞检测回调
|
|
/// </summary>
|
|
private void OnBodyEntered(Node2D body)
|
|
{
|
|
// 忽略所有者
|
|
if (body == From) return;
|
|
|
|
// 对可伤害实体造成伤害
|
|
if (body is IDamageable damageable)
|
|
{
|
|
damageable.TakeDamage(Damage);
|
|
}
|
|
|
|
// 销毁子弹
|
|
Destroy();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 销毁子弹
|
|
/// </summary>
|
|
private void Destroy()
|
|
{
|
|
// 实际应用中应该:
|
|
// 1. 播放爆炸/命中效果
|
|
// 2. 播放音效
|
|
// 3. 可选: 留下弹痕/痕迹
|
|
QueueFree();
|
|
}
|
|
}
|
|
|
|
// 可伤害接口
|
|
public interface IDamageable
|
|
{
|
|
void TakeDamage(float amount);
|
|
} |