让龙之崛起的消防员走起来

这是2003年雪瑞山留下的龙之崛起的消防员素材,8个完整的方向,每个方向有12帧。

我们在Godot中让它走起来,有了第一个消防员走起来,才有可能让所有的游戏人物都走起来。

龙之崛起消防员

在Godot 4.6.1 中使用的C#脚本,豆包教我一起做的,豆包成了我的资深程序顾问:

cs 复制代码
using Godot;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System;

public partial class EightDirectionWalker : CharacterBody2D
{
    [Export] public AnimatedSprite2D AnimatedSprite;
    [Export] public float MoveSpeed = 20f;


    private List<Texture2D>[] _directionFrames = new List<Texture2D>[8];


    Point input_point = new Point();


    // 8 个标准方向
    private readonly Vector2[] _directions = new Vector2[]
    {
        new(0, -1),  // 0 上
        new(1, -1),  // 1 右上
        new(1, 0),   // 2 右
        new(1, 1),   // 3 右下
        new(0, 1),   // 4 下
        new(-1, 1),  // 5 左下
        new(-1, 0),  // 6 左
        new(-1, -1)  // 7 左上
    };

    public override void _Ready()
    {
        if (AnimatedSprite == null) return;

      

        // 加载 8方向 × 12帧 动画
        for (int dir = 0; dir < 8; dir++)
        {
            _directionFrames[dir] = new List<Texture2D>();
            for (int frame = 0; frame < 12; frame++)
            {
                int spriteNum = 433 + dir + frame * 8;
                string path = $"res://巡逻员/SprMain_{spriteNum:D05}.png";
                var tex = GD.Load<Texture2D>(path);
                if (tex != null) _directionFrames[dir].Add(tex);
            }
        }

        SetupAnimations();
        Position = GetViewport().GetVisibleRect().Size / 2;
    }

    private void SetupAnimations()
    {
        var spriteFrames = new SpriteFrames();
        for (int dir = 0; dir < 8; dir++)
        {
            string animName = GetAnimName(dir);
            spriteFrames.AddAnimation(animName);
            foreach (var tex in _directionFrames[dir])
                spriteFrames.AddFrame(animName, tex);
            spriteFrames.SetAnimationSpeed(animName, 12);
        }
        AnimatedSprite.SpriteFrames = spriteFrames;
    }



    // 加在类里面
    public Vector2 TargetPosition = new Vector2(300, 300);

    int moveSpeed = 50;

    public override void _Process(double delta)
    {
        // 1. 输入
      //  Vector2 input = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");

        Vector2 input = (TargetPosition - Position).Normalized();

        if (Position.DistanceTo(TargetPosition) < 5f)
        {
            Random random = new Random();
            int randomNumber1 = random.Next(100, 801);
            int randomNumber2 = random.Next(100, 801);

            TargetPosition = new Vector2(randomNumber1, randomNumber2);
        }

        // 2. 移动
        Position += RotatePoint(input) * moveSpeed * (float)delta;

        // 3. 播动画
        
       
       int dir = GetClosestDir(input);
       AnimatedSprite.Play(GetAnimName(dir));

     //   if (input.Length() <= 0.1f) AnimatedSprite.Stop();


    }

  
    public static Vector2 RotatePoint(Vector2 origin)
    {
        double newX = origin.X - origin.Y;
        double newY = (origin.X + origin.Y) / 2;
        return (new Vector2((float)newX, (float)newY));
    }


    // 核心:自动找最接近的8方向
    private int GetClosestDir(Vector2 input)
    {
        int best = 4; // 默认下
        float maxDot = -999;

        for (int i = 0; i < 8; i++)
        {
            float dot = input.Dot(_directions[i].Normalized());
            if (dot > maxDot)
            {
                maxDot = dot;
                best = i;
            }
        }
        return best;
    }

    // 动画名称
    private string GetAnimName(int dir)
    {
        return dir switch
        {
            0 => "up",
            1 => "up_right",
            2 => "right",
            3 => "down_right",
            4 => "down",
            5 => "down_left",
            6 => "left",
            7 => "up_left",
            _ => "down"
        };
    }
}


/*
  public override void _Process(double delta)
  {
      // 1. 获取输入
      Vector2 input = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");

      if (input.Length() > 0.1f)
      {
          // 移动
          GlobalPosition += RotatePoint( input )* 50 * (float)delta ;

          // 自动计算 8 方向 + 播放正确动画
          int dir = GetClosestDir(input);
          AnimatedSprite.Play(GetAnimName(dir));
      }
      else
      {
          AnimatedSprite.Stop();
      }
  }
  */