初次提交
4
.editorconfig
Normal file
@ -0,0 +1,4 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Normalize EOL for all files that Git considers text files.
|
||||
* text=auto eol=lf
|
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Godot 4+ specific ignores
|
||||
.godot/
|
||||
/android/
|
BIN
Font/Uranus_Pixel_11Px.ttf
Normal file
35
Font/Uranus_Pixel_11Px.ttf.import
Normal file
@ -0,0 +1,35 @@
|
||||
[remap]
|
||||
|
||||
importer="font_data_dynamic"
|
||||
type="FontFile"
|
||||
uid="uid://cjfdun63bo72f"
|
||||
path="res://.godot/imported/Uranus_Pixel_11Px.ttf-9deb139e327f1dcf0754100708d26028.fontdata"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Font/Uranus_Pixel_11Px.ttf"
|
||||
dest_files=["res://.godot/imported/Uranus_Pixel_11Px.ttf-9deb139e327f1dcf0754100708d26028.fontdata"]
|
||||
|
||||
[params]
|
||||
|
||||
Rendering=null
|
||||
antialiasing=1
|
||||
generate_mipmaps=false
|
||||
disable_embedded_bitmaps=true
|
||||
multichannel_signed_distance_field=false
|
||||
msdf_pixel_range=8
|
||||
msdf_size=48
|
||||
allow_system_fallback=true
|
||||
force_autohinter=false
|
||||
hinting=1
|
||||
subpixel_positioning=4
|
||||
keep_rounding_remainders=true
|
||||
oversampling=0.0
|
||||
Fallbacks=null
|
||||
fallbacks=[]
|
||||
Compress=null
|
||||
compress=true
|
||||
preload=[]
|
||||
language_support={}
|
||||
script_support={}
|
||||
opentype_features={}
|
12
Resource/Item/gress.tres
Normal file
@ -0,0 +1,12 @@
|
||||
[gd_resource type="Resource" script_class="ItemResource" load_steps=3 format=3 uid="uid://byyba456mf86l"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://c6sgy6n73g1c7" path="res://图片/Item/gress.png" id="1_7esax"]
|
||||
[ext_resource type="Script" uid="uid://d02in2v01dbtb" path="res://Script/Item/ItemResource.cs" id="1_gj5v6"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_gj5v6")
|
||||
ItemName = "草"
|
||||
Description = "这是草,一种草本植物"
|
||||
Icon = ExtResource("1_7esax")
|
||||
Stackable = true
|
||||
metadata/_custom_type_script = "uid://d02in2v01dbtb"
|
10
Script/Base/IThing.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
namespace Cosmobox
|
||||
{
|
||||
public interface IThing
|
||||
{
|
||||
public void Update(double delta);
|
||||
}
|
||||
}
|
1
Script/Base/IThing.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://m301eht3eac3
|
9
Script/Base/IThingPhysics.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Godot;
|
||||
using System;
|
||||
namespace Cosmobox
|
||||
{
|
||||
public interface IThingPhysics
|
||||
{
|
||||
public void PhysicsUpdate(double delta);
|
||||
}
|
||||
}
|
1
Script/Base/IThingPhysics.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://c6hg67pd2oxuc
|
9
Script/Base/IThingUI.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Godot;
|
||||
using System;
|
||||
namespace Cosmobox
|
||||
{
|
||||
public interface IThingUI
|
||||
{
|
||||
public void UpdateUI();
|
||||
}
|
||||
}
|
1
Script/Base/IThingUI.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://bqkle0sd1vwbk
|
89
Script/Base/InputControl.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
namespace Cosmobox
|
||||
{
|
||||
public partial class InputControl : Node
|
||||
{
|
||||
[Export] public TickControl tickControl; // 控制游戏暂停的节点
|
||||
[Export] public Player player; // 玩家节点
|
||||
[Export] public BagUI bagUI; // 背包 UI
|
||||
[Export] public Control devUI; // 开发者 UI
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
// 初始化状态
|
||||
UpdatePauseState();
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
// 监听 "bag" 按键
|
||||
if (Input.IsActionJustPressed("bag"))
|
||||
{
|
||||
ToggleBagUI();
|
||||
}
|
||||
|
||||
// 监听开发者 UI 的切换(假设通过某个按键触发)
|
||||
if (Input.IsActionJustPressed("dev_ui"))
|
||||
{
|
||||
ToggleDevUI();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换背包 UI 的打开/关闭状态
|
||||
/// </summary>
|
||||
private void ToggleBagUI()
|
||||
{
|
||||
if (bagUI.IsOpen)
|
||||
{
|
||||
bagUI.CloseBag(); // 关闭背包
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果开发者 UI 已打开,则先关闭开发者 UI
|
||||
if (devUI.Visible)
|
||||
{
|
||||
devUI.Visible = false;
|
||||
}
|
||||
bagUI.OpenBag(); // 打开背包
|
||||
}
|
||||
|
||||
// 更新暂停状态
|
||||
UpdatePauseState();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换开发者 UI 的可见性
|
||||
/// </summary>
|
||||
private void ToggleDevUI()
|
||||
{
|
||||
if (devUI.Visible)
|
||||
{
|
||||
devUI.Visible = false; // 关闭开发者 UI
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果背包已打开,则先关闭背包
|
||||
if (bagUI.IsOpen)
|
||||
{
|
||||
bagUI.CloseBag();
|
||||
}
|
||||
devUI.Visible = true; // 打开开发者 UI
|
||||
}
|
||||
|
||||
// 更新暂停状态
|
||||
UpdatePauseState();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新游戏的暂停状态
|
||||
/// </summary>
|
||||
private void UpdatePauseState()
|
||||
{
|
||||
// 如果背包或开发者 UI 任一打开,则暂停游戏
|
||||
tickControl.pause = bagUI.IsOpen || devUI.Visible;
|
||||
}
|
||||
}
|
||||
}
|
1
Script/Base/InputControl.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://cgesjwgws6bmr
|
67
Script/Base/ItemResourceManager.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
namespace Cosmobox
|
||||
{
|
||||
public static class ItemResourceManager
|
||||
{
|
||||
private static Dictionary<string, ItemResource> _items;
|
||||
private static bool _initialized = false;
|
||||
|
||||
// 初始化物品数据
|
||||
private static void Initialize()
|
||||
{
|
||||
if (_initialized) return;
|
||||
|
||||
_items = new Dictionary<string, ItemResource>();
|
||||
|
||||
// 加载 res://Resource/Item/ 目录下的所有 ItemResource
|
||||
var dir = DirAccess.Open("res://Resource/Item/");
|
||||
if (dir != null)
|
||||
{
|
||||
dir.ListDirBegin();
|
||||
string fileName = dir.GetNext();
|
||||
while (fileName != "")
|
||||
{
|
||||
if (!dir.CurrentIsDir() && fileName.EndsWith(".tres"))
|
||||
{
|
||||
var resourcePath = $"res://Resource/Item/{fileName}";
|
||||
var item = GD.Load<ItemResource>(resourcePath);
|
||||
if (item != null)
|
||||
{
|
||||
_items[item.ItemName] = item;
|
||||
}
|
||||
}
|
||||
fileName = dir.GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
// 获取所有物品
|
||||
public static Dictionary<string, ItemResource> GetAllItems()
|
||||
{
|
||||
Initialize();
|
||||
return _items;
|
||||
}
|
||||
|
||||
// 通过名称获取物品
|
||||
public static ItemResource GetItem(string itemName)
|
||||
{
|
||||
Initialize();
|
||||
if (_items.TryGetValue(itemName, out var item))
|
||||
{
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取物品数量
|
||||
public static int GetItemCount()
|
||||
{
|
||||
Initialize();
|
||||
return _items.Count;
|
||||
}
|
||||
}
|
||||
}
|
1
Script/Base/ItemResourceManager.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://cla8a7157wf4v
|
135
Script/Base/PerlinNoise.cs
Normal file
@ -0,0 +1,135 @@
|
||||
using System;
|
||||
namespace Cosmobox
|
||||
{
|
||||
public class PerlinNoise
|
||||
{
|
||||
private int[] p; // 混淆表
|
||||
|
||||
// 构造函数:初始化混淆表
|
||||
public PerlinNoise(int seed)
|
||||
{
|
||||
// 初始化为0-255的随机排列
|
||||
p = new int[512]; // 混淆表加倍以方便使用
|
||||
int[] permutation = new int[256];
|
||||
Random random = new Random(seed);
|
||||
|
||||
// 填充数组为0-255
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
permutation[i] = i;
|
||||
}
|
||||
|
||||
// 使用Fisher-Yates算法打乱数组
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
int swapIndex = random.Next(256);
|
||||
int temp = permutation[i];
|
||||
permutation[i] = permutation[swapIndex];
|
||||
permutation[swapIndex] = temp;
|
||||
}
|
||||
|
||||
// 将打乱后的数组复制两次,生成512个元素的混淆表
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
p[i] = permutation[i];
|
||||
p[i + 256] = permutation[i];
|
||||
}
|
||||
}
|
||||
|
||||
// 平滑函数 (6t^5 - 15t^4 + 10t^3)
|
||||
private double Fade(double t)
|
||||
{
|
||||
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||
}
|
||||
|
||||
// 线性插值
|
||||
private double Lerp(double t, double a, double b)
|
||||
{
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
// 计算梯度向量和距离向量的点积
|
||||
private double Grad(int hash, double x, double y, double z)
|
||||
{
|
||||
// 根据hash值确定使用哪个梯度向量
|
||||
// 12个梯度向量由以下组合构成:(+/-1, +/-1, 0), (+/-1, 0, +/-1), (0, +/-1, +/-1)
|
||||
switch (hash & 0xF) // 取hash值的最后4位
|
||||
{
|
||||
case 0x0: return x + y;
|
||||
case 0x1: return -x + y;
|
||||
case 0x2: return x - y;
|
||||
case 0x3: return -x - y;
|
||||
case 0x4: return x + z;
|
||||
case 0x5: return -x + z;
|
||||
case 0x6: return x - z;
|
||||
case 0x7: return -x - z;
|
||||
case 0x8: return y + z;
|
||||
case 0x9: return -y + z;
|
||||
case 0xA: return y - z;
|
||||
case 0xB: return -y - z;
|
||||
case 0xC: return y + x; // 这四个是重复的,但Ken Perlin的原始实现中包含它们。
|
||||
case 0xD: return -y + x; // 它们对噪声质量影响不大,但保持了表格的一致性。
|
||||
case 0xE: return y - x;
|
||||
case 0xF: return -y - x;
|
||||
default: return 0; // 不应该发生
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 为给定的(x, y, z)坐标生成3D Perlin噪声。
|
||||
/// 输出值通常在-1到1之间。
|
||||
/// </summary>
|
||||
public double Noise(double x, double y, double z)
|
||||
{
|
||||
// 找到包含该点的单位立方体
|
||||
int X = (int)Math.Floor(x) & 255;
|
||||
int Y = (int)Math.Floor(y) & 255;
|
||||
int Z = (int)Math.Floor(z) & 255;
|
||||
|
||||
// 找到该点在立方体内的相对x, y, z坐标
|
||||
x -= Math.Floor(x);
|
||||
y -= Math.Floor(y);
|
||||
z -= Math.Floor(z);
|
||||
|
||||
// 计算x, y, z的平滑曲线
|
||||
double u = Fade(x);
|
||||
double v = Fade(y);
|
||||
double w = Fade(z);
|
||||
|
||||
// 对立方体的8个角进行哈希计算
|
||||
int A = p[X] + Y;
|
||||
int AA = p[A] + Z;
|
||||
int AB = p[A + 1] + Z;
|
||||
int B = p[X + 1] + Y;
|
||||
int BA = p[B] + Z;
|
||||
int BB = p[B + 1] + Z;
|
||||
|
||||
// 获取所有8个角的哈希值
|
||||
int H000 = p[AA];
|
||||
int H100 = p[BA];
|
||||
int H010 = p[AB];
|
||||
int H110 = p[BB];
|
||||
int H001 = p[AA + 1];
|
||||
int H101 = p[BA + 1];
|
||||
int H011 = p[AB + 1];
|
||||
int H111 = p[BB + 1];
|
||||
|
||||
// 计算所有8个角的点积并插值
|
||||
double x0, x1, y0, y1;
|
||||
|
||||
x0 = Lerp(u, Grad(H000, x, y, z), // (0,0,0)
|
||||
Grad(H100, x - 1, y, z)); // (1,0,0)
|
||||
x1 = Lerp(u, Grad(H010, x, y - 1, z), // (0,1,0)
|
||||
Grad(H110, x - 1, y - 1, z)); // (1,1,0)
|
||||
y0 = Lerp(v, x0, x1);
|
||||
|
||||
x0 = Lerp(u, Grad(H001, x, y, z - 1), // (0,0,1)
|
||||
Grad(H101, x - 1, y, z - 1)); // (1,0,1)
|
||||
x1 = Lerp(u, Grad(H011, x, y - 1, z - 1), // (0,1,1)
|
||||
Grad(H111, x - 1, y - 1, z - 1)); // (1,1,1)
|
||||
y1 = Lerp(v, x0, x1);
|
||||
|
||||
return Lerp(w, y0, y1);
|
||||
}
|
||||
}
|
||||
}
|
1
Script/Base/PerlinNoise.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://cnom22n5jbp2
|
74
Script/Base/TickControl.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
namespace Cosmobox
|
||||
{
|
||||
public partial class TickControl : Node
|
||||
{
|
||||
[Export] public bool pause = false;
|
||||
|
||||
private List<IThing> things = new List<IThing>();
|
||||
private List<IThingPhysics> thingsPhysics = new List<IThingPhysics>();
|
||||
private List<IThingUI> thingsUI = new List<IThingUI>();
|
||||
public override void _Ready()
|
||||
{
|
||||
// 从场景树的根节点开始查找实现了 IThing 接口的节点
|
||||
FindThingsInScene(GetTree().GetRoot());
|
||||
}
|
||||
|
||||
private void FindThingsInScene(Node node)
|
||||
{
|
||||
// 检查当前节点是否实现了 IThing 接口
|
||||
if (node is IThing thing)
|
||||
{
|
||||
things.Add(thing);
|
||||
}
|
||||
|
||||
// 检查当前节点是否实现了 IThingPhysics 接口
|
||||
if (node is IThingPhysics physicsThing)
|
||||
{
|
||||
thingsPhysics.Add(physicsThing);
|
||||
}
|
||||
|
||||
// 检查当前节点是否实现了 IThingUI 接口
|
||||
if (node is IThingUI uiThing)
|
||||
{
|
||||
thingsUI.Add(uiThing);
|
||||
}
|
||||
|
||||
// 递归查找子节点
|
||||
foreach (Node child in node.GetChildren())
|
||||
{
|
||||
FindThingsInScene(child);
|
||||
}
|
||||
}
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (!pause)
|
||||
{
|
||||
foreach (var thing in things)
|
||||
{
|
||||
thing.Update(delta);
|
||||
}
|
||||
}
|
||||
foreach (var thing in thingsUI)
|
||||
{
|
||||
thing.UpdateUI();
|
||||
}
|
||||
}
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
if (!pause)
|
||||
{
|
||||
foreach (var thing in thingsPhysics)
|
||||
{
|
||||
thing.PhysicsUpdate(delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
1
Script/Base/TickControl.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://ctbyhk40owvej
|
73
Script/Generate/PlayerGenerate.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using Cosmobox.Def;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Linq;
|
||||
namespace Cosmobox
|
||||
{
|
||||
public partial class PlayerGenerate : Node2D
|
||||
{
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
InitResource.instance.defines.TryGetValue("DrawingOrder", out var defines);
|
||||
if (defines != null)
|
||||
{
|
||||
GenerateNode(defines.First().Value as DrawingOrder,this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public bool GenerateNode(DrawingOrder drawingOrder, Node parentNode)
|
||||
{
|
||||
if (drawingOrder == null)
|
||||
{
|
||||
GD.PrintErr("DrawingOrder is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parentNode == null)
|
||||
{
|
||||
GD.PrintErr("Parent node is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 遍历 DrawingOrder 的 DrawNodes 列表
|
||||
foreach (var drawNode in drawingOrder.DrawNodes)
|
||||
{
|
||||
if (!CreateNode(drawNode, parentNode))
|
||||
{
|
||||
GD.PrintErr($"Failed to create node: {drawNode.NodeName}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
private bool CreateNode(DrawNode drawNode, Node parentNode)
|
||||
{
|
||||
if (string.IsNullOrEmpty(drawNode.NodeName))
|
||||
{
|
||||
GD.PrintErr("NodeName is null or empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 创建新节点并添加到父节点
|
||||
var newNode = new ColorRect();
|
||||
newNode.Name = drawNode.NodeName;
|
||||
parentNode.AddChild(newNode);
|
||||
|
||||
// 如果存在子节点,递归创建
|
||||
foreach (var child in drawNode.Children)
|
||||
{
|
||||
if (!CreateNode(child, newNode))
|
||||
{
|
||||
GD.PrintErr($"Failed to create child node: {child.NodeName}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1
Script/Generate/PlayerGenerate.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://yl4050ru0ros
|
45
Script/Item/BagItem.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public partial class BagItem
|
||||
{
|
||||
public ItemResource itemResource;
|
||||
public int amount;
|
||||
|
||||
public string ItemName
|
||||
{
|
||||
get
|
||||
{
|
||||
return itemResource?.ItemName ?? "Unknown"; // 防止空引用
|
||||
}
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return itemResource?.Description ?? "No description"; // 防止空引用
|
||||
}
|
||||
}
|
||||
|
||||
public void AddAmount(int value)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
GD.PrintErr("Cannot add negative amount to BagItem.");
|
||||
return;
|
||||
}
|
||||
amount += value;
|
||||
}
|
||||
|
||||
public void RemoveAmount(int value)
|
||||
{
|
||||
if (value < 0 || value > amount)
|
||||
{
|
||||
GD.PrintErr("Invalid amount to remove from BagItem.");
|
||||
return;
|
||||
}
|
||||
amount -= value;
|
||||
}
|
||||
}
|
1
Script/Item/BagItem.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://bbwjvic0ilxan
|
11
Script/Item/ItemResource.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class ItemResource : Resource
|
||||
{
|
||||
[Export] public string ItemName{ get; private set; }
|
||||
[Export] public string Description{ get; private set; }
|
||||
[Export] public Texture2D Icon{ get; private set; }
|
||||
[Export] public bool Stackable{ get; private set; }
|
||||
}
|
1
Script/Item/ItemResource.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://d02in2v01dbtb
|
125
Script/Item/Projectile.cs
Normal file
@ -0,0 +1,125 @@
|
||||
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);
|
||||
}
|
1
Script/Item/Projectile.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dg675fsx6dpv1
|
6
Script/Loader/Attribute/NeedTranslate.cs
Normal file
@ -0,0 +1,6 @@
|
||||
using System;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class NeedTranslateAttribute : Attribute
|
||||
{
|
||||
}
|
1
Script/Loader/Attribute/NeedTranslate.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://ikk1jy48d475
|
13
Script/Loader/Define/Character.cs
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
|
||||
namespace Cosmobox.Def
|
||||
{
|
||||
public partial class Character : Define
|
||||
{
|
||||
public DrawingOrder
|
||||
drawingOrder_down,
|
||||
drawingOrder_up,
|
||||
drawingOrder_left,
|
||||
drawingOrder_right;
|
||||
}
|
||||
}
|
1
Script/Loader/Define/Character.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://criteyjl5dksn
|
42
Script/Loader/Define/Define.cs
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Cosmobox.Def
|
||||
{
|
||||
public class Define
|
||||
{
|
||||
public string defName;
|
||||
[NeedTranslate]
|
||||
public string label;
|
||||
[NeedTranslate]
|
||||
public string discription;
|
||||
/// <summary>
|
||||
/// 初始化方法,根据传入的 XML 元素 (<paramref name="xmlDef"/>) 进行处理。
|
||||
/// </summary>
|
||||
/// <param name="xmlDef">包含定义信息的 XML 元素。</param>
|
||||
/// <returns>
|
||||
/// 返回一个布尔值:
|
||||
/// - 如果返回 <c>false</c>,表示按照默认方式处理(依次对 XML 进行变量名识别和赋值)。
|
||||
/// - 如果返回 <c>true</c>,表示使用自定义方式处理,不进行额外的默认处理。
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// 该方法的基类实现会自动识别并处理以下三个变量:
|
||||
/// - <c>defName</c>
|
||||
/// - <c>label</c>
|
||||
/// - <c>description</c>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// 如果需要覆盖默认行为,可以在派生类中重写此方法,并返回 <c>true</c>
|
||||
/// 以指示框架跳过默认处理逻辑。
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public virtual bool Init(XElement xmlDef)
|
||||
{
|
||||
defName = xmlDef.Element("defName")?.Value;
|
||||
label = xmlDef.Element("label")?.Value;
|
||||
discription = xmlDef.Element("discription")?.Value;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
1
Script/Loader/Define/Define.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://btgw3kqfk2i6y
|
24
Script/Loader/Define/DrawNode.cs
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Cosmobox.Def
|
||||
{
|
||||
public partial class DrawNode : Define
|
||||
{
|
||||
public string NodeName { get; set; }
|
||||
public List<DrawNode> Children { get; set; } = [];
|
||||
public override bool Init(XElement xmlDef)
|
||||
{
|
||||
base.Init(xmlDef);
|
||||
NodeName = xmlDef.Element("NodeName")?.Value;
|
||||
foreach (var childNode in xmlDef.Elements("DrawNode"))
|
||||
{
|
||||
DrawNode child = new DrawNode();
|
||||
child.Init(childNode);
|
||||
Children.Add(child);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
1
Script/Loader/Define/DrawNode.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://by1lt06g8xkiy
|
23
Script/Loader/Define/DrawingOrder.cs
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
namespace Cosmobox.Def
|
||||
{
|
||||
public class DrawingOrder : Define
|
||||
{
|
||||
public List<DrawNode> DrawNodes { get; set; } = new List<DrawNode>();
|
||||
|
||||
public override bool Init(XElement xmlDef)
|
||||
{
|
||||
base.Init(xmlDef);
|
||||
foreach (var node in xmlDef.Elements("DrawNodes"))
|
||||
{
|
||||
DrawNode drawNode = new DrawNode();
|
||||
drawNode.Init(node);
|
||||
DrawNodes.Add(drawNode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
1
Script/Loader/Define/DrawingOrder.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://coat5tts3smlo
|
177
Script/Loader/InitResource.cs
Normal file
@ -0,0 +1,177 @@
|
||||
using Cosmobox.Def;
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
|
||||
|
||||
namespace Cosmobox
|
||||
{
|
||||
public partial class InitResource : Node
|
||||
{
|
||||
public static InitResource instance;
|
||||
#if DEBUG
|
||||
static readonly string corePath = "D:\\godot_Project\\app\\打怪\\Data";
|
||||
#else
|
||||
static readonly string corePath = "Data";
|
||||
#endif
|
||||
static readonly string coreNamespace = "Cosmobox.Def.";
|
||||
|
||||
public Dictionary<string, Dictionary<string, Define>> defines = new();
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
// 在节点准备就绪时调用初始化方法
|
||||
Init();
|
||||
instance = this;
|
||||
}
|
||||
public void Init()
|
||||
{
|
||||
// 获取程序所在的目录路径
|
||||
string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
// 构建Data目录的完整路径
|
||||
string dataDirectory = Path.Combine(appDirectory, corePath);
|
||||
|
||||
try
|
||||
{
|
||||
// 检查Data目录是否存在
|
||||
if (Directory.Exists(dataDirectory))
|
||||
{
|
||||
// 获取Data目录下的所有子文件夹
|
||||
string[] subDirectories = Directory.GetDirectories(dataDirectory);
|
||||
|
||||
// 遍历并输出每个子文件夹的名称
|
||||
foreach (string dir in subDirectories)
|
||||
{
|
||||
string[] xmlFiles = Directory.GetFiles(dir, "*.xml", SearchOption.AllDirectories);
|
||||
foreach (string xmlFile in xmlFiles)
|
||||
{
|
||||
// GD.Print($"找到XML文件: {xmlFile}");
|
||||
// 调用加载XML数据的方法
|
||||
LoadXmlData(xmlFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.Print($"Data目录不存在: {dataDirectory}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GD.Print($"发生错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
public void LoadXmlData(string xmlFilePath)
|
||||
{
|
||||
// 检查文件是否存在
|
||||
if (!File.Exists(xmlFilePath))
|
||||
{
|
||||
GD.Print($"XML文件不存在: {xmlFilePath}");
|
||||
return;
|
||||
}
|
||||
XDocument xdoc = XDocument.Load(xmlFilePath);
|
||||
// 解析Define节点
|
||||
XElement rootElement = xdoc.Root;
|
||||
|
||||
if (rootElement != null)
|
||||
{
|
||||
if (rootElement.Name == "Define")
|
||||
{
|
||||
foreach (var element in rootElement.Elements())
|
||||
{
|
||||
var def = LoadDefine(element);
|
||||
var className = element.Name.ToString();
|
||||
var name = element.Element("defName")?.Value;
|
||||
if (def != null && !string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(className))
|
||||
{
|
||||
defines.TryAdd(className, new Dictionary<string, Define>());
|
||||
defines[className][name] = (Define)def;
|
||||
}
|
||||
GD.Print(name, " ", def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public object LoadDefine(XElement xElement)
|
||||
{
|
||||
string className = xElement.Name.ToString();
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
Type type;
|
||||
if (!className.Contains('.'))
|
||||
{
|
||||
// 尝试拼接默认命名空间
|
||||
string fullClassName = coreNamespace + className;
|
||||
type = assembly.GetType(fullClassName);
|
||||
|
||||
// 如果拼接命名空间后仍找不到,尝试直接查找(可能是全局命名空间下的类)
|
||||
if (type == null)
|
||||
{
|
||||
type = assembly.GetType(className);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 直接查找
|
||||
type = assembly.GetType(className);
|
||||
}
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
GD.PrintErr($"未定义的类型: {className}");
|
||||
return null;
|
||||
}
|
||||
|
||||
var constructor = type.GetConstructor(Type.EmptyTypes);
|
||||
if (constructor == null)
|
||||
{
|
||||
GD.PrintErr($"{className} 必须包含无参构造函数");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 3. 创建实例
|
||||
object instance;
|
||||
try
|
||||
{
|
||||
instance = Activator.CreateInstance(type);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GD.PrintErr($"创建 {className} 实例失败: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 4. 检查是否继承自 Define
|
||||
if (instance is not Define define)
|
||||
{
|
||||
GD.PrintErr($"{className} 必须继承自 Define");
|
||||
return null;
|
||||
}
|
||||
define.Init(xElement);
|
||||
return define;
|
||||
// SetField(define, "Address", "123 Main St");
|
||||
}
|
||||
|
||||
public static void SetField(object obj, string fieldName, object value)
|
||||
{
|
||||
Type type = obj.GetType();
|
||||
FieldInfo field = type.GetField(fieldName);
|
||||
|
||||
if (field != null)
|
||||
{
|
||||
field.SetValue(obj, Convert.ChangeType(value, field.FieldType));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Field '{fieldName}' not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
1
Script/Loader/InitResource.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://cxwpi2iikslsq
|
214
Script/Map/DoubleMap.cs
Normal file
@ -0,0 +1,214 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using static Cosmobox.TileType;
|
||||
|
||||
namespace Cosmobox
|
||||
{
|
||||
|
||||
public partial class DoubleMap : Node
|
||||
{
|
||||
[Export] TileMapLayer displayLayer;
|
||||
[Export] TileMapLayer mapLayer;
|
||||
|
||||
PerlinNoise perlinNoise = new(1573);
|
||||
|
||||
|
||||
readonly Dictionary<Tuple<TileType, TileType, TileType, TileType>, Vector3I> neighboursToAtlasCoord = new() {
|
||||
{new (Grass, Grass, Grass, Grass), new Vector3I(2, 1,0)}, // All corners
|
||||
{new (Dirt, Dirt, Dirt, Grass), new Vector3I(1, 3,0)}, // Outer bottom-right corner
|
||||
{new (Dirt, Dirt, Grass, Dirt), new Vector3I(0, 0,0)}, // Outer bottom-left corner
|
||||
{new (Dirt, Grass, Dirt, Dirt), new Vector3I(0, 2,0)}, // Outer top-right corner
|
||||
{new (Grass, Dirt, Dirt, Dirt), new Vector3I(3, 3,0)}, // Outer top-left corner
|
||||
{new (Dirt, Grass, Dirt, Grass), new Vector3I(1, 0,0)}, // Right edge
|
||||
{new (Grass, Dirt, Grass, Dirt), new Vector3I(3, 2,0)}, // Left edge
|
||||
{new (Dirt, Dirt, Grass, Grass), new Vector3I(3, 0,0)}, // Bottom edge
|
||||
{new (Grass, Grass, Dirt, Dirt), new Vector3I(1, 2,0)}, // Top edge
|
||||
{new (Dirt, Grass, Grass, Grass), new Vector3I(1, 1,0)}, // Inner bottom-right corner
|
||||
{new (Grass, Dirt, Grass, Grass), new Vector3I(2, 0,0)}, // Inner bottom-left corner
|
||||
{new (Grass, Grass, Dirt, Grass), new Vector3I(2, 2,0)}, // Inner top-right corner
|
||||
{new (Grass, Grass, Grass, Dirt), new Vector3I(3, 1,0)}, // Inner top-left corner
|
||||
{new (Dirt, Grass, Grass, Dirt), new Vector3I(2, 3,0)}, // Bottom-left top-right corners
|
||||
{new (Grass, Dirt, Dirt, Grass), new Vector3I(0, 1,0)}, // Top-left down-right corners
|
||||
{new (Dirt, Dirt, Dirt, Dirt), new Vector3I(0, 3,0)}, // No corners
|
||||
|
||||
|
||||
// {new (Grass, Grass, Grass, Grass), new Vector3I(2, 1,1)}, // All corners
|
||||
{new (Water, Water, Water, Grass), new Vector3I(1, 3,1)}, // Outer bottom-right corner
|
||||
{new (Water, Water, Grass, Water), new Vector3I(0, 0,1)}, // Outer bottom-left corner
|
||||
{new (Water, Grass, Water, Water), new Vector3I(0, 2,1)}, // Outer top-right corner
|
||||
{new (Grass, Water, Water, Water), new Vector3I(3, 3,1)}, // Outer top-left corner
|
||||
{new (Water, Grass, Water, Grass), new Vector3I(1, 0,1)}, // Right edge
|
||||
{new (Grass, Water, Grass, Water), new Vector3I(3, 2,1)}, // Left edge
|
||||
{new (Water, Water, Grass, Grass), new Vector3I(3, 0,1)}, // Bottom edge
|
||||
{new (Grass, Grass, Water, Water), new Vector3I(1, 2,1)}, // Top edge
|
||||
{new (Water, Grass, Grass, Grass), new Vector3I(1, 1,1)}, // Inner bottom-right corner
|
||||
{new (Grass, Water, Grass, Grass), new Vector3I(2, 0,1)}, // Inner bottom-left corner
|
||||
{new (Grass, Grass, Water, Grass), new Vector3I(2, 2,1)}, // Inner top-right corner
|
||||
{new (Grass, Grass, Grass, Water), new Vector3I(3, 1,1)}, // Inner top-left corner
|
||||
{new (Water, Grass, Grass, Water), new Vector3I(2, 3,1)}, // Bottom-left top-right corners
|
||||
{new (Grass, Water, Water, Grass), new Vector3I(0, 1,1)}, // Top-left down-right corners
|
||||
{new (Water, Water, Water, Water), new Vector3I(0, 3,1)}, // No corners
|
||||
|
||||
// {new (Dirt, Dirt, Dirt, Dirt), new Vector3I(2, 1,2)}, // All corners
|
||||
{new (Water, Water, Water, Dirt), new Vector3I(1, 3,2)}, // Outer bottom-right corner
|
||||
{new (Water, Water, Dirt, Water), new Vector3I(0, 0,2)}, // Outer bottom-left corner
|
||||
{new (Water, Dirt, Water, Water), new Vector3I(0, 2,2)}, // Outer top-right corner
|
||||
{new (Dirt, Water, Water, Water), new Vector3I(3, 3,2)}, // Outer top-left corner
|
||||
{new (Water, Dirt, Water, Dirt), new Vector3I(1, 0,2)}, // Right edge
|
||||
{new (Dirt, Water, Dirt, Water), new Vector3I(3, 2,2)}, // Left edge
|
||||
{new (Water, Water, Dirt, Dirt), new Vector3I(3, 0,2)}, // Bottom edge
|
||||
{new (Dirt, Dirt, Water, Water), new Vector3I(1, 2,2)}, // Top edge
|
||||
{new (Water, Dirt, Dirt, Dirt), new Vector3I(1, 1,2)}, // Inner bottom-right corner
|
||||
{new (Dirt, Water, Dirt, Dirt), new Vector3I(2, 0,2)}, // Inner bottom-left corner
|
||||
{new (Dirt, Dirt, Water, Dirt), new Vector3I(2, 2,2)}, // Inner top-right corner
|
||||
{new (Dirt, Dirt, Dirt, Water), new Vector3I(3, 1,2)}, // Inner top-left corner
|
||||
{new (Water, Dirt, Dirt, Water), new Vector3I(2, 3,2)}, // Bottom-left top-right corners
|
||||
{new (Dirt, Water, Water, Dirt), new Vector3I(0, 1,2)}, // Top-left down-right corners
|
||||
|
||||
{ new (Grass, Dirt, Water, Grass), new Vector3I(0, 0,3)},
|
||||
{ new (Dirt, Water, Grass, Grass), new Vector3I(1, 0,3)},
|
||||
{ new (Water, Dirt, Grass, Grass), new Vector3I(2, 0,3)},
|
||||
{ new (Dirt, Grass, Grass, Water), new Vector3I(3, 0,3)},
|
||||
{ new (Grass, Water, Grass, Dirt), new Vector3I(3, 1,3)},
|
||||
{ new (Grass, Dirt, Grass, Water), new Vector3I(3, 2,3)},
|
||||
{ new (Grass, Water, Dirt, Grass), new Vector3I(3, 3,3)},
|
||||
{ new (Grass, Grass, Water, Dirt), new Vector3I(2, 3,3)},
|
||||
{ new (Grass, Grass, Dirt, Water), new Vector3I(1, 3,3)},
|
||||
{ new (Water, Grass, Grass, Dirt), new Vector3I(0, 3,3)},
|
||||
{ new (Dirt, Grass, Water, Grass), new Vector3I(0, 2,3)},
|
||||
{ new (Water, Grass, Dirt, Grass), new Vector3I(0, 1,3)},
|
||||
|
||||
{ new (Dirt, Grass, Water, Dirt), new Vector3I(0, 0,4)},
|
||||
{ new (Grass, Water, Dirt, Dirt), new Vector3I(1, 0,4)},
|
||||
{ new (Water, Grass, Dirt, Dirt), new Vector3I(2, 0,4)},
|
||||
{ new (Grass, Dirt, Dirt, Water), new Vector3I(3, 0,4)},
|
||||
{ new (Dirt, Water, Dirt, Grass), new Vector3I(3, 1,4)},
|
||||
{ new (Dirt, Grass, Dirt, Water), new Vector3I(3, 2,4)},
|
||||
{ new (Dirt, Water, Grass, Dirt), new Vector3I(3, 3,4)},
|
||||
{ new (Dirt, Dirt, Water, Grass), new Vector3I(2, 3,4)},
|
||||
{ new (Dirt, Dirt, Grass, Water), new Vector3I(1, 3,4)},
|
||||
{ new (Water, Dirt, Dirt, Grass), new Vector3I(0, 3,4)},
|
||||
{ new (Grass, Dirt, Water, Dirt), new Vector3I(0, 2,4)},
|
||||
{ new (Water, Dirt, Grass, Dirt), new Vector3I(0, 1,4)},
|
||||
|
||||
{ new (Water, Grass, Dirt, Water), new Vector3I(0, 0,5)},
|
||||
{ new (Grass, Dirt, Water, Water), new Vector3I(1, 0,5)},
|
||||
{ new (Dirt, Grass, Water, Water), new Vector3I(2, 0,5)},
|
||||
{ new (Grass, Water, Water, Dirt), new Vector3I(3, 0,5)},
|
||||
{ new (Water, Dirt, Water, Grass), new Vector3I(3, 1,5)},
|
||||
{ new (Water, Grass, Water, Dirt), new Vector3I(3, 2,5)},
|
||||
{ new (Water, Dirt, Grass, Water), new Vector3I(3, 3,5)},
|
||||
{ new (Water, Water, Dirt, Grass), new Vector3I(2, 3,5)},
|
||||
{ new (Water, Water, Grass, Dirt), new Vector3I(1, 3,5)},
|
||||
{ new (Dirt, Water, Water, Grass), new Vector3I(0, 3,5)},
|
||||
{ new (Grass, Water, Dirt, Water), new Vector3I(0, 2,5)},
|
||||
{ new (Dirt, Water, Grass, Water), new Vector3I(0, 1,5)},
|
||||
};
|
||||
|
||||
private static readonly Vector2I[] _shifts =
|
||||
[
|
||||
new(0, 0),
|
||||
new(1, 0),
|
||||
new(0, 1),
|
||||
new(1, 1)
|
||||
];
|
||||
public override void _Ready()
|
||||
{
|
||||
int wide = 100;
|
||||
float scale = 0.1f; // 缩放因子
|
||||
|
||||
for (int i = 0; i < wide; i++)
|
||||
{
|
||||
for (int j = 0; j < wide; j++)
|
||||
{
|
||||
// 获取噪声值并归一化到 [0, 1]
|
||||
var noiseValue = perlinNoise.Noise(i * scale, j * scale, 0);
|
||||
var val = (noiseValue + 1) / 2;
|
||||
|
||||
// 根据噪声值设置地形类型
|
||||
if (val > 0.3)
|
||||
{
|
||||
mapLayer.SetCell(new Vector2I(i, j), 0, TileTypeToAtlasCoord(Grass));
|
||||
}
|
||||
else if (val > 0.25)
|
||||
{
|
||||
mapLayer.SetCell(new Vector2I(i, j), 0, TileTypeToAtlasCoord(Dirt));
|
||||
}
|
||||
else
|
||||
{
|
||||
mapLayer.SetCell(new Vector2I(i, j), 0, TileTypeToAtlasCoord(Water));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateDisplay();
|
||||
}
|
||||
public void UpdateDisplay()
|
||||
{
|
||||
var tilePos = mapLayer.GetUsedCells();
|
||||
foreach (var pos in tilePos)
|
||||
{
|
||||
UpdateDisplay(pos);
|
||||
// UpdateDisplay(pos - new Vector2I(1, 0));
|
||||
// UpdateDisplay(pos - new Vector2I(1, 1));
|
||||
// UpdateDisplay(pos - new Vector2I(0, 1));
|
||||
}
|
||||
}
|
||||
public void UpdateDisplay(Vector2I coord)
|
||||
{
|
||||
var key = GetNearTileData(coord);
|
||||
if (neighboursToAtlasCoord.TryGetValue(key, out Vector3I atlasCoord))
|
||||
{
|
||||
displayLayer.SetCell(coord, atlasCoord[2], new(atlasCoord[0], atlasCoord[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
displayLayer.SetCell(coord, 1, new(0, 3));
|
||||
}
|
||||
|
||||
}
|
||||
public TileType GetTileType(Vector2I pos)
|
||||
{
|
||||
var cell = mapLayer.GetCellAtlasCoords(pos);
|
||||
return AtlasCoordToTileType(cell);
|
||||
}
|
||||
public static TileType AtlasCoordToTileType(Vector2I coord)
|
||||
{
|
||||
return coord switch
|
||||
{
|
||||
Vector2I(0, 0) => Grass,
|
||||
Vector2I(1, 0) => Dirt,
|
||||
Vector2I(2, 0) => Water,
|
||||
_ => Water,
|
||||
};
|
||||
}
|
||||
public static Vector2I TileTypeToAtlasCoord(TileType tileType)
|
||||
{
|
||||
return tileType switch
|
||||
{
|
||||
Grass => new(0, 0),
|
||||
Dirt => new(1, 0),
|
||||
Water => new(2, 0),
|
||||
_ => new(0, 0),
|
||||
};
|
||||
}
|
||||
public Tuple<TileType, TileType, TileType, TileType> GetNearTileData(Vector2I coord)
|
||||
{
|
||||
return new Tuple<TileType, TileType, TileType, TileType>(
|
||||
GetTileType(coord + _shifts[0]),
|
||||
GetTileType(coord + _shifts[1]),
|
||||
GetTileType(coord + _shifts[2]),
|
||||
GetTileType(coord + _shifts[3])
|
||||
);
|
||||
}
|
||||
|
||||
public void SetTile(Vector2I pos, TileType tileType)
|
||||
{
|
||||
mapLayer.SetCell(pos, 0, TileTypeToAtlasCoord(tileType));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
1
Script/Map/DoubleMap.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://bc2ats1ib4dde
|
10
Script/Map/TileType.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Cosmobox
|
||||
{
|
||||
public enum TileType
|
||||
{
|
||||
None,
|
||||
Grass,
|
||||
Water,
|
||||
Dirt,
|
||||
}
|
||||
}
|
1
Script/Map/TileType.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dqd3d18u1e3r5
|
71
Script/Pawn/BagItemList.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
namespace Cosmobox
|
||||
{
|
||||
public partial class BagItemList
|
||||
{
|
||||
public List<BagItem> Items = new();
|
||||
|
||||
// 查找物品
|
||||
public BagItem Find(string name)
|
||||
{
|
||||
foreach (var item in Items)
|
||||
{
|
||||
if (item.ItemName == name)
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 添加物品
|
||||
public bool AddItem(ItemResource resource, int amount = 1)
|
||||
{
|
||||
if (resource == null || amount <= 0)
|
||||
{
|
||||
GD.PrintErr("Invalid item or amount.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否已有相同物品
|
||||
var existingItem = Find(resource.ItemName);
|
||||
if (existingItem != null && resource.Stackable)
|
||||
{
|
||||
existingItem.AddAmount(amount); // 堆叠物品
|
||||
}
|
||||
else
|
||||
{
|
||||
// 创建新物品条目
|
||||
var newItem = new BagItem
|
||||
{
|
||||
itemResource = resource,
|
||||
amount = amount
|
||||
};
|
||||
Items.Add(newItem);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 移除物品
|
||||
public bool RemoveItem(string name, int amount = 1)
|
||||
{
|
||||
var item = Find(name);
|
||||
if (item == null)
|
||||
{
|
||||
GD.Print($"Item '{name}' not found in bag.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (amount >= item.amount)
|
||||
{
|
||||
Items.Remove(item); // 完全移除物品
|
||||
return true;
|
||||
}
|
||||
|
||||
item.RemoveAmount(amount); // 减少数量
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
1
Script/Pawn/BagItemList.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://b1fsx76po5ksu
|
225
Script/Pawn/CameraControl.cs
Normal file
@ -0,0 +1,225 @@
|
||||
using Godot;
|
||||
using System;
|
||||
namespace Cosmobox
|
||||
{
|
||||
public partial class CameraControl : Camera2D
|
||||
{
|
||||
[Export] public Node2D Target; // 要跟随的目标(通常为玩家角色)
|
||||
[Export] public bool EnableSmoothing = true; // 启用平滑跟随
|
||||
[Export(PropertyHint.Range, "0.1,10,0.1")]
|
||||
public float SmoothingSpeed = 2.5f; // 平滑跟随速度(推荐值2.0-4.0)
|
||||
|
||||
[Export] public bool EnableBounds = false; // 启用边界限制
|
||||
[Export] public Rect2 CameraBounds; // 摄像机移动边界
|
||||
|
||||
[Export] public Vector2 PositionOffset = Vector2.Zero; // 目标位置偏移
|
||||
[Export] public bool ScaleWithZoom = true; // 边界是否随缩放调整
|
||||
|
||||
[Export] public float DeadZoneRadius = 0; // 摄像机不移动的半径(减少微小移动)
|
||||
|
||||
[Export] public float ZoomSensitivity = 0.1f; // 缩放灵敏度
|
||||
[Export] public Vector2 MinZoom = new Vector2(0.5f, 0.5f); // 最小缩放
|
||||
[Export] public Vector2 MaxZoom = new Vector2(2.0f, 2.0f); // 最大缩放
|
||||
|
||||
private Vector2 _targetPosition;
|
||||
private Vector2 _currentVelocity = Vector2.Zero; // 用于平滑插值
|
||||
private Rect2 _effectiveBounds; // 实际使用的边界(考虑缩放)
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
if (Target == null)
|
||||
{
|
||||
// 自动查找玩家作为目标
|
||||
Target = GetTree().Root.GetNodeOrNull<Node2D>("Player");
|
||||
if (Target == null)
|
||||
{
|
||||
GD.PrintErr("CameraControl: Failed to find Player node. Assign a Target manually.");
|
||||
}
|
||||
}
|
||||
|
||||
// 确保摄像机位置初始化
|
||||
if (Target != null)
|
||||
{
|
||||
_targetPosition = Target.GlobalPosition + PositionOffset;
|
||||
GlobalPosition = _targetPosition;
|
||||
}
|
||||
|
||||
// 初始化有效边界
|
||||
UpdateEffectiveBounds();
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
if (Target == null)
|
||||
return;
|
||||
|
||||
float deltaFloat = (float)delta;
|
||||
|
||||
// 更新目标位置(考虑偏移)
|
||||
Vector2 newTarget = Target.GlobalPosition + PositionOffset;
|
||||
|
||||
// 应用死区减少微小移动
|
||||
if (DeadZoneRadius > 0 && newTarget.DistanceTo(_targetPosition) < DeadZoneRadius)
|
||||
{
|
||||
newTarget = _targetPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
_targetPosition = newTarget;
|
||||
}
|
||||
|
||||
// 应用边界限制
|
||||
if (EnableBounds)
|
||||
{
|
||||
UpdateEffectiveBounds();
|
||||
_targetPosition = ClampPosition(_targetPosition);
|
||||
}
|
||||
|
||||
// 应用平滑过渡或直接跟随
|
||||
Vector2 newPosition;
|
||||
if (EnableSmoothing && SmoothingSpeed > 0)
|
||||
{
|
||||
// 使用SmoothDamp获得更自然的缓动效果
|
||||
newPosition = SmoothDamp(GlobalPosition, _targetPosition, ref _currentVelocity, 1 / SmoothingSpeed, deltaFloat);
|
||||
}
|
||||
else
|
||||
{
|
||||
newPosition = _targetPosition;
|
||||
}
|
||||
|
||||
// 最终位置赋值
|
||||
GlobalPosition = newPosition;
|
||||
}
|
||||
|
||||
public override void _UnhandledInput(InputEvent @event)
|
||||
{
|
||||
// 鼠标滚轮缩放控制
|
||||
if (@event is InputEventMouseButton mouseEvent)
|
||||
{
|
||||
if (mouseEvent.IsPressed())
|
||||
{
|
||||
Vector2 zoomFactor = Zoom;
|
||||
|
||||
// // 滚轮向上 - 放大
|
||||
// if (mouseEvent.ButtonIndex == MouseButton.WheelUp)
|
||||
// {
|
||||
// zoomFactor -= Vector2.One * ZoomSensitivity;
|
||||
// }
|
||||
// // 滚轮向下 - 缩小
|
||||
// else if (mouseEvent.ButtonIndex == MouseButton.WheelDown)
|
||||
// {
|
||||
// zoomFactor += Vector2.One * ZoomSensitivity;
|
||||
// }
|
||||
|
||||
// // 钳制缩放值
|
||||
// zoomFactor.X = Mathf.Clamp(zoomFactor.X, MinZoom.X, MaxZoom.X);
|
||||
// zoomFactor.Y = Mathf.Clamp(zoomFactor.Y, MinZoom.Y, MaxZoom.Y);
|
||||
|
||||
if (zoomFactor != Zoom)
|
||||
{
|
||||
Zoom = zoomFactor;
|
||||
UpdateEffectiveBounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 平滑插值函数(类似Unity的SmoothDamp)
|
||||
/// </summary>
|
||||
private Vector2 SmoothDamp(Vector2 current, Vector2 target, ref Vector2 currentVelocity, float smoothTime, float deltaTime, float maxSpeed = float.MaxValue)
|
||||
{
|
||||
float omega = 2f / Mathf.Max(0.0001f, smoothTime);
|
||||
float x = omega * deltaTime;
|
||||
float exp = 1f / (1f + x + 0.48f * x * x + 0.235f * x * x * x);
|
||||
Vector2 change = current - target;
|
||||
Vector2 originalTarget = target;
|
||||
|
||||
float maxChange = maxSpeed * smoothTime;
|
||||
|
||||
// 使用自定义方法替代ClampMagnitude
|
||||
float magnitude = change.Length();
|
||||
if (magnitude > maxChange && maxChange > 0)
|
||||
{
|
||||
change = change.Normalized() * maxChange;
|
||||
}
|
||||
|
||||
target = current - change;
|
||||
|
||||
Vector2 temp = (currentVelocity + omega * change) * deltaTime;
|
||||
currentVelocity = (currentVelocity - omega * temp) * exp;
|
||||
Vector2 result = target + (change + temp) * exp;
|
||||
|
||||
// 防止过冲
|
||||
Vector2 toOriginalTarget = originalTarget - current;
|
||||
Vector2 toResult = result - originalTarget;
|
||||
if (toOriginalTarget.Dot(toResult) > 0)
|
||||
{
|
||||
result = originalTarget;
|
||||
currentVelocity = (result - originalTarget) / deltaTime;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新实际使用的边界(考虑缩放)
|
||||
/// </summary>
|
||||
private void UpdateEffectiveBounds()
|
||||
{
|
||||
if (!EnableBounds || !ScaleWithZoom)
|
||||
{
|
||||
_effectiveBounds = CameraBounds;
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据缩放比例调整边界
|
||||
Vector2 halfViewSize = GetViewportRect().Size * 0.5f / Zoom;
|
||||
Vector2 min = CameraBounds.Position + halfViewSize;
|
||||
Vector2 max = CameraBounds.End - halfViewSize;
|
||||
|
||||
// 确保有效边界有效
|
||||
if (min.X > max.X) min.X = max.X = (min.X + max.X) * 0.5f;
|
||||
if (min.Y > max.Y) min.Y = max.Y = (min.Y + max.Y) * 0.5f;
|
||||
|
||||
_effectiveBounds = new Rect2(min, max - min);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 钳制位置在边界范围内
|
||||
/// </summary>
|
||||
private Vector2 ClampPosition(Vector2 position)
|
||||
{
|
||||
return new Vector2(
|
||||
Mathf.Clamp(position.X, _effectiveBounds.Position.X, _effectiveBounds.End.X),
|
||||
Mathf.Clamp(position.Y, _effectiveBounds.Position.Y, _effectiveBounds.End.Y)
|
||||
);
|
||||
}
|
||||
|
||||
// 调试:在编辑器中绘制边界可视化
|
||||
public override void _Draw()
|
||||
{
|
||||
if (Engine.IsEditorHint() && EnableBounds)
|
||||
{
|
||||
// 绘制主边界
|
||||
var rect = new Rect2(_effectiveBounds.Position - GlobalPosition, _effectiveBounds.Size);
|
||||
DrawRect(rect, Colors.Red, false, 2.0f);
|
||||
|
||||
// 绘制原始边界参考线
|
||||
var origRect = new Rect2(CameraBounds.Position - GlobalPosition, CameraBounds.Size);
|
||||
DrawRect(origRect, Colors.Yellow, false, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置摄像机边界(简化API)
|
||||
/// </summary>
|
||||
public void SetBounds(Rect2 bounds, bool updateImmediately = true)
|
||||
{
|
||||
CameraBounds = bounds;
|
||||
EnableBounds = true;
|
||||
if (updateImmediately)
|
||||
UpdateEffectiveBounds();
|
||||
}
|
||||
}
|
||||
}
|
1
Script/Pawn/CameraControl.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://bhpimjcr0h66h
|
232
Script/Pawn/CharacterLoader.cs
Normal file
@ -0,0 +1,232 @@
|
||||
using Godot;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
namespace Cosmobox
|
||||
{
|
||||
public static class CharacterLoader
|
||||
{
|
||||
// 支持的部件目录列表
|
||||
private static readonly string[] ComponentFolders = {
|
||||
"body", "clothing", "hair", "hairBackground", "head", "leftEar", "rightEar"
|
||||
};
|
||||
|
||||
// 方向关键词映射到索引位置
|
||||
private static readonly Dictionary<string, int> DirectionMapping = new Dictionary<string, int>(System.StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{"south", 0}, // 南方向 - 索引0
|
||||
{"north", 1}, // 北方向 - 索引1
|
||||
{"east", 2}, // 东方向 - 索引2
|
||||
{"west", 2} // 西方向也映射到索引2(共用东方向的纹理)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 加载角色所有部件的纹理
|
||||
/// </summary>
|
||||
public static Dictionary<string, Texture2D[]> LoadCharacterTextures(string rootPath)
|
||||
{
|
||||
var textures = new Dictionary<string, Texture2D[]>();
|
||||
// GD.Print($"开始加载角色纹理资源,根目录: {rootPath}");
|
||||
|
||||
// 检查根目录是否存在
|
||||
if (!DirAccess.DirExistsAbsolute(rootPath))
|
||||
{
|
||||
// GD.PrintErr($"错误:资源根目录不存在 - {rootPath}");
|
||||
return textures;
|
||||
}
|
||||
|
||||
using (var dir = DirAccess.Open(rootPath))
|
||||
{
|
||||
if (dir == null)
|
||||
{
|
||||
GD.PrintErr($"错误:无法打开根目录 - {rootPath}");
|
||||
return textures;
|
||||
}
|
||||
|
||||
// GD.Print($"找到根目录,开始扫描部件文件夹...");
|
||||
|
||||
// 遍历所有支持的部件目录
|
||||
foreach (string component in ComponentFolders)
|
||||
{
|
||||
string componentPath = Path.Combine(rootPath, component);
|
||||
// GD.Print($"检查部件: {component},路径: {componentPath}");
|
||||
|
||||
if (DirAccess.DirExistsAbsolute(componentPath))
|
||||
{
|
||||
// GD.Print($"找到部件文件夹: {component}");
|
||||
Texture2D[] componentTextures = LoadComponentTextures(componentPath);
|
||||
|
||||
if (componentTextures != null && componentTextures.Length == 3)
|
||||
{
|
||||
// GD.Print($"成功加载部件: {component},纹理数量: 3");
|
||||
textures[component] = componentTextures;
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.PrintErr($"警告:部件{component}纹理加载不完整,实际数量: {componentTextures?.Length ?? 0}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// GD.Print($"部件文件夹不存在: {component}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GD.Print($"资源加载完成,成功部件: {textures.Count}/{ComponentFolders.Length}");
|
||||
return textures;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载单个部件的所有方向纹理
|
||||
/// </summary>
|
||||
private static Texture2D[] LoadComponentTextures(string folderPath)
|
||||
{
|
||||
Texture2D[] textures = new Texture2D[3];
|
||||
var foundFiles = new List<(string path, int index)>();
|
||||
// GD.Print($"加载部件文件夹: {folderPath}");
|
||||
|
||||
using (var dir = DirAccess.Open(folderPath))
|
||||
{
|
||||
if (dir == null)
|
||||
{
|
||||
GD.PrintErr($"错误:无法打开部件目录 - {folderPath}");
|
||||
return textures;
|
||||
}
|
||||
|
||||
var status = dir.ListDirBegin();
|
||||
if (status != Error.Ok)
|
||||
{
|
||||
GD.PrintErr($"错误:无法开始文件列表 ({status}) - {folderPath}");
|
||||
return textures;
|
||||
}
|
||||
|
||||
string fileName = dir.GetNext();
|
||||
int fileCount = 0;
|
||||
int matchedCount = 0;
|
||||
List<string> unmatchedFiles = new List<string>();
|
||||
|
||||
// GD.Print($"开始扫描文件...");
|
||||
|
||||
while (!string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
fileCount++;
|
||||
if (!dir.CurrentIsDir())
|
||||
{
|
||||
string filePath = Path.Combine(folderPath, fileName);
|
||||
// GD.Print($"处理文件 #{fileCount}: {fileName}");
|
||||
|
||||
// 检查文件扩展名
|
||||
if (!IsImageFile(fileName))
|
||||
{
|
||||
// GD.Print($"跳过非图片文件: {fileName}");
|
||||
fileName = dir.GetNext();
|
||||
continue;
|
||||
}
|
||||
|
||||
bool matched = false;
|
||||
|
||||
// 检测方向关键词
|
||||
foreach (var kv in DirectionMapping)
|
||||
{
|
||||
if (fileName.Contains(kv.Key, System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// GD.Print($"找到方向关键词 '{kv.Key}' -> 索引 {kv.Value}");
|
||||
foundFiles.Add((filePath, kv.Value));
|
||||
matched = true;
|
||||
matchedCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched)
|
||||
{
|
||||
GD.PrintErr($"警告:无法识别的方向名称 - {fileName}");
|
||||
unmatchedFiles.Add(fileName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// GD.Print($"跳过子目录: {fileName}");
|
||||
}
|
||||
|
||||
fileName = dir.GetNext();
|
||||
}
|
||||
|
||||
dir.ListDirEnd();
|
||||
|
||||
// GD.Print($"文件夹扫描完成:");
|
||||
// GD.Print($"- 总文件: {fileCount}");
|
||||
// GD.Print($"- 匹配文件: {matchedCount}");
|
||||
|
||||
if (unmatchedFiles.Count > 0)
|
||||
{
|
||||
GD.PrintErr($"警告: {unmatchedFiles.Count} 个文件未包含方向关键词(south/north/east/west):");
|
||||
foreach (var f in unmatchedFiles)
|
||||
{
|
||||
GD.PrintErr($" - {f}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否所有方向都找到了文件
|
||||
bool[] foundDirections = new bool[3];
|
||||
|
||||
// 加载纹理
|
||||
foreach (var (path, index) in foundFiles)
|
||||
{
|
||||
if (index >= 0 && index < textures.Length)
|
||||
{
|
||||
if (textures[index] == null)
|
||||
{
|
||||
// GD.Print($"加载纹理: {Path.GetFileName(path)} -> 方向索引 {index}");
|
||||
textures[index] = ResourceLoader.Load<Texture2D>(path);
|
||||
foundDirections[index] = true;
|
||||
|
||||
if (textures[index] == null)
|
||||
{
|
||||
GD.PrintErr($"错误:无法加载纹理资源 - {path}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.Print($"跳过纹理: {Path.GetFileName(path)} -> 方向索引 {index}(已有更优先的纹理)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.PrintErr($"错误:无效方向索引 {index} - {path}");
|
||||
}
|
||||
}
|
||||
|
||||
// 检查缺失的方向
|
||||
for (int i = 0; i < foundDirections.Length; i++)
|
||||
{
|
||||
if (!foundDirections[i])
|
||||
{
|
||||
string direction;
|
||||
if (i == 0) direction = "south";
|
||||
else if (i == 1) direction = "north";
|
||||
else direction = "east";
|
||||
|
||||
GD.PrintErr($"警告:缺少{direction}方向纹理");
|
||||
}
|
||||
}
|
||||
|
||||
return textures;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查文件是否是图片格式
|
||||
/// </summary>
|
||||
private static bool IsImageFile(string fileName)
|
||||
{
|
||||
string ext = Path.GetExtension(fileName).ToLower();
|
||||
return ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".webp" || ext == ".bmp";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1
Script/Pawn/CharacterLoader.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://cvdj4q7yvd85a
|
252
Script/Pawn/Pawn.cs
Normal file
@ -0,0 +1,252 @@
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 方向纹理设置方法
|
||||
/// 每个方法设置角色在特定方向的纹理
|
||||
/// </summary>
|
||||
public void SetDownDirection() => SetTextures(0, false); // 设置向下方向的纹理
|
||||
public void SetUpDirection() => SetTextures(1, false); // 设置向上方向的纹理
|
||||
public void SetRightDirection() => SetTextures(2, false); // 设置向右方向的纹理
|
||||
public void SetLeftDirection() => SetTextures(2, true); // 设置向左方向的纹理(使用翻转)
|
||||
|
||||
/// <summary>
|
||||
/// 核心纹理设置方法
|
||||
/// 为角色各部分设置纹理和水平翻转状态
|
||||
/// </summary>
|
||||
/// <param name="index">纹理索引:0=下, 1=上, 2=侧边</param>
|
||||
/// <param name="flipH">是否水平翻转(用于左右方向)</param>
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 简化版移动处理 - 直接存储输入方向
|
||||
/// 实际移动在物理处理过程中完成
|
||||
/// </summary>
|
||||
/// <param name="inputDirection">输入方向向量</param>
|
||||
protected void HandleMovement(Vector2 inputDirection)
|
||||
{
|
||||
// 存储当前输入方向,移动计算在物理过程中处理
|
||||
currentMovementInput = inputDirection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据移动向量更新角色朝向
|
||||
/// </summary>
|
||||
/// <param name="direction">移动方向向量</param>
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应用加载的纹理到各个角色部件
|
||||
/// </summary>
|
||||
/// <param name="loadedTextures">加载的纹理字典</param>
|
||||
private void ApplyLoadedTextures(Dictionary<string, Texture2D[]> 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 工具方法
|
||||
/// </summary>
|
||||
|
||||
// 瞬间传送角色到指定位置
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加瞬间冲量(直接改变位置)
|
||||
/// 注意:对于持续的推动效果可能需要单独实现
|
||||
/// </summary>
|
||||
public void AddImpulse(Vector2 impulse)
|
||||
{
|
||||
// 直接修改位置 - 适用于瞬间位移
|
||||
// 如需持续推动效果,需单独实现冲量系统
|
||||
Position += impulse;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
1
Script/Pawn/Pawn.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://doim6711upf0a
|
141
Script/Pawn/Player.cs
Normal file
@ -0,0 +1,141 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic; // 使用 List 和 Dictionary 需要这个命名空间
|
||||
|
||||
namespace Cosmobox
|
||||
{
|
||||
public partial class Player : Pawn, IThing
|
||||
{
|
||||
// === 玩家属性 ===
|
||||
[Export] public Camera2D PlayerCamera; // 玩家摄像机
|
||||
[Export] public Sprite2D AimCursor; // 瞄准光标精灵
|
||||
[Export] public Vector2 AimOffset = Vector2.Zero; // 瞄准点偏移量
|
||||
|
||||
public BagItemList bagItem = new();
|
||||
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
// 调用基类的_Ready方法
|
||||
base._Ready();
|
||||
|
||||
// 尝试查找摄像机(如果未分配)
|
||||
if (PlayerCamera == null)
|
||||
{
|
||||
PlayerCamera = GetViewport().GetCamera2D();
|
||||
if (PlayerCamera == null)
|
||||
{
|
||||
GD.PrintErr("Player: 未分配摄像机且视口中没有活动摄像机!");
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化瞄准光标
|
||||
if (AimCursor != null)
|
||||
{
|
||||
AimCursor.Visible = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Update(double delta)
|
||||
{
|
||||
// 获取输入方向
|
||||
Vector2 inputDirection = GetInputDirection();
|
||||
|
||||
// 处理移动(调用Pawn基类方法)
|
||||
HandleMovement(inputDirection);
|
||||
|
||||
// 更新角色朝向(鼠标方向)
|
||||
UpdateDirectionToMouse();
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新角色朝向鼠标方向
|
||||
/// </summary>
|
||||
private void UpdateDirectionToMouse()
|
||||
{
|
||||
if (PlayerCamera == null) return;
|
||||
|
||||
// 获取鼠标在游戏世界中的位置
|
||||
Vector2 mousePosition = GetGlobalMousePosition();
|
||||
|
||||
// 计算从玩家位置到鼠标位置的方向向量
|
||||
Vector2 directionToMouse = (mousePosition - GlobalPosition).Normalized();
|
||||
|
||||
// 调用基类方法更新视觉方向
|
||||
UpdateDirection(directionToMouse);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新瞄准光标位置
|
||||
/// </summary>
|
||||
private void UpdateAimCursor()
|
||||
{
|
||||
if (AimCursor == null || PlayerCamera == null) return;
|
||||
|
||||
// 获取鼠标位置
|
||||
Vector2 mousePosition = GetGlobalMousePosition();
|
||||
|
||||
// 设置光标位置(带偏移)
|
||||
AimCursor.GlobalPosition = mousePosition + AimOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取键盘输入方向
|
||||
/// </summary>
|
||||
/// <returns>归一化的移动方向向量</returns>
|
||||
private Vector2 GetInputDirection()
|
||||
{
|
||||
Vector2 direction = Vector2.Zero;
|
||||
|
||||
// 处理上下左右输入(确保项目设置中已配置这些输入)
|
||||
if (Input.IsActionPressed("ui_up"))
|
||||
{
|
||||
direction.Y -= 1; // 上移
|
||||
}
|
||||
if (Input.IsActionPressed("ui_down"))
|
||||
{
|
||||
direction.Y += 1; // 下移
|
||||
}
|
||||
if (Input.IsActionPressed("ui_left"))
|
||||
{
|
||||
direction.X -= 1; // 左移
|
||||
}
|
||||
if (Input.IsActionPressed("ui_right"))
|
||||
{
|
||||
direction.X += 1; // 右移
|
||||
}
|
||||
|
||||
return direction.Normalized(); // 确保斜向移动速度一致
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取瞄准方向(从玩家指向鼠标位置)
|
||||
/// </summary>
|
||||
public Vector2 GetAimDirection()
|
||||
{
|
||||
if (PlayerCamera == null) return Vector2.Zero;
|
||||
|
||||
Vector2 mousePosition = GetGlobalMousePosition();
|
||||
return (mousePosition - GlobalPosition).Normalized();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取瞄准角度(弧度)
|
||||
/// </summary>
|
||||
public float GetAimAngle()
|
||||
{
|
||||
Vector2 aimDir = GetAimDirection();
|
||||
return Mathf.Atan2(aimDir.Y, aimDir.X);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取瞄准角度(度)
|
||||
/// </summary>
|
||||
public float GetAimAngleDegrees()
|
||||
{
|
||||
return Mathf.RadToDeg(GetAimAngle());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
1
Script/Pawn/Player.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://c1g503q7yoy1s
|
45
Script/UI/BagItemUI.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using Godot;
|
||||
using System;
|
||||
namespace Cosmobox
|
||||
{
|
||||
public partial class BagItemUI : Button
|
||||
{
|
||||
[Export] public TextureRect icon;
|
||||
[Export] public Label count, itemName;
|
||||
[Export] public Control itemNamePanel;
|
||||
[Export] public Texture2D emptyIcon;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
itemNamePanel.Visible = false;
|
||||
}
|
||||
|
||||
public void SetItem(BagItem bagItem)
|
||||
{
|
||||
if (bagItem == null || bagItem.itemResource == null)
|
||||
{
|
||||
SetEmpty();
|
||||
return;
|
||||
}
|
||||
itemName.Text = bagItem.itemResource.ItemName;
|
||||
icon.Texture = bagItem.itemResource.Icon ?? emptyIcon;
|
||||
count.Text = bagItem.amount > 0 ? bagItem.amount.ToString() : "空";
|
||||
}
|
||||
|
||||
public void SetEmpty()
|
||||
{
|
||||
icon.Texture = emptyIcon;
|
||||
count.Text = "空";
|
||||
}
|
||||
void _on_mouse_entered()
|
||||
{
|
||||
itemNamePanel.Visible = true;
|
||||
// GD.Print("鼠标进入");
|
||||
}
|
||||
void _on_mouse_exited()
|
||||
{
|
||||
itemNamePanel.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1
Script/UI/BagItemUI.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://cc7chrmpuw4vu
|
101
Script/UI/BagUI.cs
Normal file
@ -0,0 +1,101 @@
|
||||
using Godot;
|
||||
using System;
|
||||
namespace Cosmobox
|
||||
{
|
||||
public partial class BagUI : Control
|
||||
{
|
||||
[Export] public Player player;
|
||||
[Export] public Label text;
|
||||
[Export] public Panel background;
|
||||
[Export] public Control itemContainer;
|
||||
[Export] public float animationTime = 0.5f;
|
||||
|
||||
[Export] public PackedScene itemUI;
|
||||
private float animationTimeRun = 0;
|
||||
private bool isOpen = false;
|
||||
|
||||
private Vector2 labelOriginalPosition;
|
||||
private Vector2 backgroundOriginalPosition;
|
||||
|
||||
public bool IsOpen
|
||||
{
|
||||
get { return isOpen; }
|
||||
}
|
||||
public override void _Ready()
|
||||
{
|
||||
labelOriginalPosition = text.Position;
|
||||
backgroundOriginalPosition = background.Position;
|
||||
// animationTimeRun = 0.01f;
|
||||
text.Position = new Vector2(text.Position.X, labelOriginalPosition.Y - text.Size.Y);
|
||||
background.Position = new Vector2(background.Position.X, backgroundOriginalPosition.Y + (background.Size.Y + 50));
|
||||
isOpen = false;
|
||||
|
||||
}
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (animationTimeRun > 0)
|
||||
{
|
||||
animationTimeRun -= (float)delta;
|
||||
if (isOpen)
|
||||
{
|
||||
text.Position = new Vector2(text.Position.X, labelOriginalPosition.Y - (animationTimeRun / animationTime) * text.Size.Y);
|
||||
background.Position = new Vector2(background.Position.X, backgroundOriginalPosition.Y + (animationTimeRun / animationTime) * (background.Size.Y + 50));
|
||||
if (animationTimeRun <= 0)
|
||||
{
|
||||
text.Position = labelOriginalPosition;
|
||||
background.Position = backgroundOriginalPosition;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
text.Position = new Vector2(text.Position.X, labelOriginalPosition.Y - (1 - animationTimeRun / animationTime) * text.Size.Y);
|
||||
background.Position = new Vector2(background.Position.X, backgroundOriginalPosition.Y + (1 - animationTimeRun / animationTime) * (background.Size.Y + 50));
|
||||
if (animationTimeRun <= 0)
|
||||
{
|
||||
Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public void OpenBag()
|
||||
{
|
||||
Visible = true;
|
||||
isOpen = true;
|
||||
UpdateUI();
|
||||
animationTimeRun = animationTime - animationTimeRun;
|
||||
isOpen = true;
|
||||
}
|
||||
public void CloseBag()
|
||||
{
|
||||
isOpen = false;
|
||||
animationTimeRun = animationTime - animationTimeRun;
|
||||
isOpen = false;
|
||||
}
|
||||
|
||||
public void UpdateUI()
|
||||
{
|
||||
// 清除容器中现有的所有子节点
|
||||
foreach (Node child in itemContainer.GetChildren())
|
||||
{
|
||||
child.QueueFree();
|
||||
}
|
||||
|
||||
var bagItems = player.bagItem.Items;
|
||||
|
||||
foreach (BagItem item in bagItems)
|
||||
{
|
||||
// 实例化新的物品UI
|
||||
BagItemUI itemInstance = (BagItemUI)itemUI.Instantiate();
|
||||
|
||||
// 设置物品数据
|
||||
itemInstance.SetItem(item);
|
||||
|
||||
// 将实例添加到容器中
|
||||
itemContainer.AddChild(itemInstance);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
1
Script/UI/BagUI.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dry2x5otnbedt
|
73
Script/UI/DevUi.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using Godot;
|
||||
using System;
|
||||
namespace Cosmobox
|
||||
{
|
||||
public partial class DevUi : Control
|
||||
{
|
||||
[Export] public Player player;
|
||||
[Export] public Container itemDevList; // 改为Container类型更准确
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
InitializeItemButtons();
|
||||
}
|
||||
|
||||
private void InitializeItemButtons()
|
||||
{
|
||||
// // 清空现有按钮(如果有)
|
||||
// foreach (Node child in itemDevList.GetChildren())
|
||||
// {
|
||||
// child.QueueFree();
|
||||
// }
|
||||
|
||||
// 获取所有物品
|
||||
var items = ItemResourceManager.GetAllItems();
|
||||
|
||||
// 为每个物品创建按钮
|
||||
foreach (var itemPair in items)
|
||||
{
|
||||
var button = new Button();
|
||||
button.Text = $"{itemPair.Key}"; // 显示物品名称
|
||||
|
||||
// 绑定点击事件,使用闭包捕获当前物品名称
|
||||
string currentItemName = itemPair.Key;
|
||||
button.Pressed += () => OnItemButtonPressed(currentItemName);
|
||||
|
||||
itemDevList.AddChild(button);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnItemButtonPressed(string itemName)
|
||||
{
|
||||
// 添加物品到背包
|
||||
bool success = AddItem(itemName);
|
||||
|
||||
if (success)
|
||||
{
|
||||
GD.Print($"成功添加物品: {itemName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.PrintErr($"添加物品失败: {itemName}");
|
||||
}
|
||||
}
|
||||
|
||||
public bool AddItem(string itemName, int amount = 1)
|
||||
{
|
||||
var item = ItemResourceManager.GetItem(itemName);
|
||||
if (item == null)
|
||||
{
|
||||
GD.PrintErr($"物品不存在: {itemName}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return player.bagItem.AddItem(item, amount);
|
||||
}
|
||||
public bool ClearItems()
|
||||
{
|
||||
player.bagItem.Items.Clear();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1
Script/UI/DevUi.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://bpaoua3tyv5ju
|
69
export_presets.cfg
Normal file
@ -0,0 +1,69 @@
|
||||
[preset.0]
|
||||
|
||||
name="Windows Desktop"
|
||||
platform="Windows Desktop"
|
||||
runnable=true
|
||||
advanced_options=false
|
||||
dedicated_server=false
|
||||
custom_features=""
|
||||
export_filter="all_resources"
|
||||
include_filter=""
|
||||
exclude_filter=""
|
||||
export_path="../app/打怪/肉鸽.exe"
|
||||
patches=PackedStringArray()
|
||||
encryption_include_filters=""
|
||||
encryption_exclude_filters=""
|
||||
seed=0
|
||||
encrypt_pck=false
|
||||
encrypt_directory=false
|
||||
script_export_mode=2
|
||||
|
||||
[preset.0.options]
|
||||
|
||||
custom_template/debug=""
|
||||
custom_template/release=""
|
||||
debug/export_console_wrapper=1
|
||||
binary_format/embed_pck=false
|
||||
texture_format/s3tc_bptc=true
|
||||
texture_format/etc2_astc=false
|
||||
binary_format/architecture="x86_64"
|
||||
codesign/enable=false
|
||||
codesign/timestamp=true
|
||||
codesign/timestamp_server_url=""
|
||||
codesign/digest_algorithm=1
|
||||
codesign/description=""
|
||||
codesign/custom_options=PackedStringArray()
|
||||
application/modify_resources=false
|
||||
application/icon=""
|
||||
application/console_wrapper_icon=""
|
||||
application/icon_interpolation=4
|
||||
application/file_version=""
|
||||
application/product_version=""
|
||||
application/company_name=""
|
||||
application/product_name=""
|
||||
application/file_description=""
|
||||
application/copyright=""
|
||||
application/trademarks=""
|
||||
application/export_angle=0
|
||||
application/export_d3d12=0
|
||||
application/d3d12_agility_sdk_multiarch=true
|
||||
ssh_remote_deploy/enabled=false
|
||||
ssh_remote_deploy/host="user@host_ip"
|
||||
ssh_remote_deploy/port="22"
|
||||
ssh_remote_deploy/extra_args_ssh=""
|
||||
ssh_remote_deploy/extra_args_scp=""
|
||||
ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}'
|
||||
$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}'
|
||||
$trigger = New-ScheduledTaskTrigger -Once -At 00:00
|
||||
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
|
||||
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings
|
||||
Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true
|
||||
Start-ScheduledTask -TaskName godot_remote_debug
|
||||
while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 }
|
||||
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue"
|
||||
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
|
||||
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
|
||||
Remove-Item -Recurse -Force '{temp_dir}'"
|
||||
dotnet/include_scripts_content=false
|
||||
dotnet/include_debug_symbols=true
|
||||
dotnet/embed_build_outputs=false
|
1
icon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>
|
After Width: | Height: | Size: 994 B |
37
icon.svg.import
Normal file
@ -0,0 +1,37 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://u3du2w54mu65"
|
||||
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.svg"
|
||||
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
94
project.godot
Normal file
@ -0,0 +1,94 @@
|
||||
; Engine configuration file.
|
||||
; It's best edited using the editor UI and not directly,
|
||||
; since the parameters that go here are not all obvious.
|
||||
;
|
||||
; Format:
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=5
|
||||
|
||||
[application]
|
||||
|
||||
config/name="苍穹沙盘"
|
||||
run/main_scene="uid://8u0ex56qvckx"
|
||||
config/features=PackedStringArray("4.4", "C#", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[autoload]
|
||||
|
||||
InitResource="*res://Script/Loader/InitResource.cs"
|
||||
|
||||
[display]
|
||||
|
||||
window/size/viewport_width=1280
|
||||
window/size/viewport_height=720
|
||||
window/stretch/mode="viewport"
|
||||
|
||||
[dotnet]
|
||||
|
||||
project/assembly_name="肉鸽"
|
||||
|
||||
[input]
|
||||
|
||||
ui_left={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194319,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
ui_right={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194321,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
ui_up={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194320,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
ui_down={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194322,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
fire={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
next_weapon={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":5,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
prev_weapon={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":4,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
bag={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":66,"key_label":0,"unicode":66,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
dev_ui={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194332,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[rendering]
|
||||
|
||||
textures/canvas_textures/default_texture_filter=0
|
BIN
图片/Item/None.png
Normal file
After Width: | Height: | Size: 187 B |
34
图片/Item/None.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://w54e0f3ya7js"
|
||||
path="res://.godot/imported/None.png-1673d38dec04531aa4df4447579f8800.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Item/None.png"
|
||||
dest_files=["res://.godot/imported/None.png-1673d38dec04531aa4df4447579f8800.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Item/gress.png
Normal file
After Width: | Height: | Size: 187 KiB |
34
图片/Item/gress.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c6sgy6n73g1c7"
|
||||
path="res://.godot/imported/gress.png-787f6c4d560db2c86436a579e70229ec.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Item/gress.png"
|
||||
dest_files=["res://.godot/imported/gress.png-787f6c4d560db2c86436a579e70229ec.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Map/GrassDirtDirtWater.png
Normal file
After Width: | Height: | Size: 656 B |
34
图片/Map/GrassDirtDirtWater.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://x6gjynrbk15s"
|
||||
path="res://.godot/imported/GrassDirtDirtWater.png-dd99f0dc59981c6357749a73e0aa305b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Map/GrassDirtDirtWater.png"
|
||||
dest_files=["res://.godot/imported/GrassDirtDirtWater.png-dd99f0dc59981c6357749a73e0aa305b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Map/GrassDirtWaterWater.png
Normal file
After Width: | Height: | Size: 680 B |
34
图片/Map/GrassDirtWaterWater.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://s3fgr2wdr3ch"
|
||||
path="res://.godot/imported/GrassDirtWaterWater.png-91e5c5460637dd29051723dede8d2956.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Map/GrassDirtWaterWater.png"
|
||||
dest_files=["res://.godot/imported/GrassDirtWaterWater.png-91e5c5460637dd29051723dede8d2956.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Map/GrassGrassDirtWater.png
Normal file
After Width: | Height: | Size: 876 B |
34
图片/Map/GrassGrassDirtWater.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://be4nredmg77id"
|
||||
path="res://.godot/imported/GrassGrassDirtWater.png-7b17c61552a9e93ef33ddec03a115684.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Map/GrassGrassDirtWater.png"
|
||||
dest_files=["res://.godot/imported/GrassGrassDirtWater.png-7b17c61552a9e93ef33ddec03a115684.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Map/GrassSoild.png
Normal file
After Width: | Height: | Size: 1001 B |
34
图片/Map/GrassSoild.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bwkcydgr21obu"
|
||||
path="res://.godot/imported/GrassSoild.png-d32d8df03f038815e08a49cb73bc79c3.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Map/GrassSoild.png"
|
||||
dest_files=["res://.godot/imported/GrassSoild.png-d32d8df03f038815e08a49cb73bc79c3.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Map/GrassWater.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
34
图片/Map/GrassWater.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b07lrfhxsp5ix"
|
||||
path="res://.godot/imported/GrassWater.png-10e785415d88d5ca2811d03f0677395f.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Map/GrassWater.png"
|
||||
dest_files=["res://.godot/imported/GrassWater.png-10e785415d88d5ca2811d03f0677395f.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Map/SoildWater.png
Normal file
After Width: | Height: | Size: 915 B |
34
图片/Map/SoildWater.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dwnoufv3ysra5"
|
||||
path="res://.godot/imported/SoildWater.png-64b003ede6dedea499537982faafa3cf.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Map/SoildWater.png"
|
||||
dest_files=["res://.godot/imported/SoildWater.png-64b003ede6dedea499537982faafa3cf.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Map/mapType.png
Normal file
After Width: | Height: | Size: 340 B |
34
图片/Map/mapType.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cd2e0hmqkwg43"
|
||||
path="res://.godot/imported/mapType.png-6bb0d869802fe7ac656c5459efe416f1.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Map/mapType.png"
|
||||
dest_files=["res://.godot/imported/mapType.png-6bb0d869802fe7ac656c5459efe416f1.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Object/bullet.png
Normal file
After Width: | Height: | Size: 148 B |
34
图片/Object/bullet.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cqo4d16yxek4d"
|
||||
path="res://.godot/imported/bullet.png-c6b7a42f90e838752364880488a15f62.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Object/bullet.png"
|
||||
dest_files=["res://.godot/imported/bullet.png-c6b7a42f90e838752364880488a15f62.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Plyear/body/east.png
Normal file
After Width: | Height: | Size: 26 KiB |
34
图片/Plyear/body/east.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://3jyj45tr880k"
|
||||
path="res://.godot/imported/east.png-85556d23645cf691403da7a0f0ff414d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Plyear/body/east.png"
|
||||
dest_files=["res://.godot/imported/east.png-85556d23645cf691403da7a0f0ff414d.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Plyear/body/north.png
Normal file
After Width: | Height: | Size: 33 KiB |
34
图片/Plyear/body/north.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bjxgk4i2p5adw"
|
||||
path="res://.godot/imported/north.png-9646ab1ad958f3526ed645aaf2fc948e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Plyear/body/north.png"
|
||||
dest_files=["res://.godot/imported/north.png-9646ab1ad958f3526ed645aaf2fc948e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Plyear/body/south.png
Normal file
After Width: | Height: | Size: 27 KiB |
34
图片/Plyear/body/south.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bfb4jkr001yc3"
|
||||
path="res://.godot/imported/south.png-a9b4095a928209aa6a4eef1cda7db05b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Plyear/body/south.png"
|
||||
dest_files=["res://.godot/imported/south.png-a9b4095a928209aa6a4eef1cda7db05b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Plyear/clothing/east.png
Normal file
After Width: | Height: | Size: 32 KiB |
34
图片/Plyear/clothing/east.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bwm7l6l5fjpm6"
|
||||
path="res://.godot/imported/east.png-2611e6f195f82b0696e58df57a36574b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Plyear/clothing/east.png"
|
||||
dest_files=["res://.godot/imported/east.png-2611e6f195f82b0696e58df57a36574b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Plyear/clothing/north.png
Normal file
After Width: | Height: | Size: 34 KiB |
34
图片/Plyear/clothing/north.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://becluhw880l15"
|
||||
path="res://.godot/imported/north.png-52dcfeca6042b2ee7688caba862094d7.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Plyear/clothing/north.png"
|
||||
dest_files=["res://.godot/imported/north.png-52dcfeca6042b2ee7688caba862094d7.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Plyear/clothing/south.png
Normal file
After Width: | Height: | Size: 38 KiB |
34
图片/Plyear/clothing/south.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ddwe3fgpw6lws"
|
||||
path="res://.godot/imported/south.png-9d4047e01ed71487c11eb4727a696aa1.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Plyear/clothing/south.png"
|
||||
dest_files=["res://.godot/imported/south.png-9d4047e01ed71487c11eb4727a696aa1.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Plyear/hair/KiiroHair5_east.png
Normal file
After Width: | Height: | Size: 36 KiB |
34
图片/Plyear/hair/KiiroHair5_east.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://btb5kfva4cil0"
|
||||
path="res://.godot/imported/KiiroHair5_east.png-20bf8d448513adc6eb9347cd9bceed15.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Plyear/hair/KiiroHair5_east.png"
|
||||
dest_files=["res://.godot/imported/KiiroHair5_east.png-20bf8d448513adc6eb9347cd9bceed15.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
BIN
图片/Plyear/hair/KiiroHair5_north.png
Normal file
After Width: | Height: | Size: 44 KiB |
34
图片/Plyear/hair/KiiroHair5_north.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://6klx0iccsaqf"
|
||||
path="res://.godot/imported/KiiroHair5_north.png-f6dd2b23d088b05b68ce0882b21dae1b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://图片/Plyear/hair/KiiroHair5_north.png"
|
||||
dest_files=["res://.godot/imported/KiiroHair5_north.png-f6dd2b23d088b05b68ce0882b21dae1b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|