using Godot; using System; using System.Collections.Generic; namespace Cosmobox { public partial class Pawn : Sprite2D, IThingPhysics { // 移动参数 [Export] protected float moveSpeed = 200f; // 每秒移动的世界单位数 // 角色属性 [Export] protected int attack = 10; // 攻击力 [Export] protected int health = 100; // 生命值 [Export] protected int defense = 5; // 防御力 // 部件节点 [Export] protected Sprite2D head; // 头部精灵 [Export] protected Sprite2D body; // 身体精灵 [Export] protected Sprite2D clothes; // 衣服精灵 [Export] protected Sprite2D hairBackground; // 头发背景精灵 [Export] protected Sprite2D hair; // 头发精灵 [Export] protected Sprite2D leftEar; // 左耳精灵 [Export] protected Sprite2D rightEar; // 右耳精灵 // 资源路径 [Export] protected string characterResourcesPath = null; // 角色资源文件夹路径 // 纹理数组(每个数组有3个方向:下/上/侧边) [Export] protected Texture2D[] headTextures = new Texture2D[3]; // 头部纹理 [Export] protected Texture2D[] bodyTextures = new Texture2D[3]; // 身体纹理 [Export] protected Texture2D[] clothesTextures = new Texture2D[3]; // 衣服纹理 [Export] protected Texture2D[] hairBackgroundTextures = new Texture2D[3]; // 头发背景纹理 [Export] protected Texture2D[] hairTextures = new Texture2D[3]; // 头发纹理 [Export] protected Texture2D[] leftEarTextures = new Texture2D[3]; // 左耳纹理 [Export] protected Texture2D[] rightEarTextures = new Texture2D[3]; // 右耳纹理 // 物理相关 protected Vector2 currentMovementInput = Vector2.Zero; // 当前原始的输入方向 public bool Moving { get { return currentMovementInput != Vector2.Zero; } } public override void _Ready() { if (!string.IsNullOrEmpty(characterResourcesPath)) { // 加载角色纹理 var loadedTextures = CharacterLoader.LoadCharacterTextures(characterResourcesPath); // 应用加载的纹理 ApplyLoadedTextures(loadedTextures); } SetDownDirection(); // 初始化为向下方向 } void IThingPhysics.PhysicsUpdate(double delta) { float deltaF = (float)delta; // 根据输入方向和移动速度直接应用移动 // 使用Normalized()确保斜向移动不会更快 Position += currentMovementInput.Normalized() * moveSpeed * deltaF; } /// /// 方向纹理设置方法 /// 每个方法设置角色在特定方向的纹理 /// public void SetDownDirection() => SetTextures(0, false); // 设置向下方向的纹理 public void SetUpDirection() => SetTextures(1, false); // 设置向上方向的纹理 public void SetRightDirection() => SetTextures(2, false); // 设置向右方向的纹理 public void SetLeftDirection() => SetTextures(2, true); // 设置向左方向的纹理(使用翻转) /// /// 核心纹理设置方法 /// 为角色各部分设置纹理和水平翻转状态 /// /// 纹理索引:0=下, 1=上, 2=侧边 /// 是否水平翻转(用于左右方向) private void SetTextures(int index, bool flipH) { // 为每个部件设置纹理 if (head != null) head.Texture = headTextures[index]; if (body != null) body.Texture = bodyTextures[index]; if (clothes != null) clothes.Texture = clothesTextures[index]; if (hairBackground != null) hairBackground.Texture = hairBackgroundTextures[index]; if (hair != null) hair.Texture = hairTextures[index]; // 武器纹理设置(需要时取消注释) // if (weapon != null) weapon.Texture = weaponTextures[index]; // 设置每个部件的水平翻转状态 if (head != null) head.FlipH = flipH; if (body != null) body.FlipH = flipH; if (clothes != null) clothes.FlipH = flipH; if (hairBackground != null) hairBackground.FlipH = flipH; if (hair != null) hair.FlipH = flipH; // 耳朵的特殊处理逻辑 if (leftEar != null && rightEar != null) { // 先设置耳朵纹理 leftEar.Texture = leftEarTextures[index]; rightEar.Texture = rightEarTextures[index]; // 当角色面向侧面时(左右方向) if (index == 2) { if (flipH) // 面向左时 { leftEar.Show(); // 显示左耳 rightEar.Hide(); // 隐藏右耳 } else // 面向右时 { leftEar.Hide(); // 隐藏左耳 rightEar.Show(); // 显示右耳 } } else // 上下方向,两个耳朵都显示 { leftEar.Show(); rightEar.Show(); } } } /// /// 简化版移动处理 - 直接存储输入方向 /// 实际移动在物理处理过程中完成 /// /// 输入方向向量 protected void HandleMovement(Vector2 inputDirection) { // 存储当前输入方向,移动计算在物理过程中处理 currentMovementInput = inputDirection; } /// /// 根据移动向量更新角色朝向 /// /// 移动方向向量 public void UpdateDirection(Vector2 direction) { if (direction == Vector2.Zero) return; // 没有移动时不改变方向 // 计算角度(0-360度) float angle = Mathf.RadToDeg(Mathf.Atan2(direction.Y, direction.X)); if (angle < 0) angle += 360; // 根据角度范围决定方向 if (angle >= 45 && angle < 135) { SetDownDirection(); // 下方(例如输入 (0, 1)) } else if (angle >= 135 && angle < 225) { SetLeftDirection(); // 左方(例如输入 (-1, 0)) } else if (angle >= 225 && angle < 315) { SetUpDirection(); // 上方(例如输入 (0, -1)) } else { SetRightDirection(); // 右方(例如输入 (1, 0)) } } /// /// 应用加载的纹理到各个角色部件 /// /// 加载的纹理字典 private void ApplyLoadedTextures(Dictionary loadedTextures) { // 头部纹理 if (loadedTextures.TryGetValue("head", out var headTex) && headTex.Length == 3) { headTextures = headTex; } // 身体纹理 if (loadedTextures.TryGetValue("body", out var bodyTex) && bodyTex.Length == 3) { bodyTextures = bodyTex; } // 衣服纹理 if (loadedTextures.TryGetValue("clothing", out var clothesTex) && clothesTex.Length == 3) { clothesTextures = clothesTex; } // 头发纹理 if (loadedTextures.TryGetValue("hair", out var hairTex) && hairTex.Length == 3) { hairTextures = hairTex; } // 头发背景纹理 if (loadedTextures.TryGetValue("hairBackground", out var hairBGTextures) && hairBGTextures.Length == 3) { hairBackgroundTextures = hairBGTextures; } // 耳朵纹理 - 分别处理左右耳 if (loadedTextures.TryGetValue("leftEar", out var leftEarTex) && leftEarTex.Length == 3) { leftEarTextures = leftEarTex; } if (loadedTextures.TryGetValue("rightEar", out var rightEarTex) && rightEarTex.Length == 3) { rightEarTextures = rightEarTex; } } /// /// 工具方法 /// // 瞬间传送角色到指定位置 public void Teleport(Vector2 position) => Position = position; // 设置移动速度(确保不小于0) public void SetMoveSpeed(float speed) => moveSpeed = Mathf.Max(speed, 0); // 获取当前速度矢量(方向向量 × 速度) public Vector2 GetVelocity() { return currentMovementInput.Normalized() * moveSpeed; } /// /// 添加瞬间冲量(直接改变位置) /// 注意:对于持续的推动效果可能需要单独实现 /// public void AddImpulse(Vector2 impulse) { // 直接修改位置 - 适用于瞬间位移 // 如需持续推动效果,需单独实现冲量系统 Position += impulse; } } }