这是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();
}
}
*/