Newer
Older
DungeonShooting / DungeonShooting_Godot / src / effect / ThrowNode.cs
using System;
using Godot;

/// <summary>
/// 模拟抛出的物体, 使用时将对象挂载到该节点上即可
/// </summary>
public class ThrowNode : KinematicBody2D
{
    /// <summary>
    /// 是否已经结束
    /// </summary>
    /// <value></value>
    public bool IsOver { get; protected set; } = true;
    /// <summary>
    /// 物体大小
    /// </summary>
    public Vector2 Size { get; protected set; }
    /// <summary>
    /// 起始坐标
    /// </summary>
    public Vector2 StartPosition { get; protected set; }
    /// <summary>
    /// 移动方向, 0 - 360
    /// </summary>
    /// <value></value>
    public float Direction { get; protected set; }
    /// <summary>
    /// x速度, 也就是水平速度
    /// </summary>
    public float XSpeed { get; protected set; }
    /// <summary>
    /// y轴速度, 也就是竖直速度
    /// </summary>
    /// <value></value>
    public float YSpeed { get; protected set; }
    /// <summary>
    /// 初始x轴组队
    /// </summary>
    /// <value></value>
    public float StartXSpeed { get; protected set; }
    /// <summary>
    /// 初始y轴速度
    /// </summary>
    public float StartYSpeed { get; protected set; }
    /// <summary>
    /// 旋转速度
    /// </summary>
    public float RotateSpeed { get; protected set; }
    /// <summary>
    /// 挂载的对象
    /// </summary>
    public Node2D Mount { get; protected set; }
    /// <summary>
    /// 碰撞组件
    /// </summary>
    /// <value></value>
    public CollisionShape2D CollisionShape { get; protected set; }
    /// <summary>
    /// 绘制阴影的精灵
    /// </summary>
    public Sprite ShadowSprite { get; protected set; }

    protected Sprite ShadowTarget { get; set; }

    private bool inversionX = false;

    public override void _Ready()
    {
        //只与墙壁碰撞
        CollisionMask = 1;
        CollisionLayer = 0;
        //创建碰撞器
        CollisionShape = new CollisionShape2D();
        var shape = new RectangleShape2D();
        shape.Extents = Size * 0.5f;
        CollisionShape.Shape = shape;
        AddChild(CollisionShape);
    }

    /// <summary>
    /// 初始化该抛物线对象的基础数据
    /// </summary>
    /// <param name="size">抛射的物体所占大小, 用于碰撞检测</param>
    /// <param name="start">起始点</param>
    /// <param name="startHeight">起始高度</param>
    /// <param name="direction">角度, 0 - 360</param>
    /// <param name="xSpeed">横轴速度</param>
    /// <param name="ySpeed">纵轴速度</param>
    /// <param name="rotate">旋转速度</param>
    /// <param name="mount">需要挂载的节点</param>
    /// <param name="texutre">抛射的节点显示的纹理, 用于渲染阴影用</param>
    public void InitThrow(Vector2 size, Vector2 start, float startHeight, float direction, float xSpeed, float ySpeed, float rotate, Node2D mount)
    {
        if (CollisionShape != null)
        {
            CollisionShape.Disabled = false;
        }

        IsOver = false;
        Size = size;
        GlobalPosition = StartPosition = start;
        Direction = direction;
        XSpeed = xSpeed;
        YSpeed = ySpeed;
        StartXSpeed = xSpeed;
        StartYSpeed = ySpeed;
        RotateSpeed = rotate;

        if (mount != null)
        {
            Mount = mount;
            AddChild(mount);
            mount.Position = new Vector2(0, -startHeight);
        }
    }

    /// <summary>
    /// 初始化该抛物线对象的基础数据, 并且渲染阴影
    /// </summary>
    /// <param name="size">抛射的物体所占大小, 用于碰撞检测</param>
    /// <param name="start">起始点</param>
    /// <param name="startHeight">起始高度</param>
    /// <param name="direction">角度, 0 - 360</param>
    /// <param name="xSpeed">横轴速度</param>
    /// <param name="ySpeed">纵轴速度</param>
    /// <param name="rotate">旋转速度</param>
    /// <param name="mount">需要挂载的节点</param>
    /// <param name="shadowTarget">抛射的节点显示的纹理, 用于渲染阴影用</param>
    public void InitThrow(Vector2 size, Vector2 start, float startHeight, float direction, float xSpeed, float ySpeed, float rotate, Node2D mount, Sprite shadowTarget)
    {
        InitThrow(size, start, startHeight, direction, xSpeed, ySpeed, rotate, mount);
        ShadowTarget = shadowTarget;
        if (shadowTarget != null)
        {
            if (ShadowSprite == null)
            {
                //阴影
                ShadowSprite = new Sprite();
                ShadowSprite.ZIndex = -5;
                ShadowSprite.Material = ResourceManager.ShadowMaterial;
                AddChild(ShadowSprite);
            }
            inversionX = mount.Scale.y < 0 ? true : false;
            if (inversionX)
            {
                ShadowSprite.Scale = shadowTarget.Scale * new Vector2(1, -1);
            }
            else
            {
                ShadowSprite.Scale = shadowTarget.Scale;
            }
            ShadowSprite.Texture = shadowTarget.Texture;
        }
        else if (ShadowSprite != null)
        {
            ShadowSprite.Texture = null;
        }
    }

    /// <summary>
    /// 达到最高点时调用
    /// </summary>
    protected virtual void OnMaxHeight(float height)
    {

    }

    /// <summary>
    /// 结束的调用
    /// </summary>
    protected virtual void OnOver()
    {

    }

    public override void _Process(float delta)
    {
        if (!IsOver)
        {
            MoveAndSlide(new Vector2(XSpeed, 0).Rotated(Direction * Mathf.Pi / 180));
            Mount.Position = new Vector2(0, Mount.Position.y - YSpeed * delta);
            var rotate = Mount.GlobalRotationDegrees + RotateSpeed * delta;
            Mount.GlobalRotationDegrees = rotate;
            if (ShadowSprite != null)
            {
                ShadowSprite.GlobalRotationDegrees = rotate;
                // ShadowSprite.GlobalRotationDegrees = rotate + (inversionX ? 180 : 0);
                ShadowSprite.GlobalPosition = ShadowTarget.GlobalPosition + new Vector2(0, 1 - Mount.Position.y);
            }
            var ysp = YSpeed;
            YSpeed -= GameConfig.G * delta;
            //达到最高点
            if (ysp * YSpeed < 0)
            {
                OnMaxHeight(-Mount.Position.y);
            }
            //落地判断
            if (Mount.Position.y >= 0)
            {
                Mount.Position = new Vector2(0, 0);
                IsOver = true;
                CollisionShape.Disabled = true;
                OnOver();
            }
        }
    }

}