CS基础配置代码

脚本配置

按键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public class GAME_KEY
{
//方向键
public const string lift = "ui_left";
public const string right = "ui_left";
public const string up = "ui_left";
public const string down = "ui_left";

//鼠标(未配置)
public readonly static string Moue_lift = "ui_lift";
public readonly static string Moue_right = "ui_right";

//26字母(未配置)
public readonly static string KEY_A="key_a";
public readonly static string KEY_B="key_b";
public readonly static string KEY_C="key_c";
public readonly static string KEY_D="key_d";
public readonly static string KEY_E="key_e";
public readonly static string KEY_F="key_f";
public readonly static string KEY_G="key_g";
public readonly static string KEY_H="key_h";
public readonly static string KEY_I="key_i";
public readonly static string KEY_J="key_j";
public readonly static string KEY_K="key_k";
public readonly static string KEY_L="key_l";
public readonly static string KEY_M="key_m";
public readonly static string KEY_N="key_n";
public readonly static string KEY_O="key_o";
public readonly static string KEY_P="key_p";
public readonly static string KEY_Q="key_q";
public readonly static string KEY_R="key_r";
public readonly static string KEY_S="key_s";
public readonly static string KEY_T="key_t";
public readonly static string KEY_U="key_u";
public readonly static string KEY_V="key_v";
public readonly static string KEY_W="key_w";
public readonly static string KEY_X="key_s";
public readonly static string KEY_Y="key_y";
public readonly static string KEY_Z="key_z";

//大键盘数字(未配置)
public readonly static string KEY_0="key_0";
public readonly static string KEY_1="key_1";
public readonly static string KEY_2="key_2";
public readonly static string KEY_3="key_3";
public readonly static string KEY_4="key_4";
public readonly static string KEY_5="key_5";
public readonly static string KEY_6="key_6";
public readonly static string KEY_7="key_7";
public readonly static string KEY_8="key_8";
public readonly static string KEY_9="key_9";

//小键盘数字(未配置)
public readonly static string Min_0="min_0";
public readonly static string Min_1="min_1";
public readonly static string Min_2="min_2";
public readonly static string Min_3="min_3";
public readonly static string Min_4="min_4";
public readonly static string Min_5="min_5";
public readonly static string Min_6="min_6";
public readonly static string Min_7="min_7";
public readonly static string Min_8="min_8";
public readonly static string Min_9="min_9";

//F键数字(未配置)
public readonly static string F_0="f_0";
public readonly static string F_1="f_1";
public readonly static string F_2="f_2";
public readonly static string F_3="f_3";
public readonly static string F_4="f_4";
public readonly static string F_5="f_5";
public readonly static string F_6="f_6";
public readonly static string F_7="f_7";
public readonly static string F_8="f_8";
public readonly static string F_9="f_9";

//特殊
public const string Ender = "ui_accept";
public readonly static string Space = "ui_select";
public readonly static string Escape = "ui_cancel";
public readonly static string Tab = "ui_focus_next";
public readonly static string End = "ui_end";
public readonly static string Shift_Tab = "ui_focus_prev";
}

JSON

xlsx和json转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class MyJson
{
/// <summary>
/// 将xlsx文件转换为JSON并创建JSON文件
/// </summary>
/// <param name="xlsxpath">xlsx路径</param>
/// <param name="jsonpath">json输出路径</param>
public void CreateJson(string xlsxpath,string jsonpath)
{
using (var workbook = new XLWorkbook(xlsxpath))
{
var worksheet = workbook.Worksheet(1); // 假设要读取第一个工作表

var dataTable = new System.Data.DataTable();


// 从工作表数据填充到DataTable
foreach (var row in worksheet.RowsUsed())
{


if (row.RowNumber() == 1) // 处理表头
{
foreach (var cell in row.CellsUsed())
{
dataTable.Columns.Add(cell.Value.ToString());
}
}
else // 处理数据行
{
var dataRow = dataTable.NewRow();
foreach (var cell in row.CellsUsed())
{
dataRow[cell.Address.ColumnNumber - 1] = cell.Value.ToString();
}
dataTable.Rows.Add(dataRow);
}
}

// 将DataTable转换为JSON
string json = JsonConvert.SerializeObject(dataTable, Formatting.Indented);
File.WriteAllText(jsonpath, json);
// 打印JSON数据
//Console.WriteLine(json);
GD.Print(json);
//备用路径./Json/xxxc.xlsx
//备用路径./Json/output.json"
}
}
}

读取JSON

  • 方法1,这个会将读取到的值映射到对象的属性(需要对象和JSON匹配)
1
2
3
string json = File.ReadAllText(Directory.GetCurrentDirectory() + "//Json/Player.json");
主场景 obj = System.Text.Json.JsonSerializer.Deserialize<主场景>(json);
GD.Print(obj);
  • 方法2:
1
2
3
4
5
6
7
8
//读取文件
string jsontext = File.ReadAllText(Directory.GetCurrentDirectory() + "//Json/Player.json");
using(JsonDocument doc=JsonDocument.Parse(jsontext)) //解析JSON数据并将其存储在名为"doc"的JsonDocument对象中。
{
JsonElement root=doc.RootElement; //这行代码从JsonDocument中获取根元素并将其存储在名为“root”的JsonElement对象中
string pro=root.GetProperty("id").ToString(); //在这行中,通过调用 GetProperty 方法从根元素中获取名为“id”的属性,并将其值作为字符串存储在变量“pro”中。
GD.Print(doc);
}
  • 方法3:异步读取
1
2
3
4
5
6
// 读取JSON文件
using (FileStream fs = File.OpenRead("path_to_your_json_file"))
{
YourClass obj = await JsonSerializer.DeserializeAsync<YourClass>(fs);
// 对读取的数据进行处理
}

序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.Text.Json;

namespace JsonExample
{
class Program
{
static void Main(string[] args)
{
// 定义一个用于序列化的类
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}

// 创建 Person 类的实例
Person person = new Person
{
Name = "John",
Age = 30
};

// 将 person 对象序列化为 JSON
string jsonString = JsonSerializer.Serialize(person);
Console.WriteLine(jsonString);

// 将 JSON 反序列化为对象
string json = @"{""Name"":""Alice"",""Age"":25}";
Person deserializedPerson = JsonSerializer.Deserialize<Person>(json);
Console.WriteLine($"姓名: {deserializedPerson.Name}, 年龄: {deserializedPerson.Age}");
}
}
}

GUI

背包

  • 格子主题资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public partial class BoxFlatResource : StyleBoxFlat
{
public BoxFlatResource()
{
BgColor=new Color(0.756f,0.736f,0.585f,1); //背景色
DrawCenter = true; //绘制中心
Skew =new Vector2(0, 0); //偏移
CornerDetail = 8; //圆角细节

SetBorderWidthAll(2); //边框宽度
BorderBlend = false; //边框混合
BorderColor = new Color(0, 0, 0, 1); //颜色

SetCornerRadiusAll(3); //圆角半径
SetExpandMarginAll(10); //扩展边距


ShadowColor = new Color(0, 0, 0,1); //阴影颜色
ShadowSize = 0; //阴影大小
ShadowOffset=new Vector2(0,0); //便宜

AntiAliasing = true; //抗锯齿
AntiAliasingSize = 1; //大小

SetContentMarginAll(8); //内容边距

}
}

2D绘制

  • 居中需要将节点和图片的中心位置算出来,然后用节点的中心减去图片的中心位置,就可以得到图片相对节点居中的位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Texture2D imageTexture = ResourceLoader.Load<Texture2D>("res://icon.svg");


// 调用基类的 _Draw 方法
base._Draw();

// 获取图片的原始大小
Vector2 textureSize1 = imageTexture.GetSize();

//缩放图片
Vector2 textureSize = new Vector2(textureSize1.X/2, textureSize1.Y/2);

// 获取当前节点的尺寸
Vector2 nodeSize = Size;

// 计算图片的中心位置
Vector2 centerPosition = new Vector2(nodeSize.X / 2 - textureSize.X / 2, nodeSize.Y / 2 - textureSize.Y / 2);

// 定义图片的显示区域和大小
Rect2 rect = new Rect2(centerPosition, textureSize);

// 使用 draw_texture_rect 方法绘制图片并居中显示
DrawTextureRect(imageTexture, rect, false);

var font = ThemeDB.FallbackFont;
var font_size = 15;

string text = "99";

Vector2 position = new Vector2(45,60);
DrawString(font, position, text, HorizontalAlignment.Left, -1, font_size);
base._Draw();

第三人称C#控制器

  • 条件

    • 需要2个脚本,一个负责旋转相机,一个负责控制角色,两个脚本的节点虽然互相依赖,不过脚本变量不需要

    • 相机节点放在Node3D节点作为自己,通过旋转Node3D节点控制相机朝向,就是说相机始终是朝着Node3D节点看的,当Node3D节点旋转时,相机也相对跟着旋转从而达到一个聚焦在一个点上旋转的目的

    • 玩家节点的话需要创建两个方法,一个用于控制玩家的移动,一个用于控制玩家的旋转,控制玩家移动需要获得Node3D节点来计算,而计算过后还用于控制玩家的旋转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using Godot;

public partial class PlayerCamera : Node3D
{
private bool 鼠标输入;
private float 鼠标输入旋转;
private float 鼠标输入倾斜;
private float 灵敏度 = 0.25f;
private Vector3 欧拉旋转;

[Export] public float TiltUpperLimit = Mathf.DegToRad(-60.0f);
[Export] public float TiltLowerLimit = Mathf.DegToRad(60.0f);

public override void _Ready()
{
// 开始隐藏鼠标
Input.MouseMode = Input.MouseModeEnum.Captured;
}

public override void _PhysicsProcess(double delta)
{
欧拉旋转.X += 鼠标输入倾斜 * (float)delta;
//欧拉旋转.X = Mathf.Clamp(欧拉旋转.X, TiltLowerLimit, TiltUpperLimit); // 限制倾斜角度
欧拉旋转.Y += 鼠标输入旋转 * (float)delta;

// 创建新的变换矩阵
Transform3D newTransform = new Transform3D(Basis.FromEuler(欧拉旋转), Transform.Origin);
Transform = newTransform;

// 初始化鼠标向量
鼠标输入倾斜 = 0.0f;
鼠标输入旋转 = 0.0f;
}

public override void _Input(InputEvent @event)
{
// 初始化鼠标输入为 鼠标移动与获取鼠标模式为隐藏锁定鼠标在视口中心
鼠标输入 = @event is InputEventMouseMotion && Input.MouseMode == Input.MouseModeEnum.Captured;

// 如果鼠标输入满足条件 执行以下代码
if (鼠标输入 && @event is InputEventMouseMotion aa)
{
鼠标输入旋转 = -aa.Relative.X * 灵敏度; // 鼠标x轴旋转
鼠标输入倾斜 = -aa.Relative.Y * 灵敏度; // 鼠标y轴旋转
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
using Godot;

public partial class 玩家控制器 : CharacterBody3D
{
private Node3D _相机父节点;
public Node3D 活动物体;
public Vector3 旋转向量 = Vector3.Forward;

[Export] public float 跳跃力 = 5.0f; // 跳跃力
[Export] public float 移动速度=10;
[Export]public float 旋转速度= 10.0f; // 旋转速度

public override void _Ready()
{
// 获取摄像机节点
_相机父节点 = GetNode<Node3D>("Node3D");
活动物体 = GetNode<Node3D>("机器人");
}

public override void _PhysicsProcess(double delta)
{
//将变量拿出来方便操作
Vector3 velocity = Velocity;

// Add the gravity.如果不发生碰撞则计算重力
if (!IsOnFloor())
{
velocity += GetGravity() * (float)delta;
}

// Handle Jump.跳跃
if (Input.IsActionJustPressed("ui_accept") && IsOnFloor())
{
velocity.Y = 4.5f;
}



//获取玩家移动方向的向量
Vector3 移动方向 = 角色移动();

//如果玩家的移动方向长度大于0.2,则更新旋转向量
if (移动方向.Length() > 0.2f)
{
旋转向量 = 移动方向.Normalized();
}
//将获得的旋转向量给旋转方法,让角色旋转
角色旋转(旋转向量, (float)delta);

//获取玩家的速度方向并分离Y轴
float 速度Y = velocity.Y;
移动方向.Y = 0.0f;
//通过插值让玩家移动
velocity = velocity.Lerp(移动方向 * 移动速度, 10.0f * (float)delta);

//如果移动方向小于等于0则停止移动
if (移动方向.Length() == 0.0f && velocity.Length() < 1.0f)
{
Velocity = Vector3.Zero;
}
//重新设置Velocity变量,将Y轴设置为之前的速度
velocity = new Vector3(velocity.X, 速度Y, velocity.Z);



Velocity = velocity;
MoveAndSlide();
}

private void 角色旋转(Vector3 朝向, float delta)
{
var 左轴 = Vector3.Up.Cross(朝向);
var 基础旋转 = new Basis(左轴, Vector3.Up, 朝向).GetRotationQuaternion();
var 角色缩放 = 活动物体.Transform.Basis.Scale;

// 获取活动物体当前的Transform
Transform3D 当前变换 = 活动物体.Transform;

// 创建新的Basis矩阵并计算赋值
Basis 新基础 = new Basis(活动物体.Transform.Basis.GetRotationQuaternion().Slerp(基础旋转, delta * 旋转速度)).Scaled(角色缩放);

// 更新Transform的Basis
当前变换.Basis = 新基础;

// 应用新的Transform,将计算过后获得的旋转方向更新给活动物体,让其旋转
活动物体.Transform = 当前变换;
}

// 相机矩阵计算返回
private Vector3 角色移动()
{
// 定义变量 获取输入向量
Vector2 输入向量 = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");
// 定义向量初始化为0
Vector3 方向 = Vector3.Zero;
// 输入向量计算平方根
方向.X = -输入向量.X * Mathf.Sqrt(1.0f - 输入向量.Y * 输入向量.Y / 2.0f);
方向.Z = -输入向量.Y * Mathf.Sqrt(1.0f - 输入向量.X * 输入向量.X / 2.0f);
// 输入向量等于相机矩阵*输入向量
方向 = _相机父节点.GlobalTransform.Basis * 方向;
// 初始化Y轴为0
方向.Y = 0.0f;
return -方向;
}
}

}
}
sis * 输入;
// 初始化Y轴为0
输入.Y = 0.0f;
return -输入;
}
}

2024911-30813.jpgtle=”” alt=”2024911-30813.jpg” width=”647”>tle=”” alt=”2024911-30813.jpg” width=”647”>tle=”” alt=”2024911-30813.jpg” width=”647”>

武器篇

武器

武器射击模式类的设想

设想一:通过枚举,即装备组件切换设计状态

设想二:创建一个部件抽象类,他们有一个抽象向方法,且可以重写,武器调用它的抽象方法,然后用于不同模式,且可以通过部件扩展玩法

设想三:通过武器赋予子弹方向初始位置并创建子弹发射,子弹是否在途中实现自己的逻辑

子弹

子弹位置,方向,旋转

1
2
3
4
5
6
7
global_position=武器.子弹位置 #开始位置
linear_velocity=-武器.子弹方向*武器.子弹速度 #发射方向及速度 方向=子弹位置-目标位置再归一化

#重置旋转
var move_direction = 武器.子弹方向
look_at(global_position + move_direction, Vector3.UP)
rotate_object_local(Vector3.RIGHT,deg_to_rad(90))

子弹1:经过一段距离自动销毁,是否会爆炸?,是否穿透敌人?

  • using Godot;
    using System;
    
    public partial class 子弹场景 : MeshInstance3D
    {
        // 定义子弹的速度
        private float _速度 = 10.0f;
        // 定义最大移动距离
        private float _最大移动距离 = 50.0f;
        // 记录子弹的初始位置
        private Vector3 _初始位置;
    
        public override void _Ready()
        {
            // 记录子弹的初始位置
            _初始位置 = GlobalTransform.Origin;
        }
    
        public override void _PhysicsProcess(double delta)
        {
            Vector3 方向 = GlobalTransform.Basis.Z;
            // 移动子弹
            Translate(方向 * _速度 * (float)delta);
    
            // 检查子弹与初始位置的距离
            if (GlobalTransform.Origin.DistanceTo(_初始位置) > _最大移动距离)
            {
                // 超过特定距离后销毁子弹
                QueueFree();
            }
        }
    
    }
    
    #或者
        global_position=武器.子弹位置 #开始位置
        linear_velocity=-武器.子弹方向*武器.子弹速度 #发射方向及速度
    
        #重置旋转
        look_at(global_position - linear_velocity) 位置-速度
        rotate_object_local(Vector3.RIGHT,deg_to_rad(90))###查看是否相同
    
    1
    2
    3
    4

    ```gdscript
    var current_direction = linear_velocity.normalized()
    if not global_position.is_equal_approx(global_position + current_direction):

子弹2:碰到墙面会反弹,是否在地面会滚动?,相对反弹还是角度反弹?

陷阱

地雷:放在地上,怪物碰到会爆炸,对敌人照成伤害

  • 制作思路制作一个地雷类,当怪物碰到时获取敌人信息,并进行减血计算,然后播放爆炸销毁

毒气:当敌人碰撞时,持续对敌人造成伤害

  • 制作思路当放置后开始计时且记录碰撞到的敌人,让其在一定时间后自动销毁,若时间到了记录的敌人还存在,则关闭粗发检测和显示,并计算伤害,当记录的敌人状态全部消失时则销毁

落穴:当敌人碰撞后,生成一个坑,并将敌人陷进去使其无法继续移动

道具

物品类:记录物品的价格数量图标描述属性等

可拾取道具:拥有物品类的信息,记录了物品类的ID,当被拾取时向物品类发出信息更新物品类,然后销毁。

可装备道具:数据存储在物品里,当需要装备时从物品获得数据并实例化一个新的物品装备到玩家身上。

1
2
3
4
5
6
7
# 游戏算法逻辑

## 怪物移动向玩家

```gdscript
var 方向=(玩家全局位置-怪物全局位置).normalized()
怪物.velocity=方向*速度

获取距离玩家最近的敌人,返回最近敌人节点

  • 最近
1
2
3
4
5
6
7
8
9
10
11
12
func 获取所有怪物并返回离玩家最近的怪物(player:CharacterBody3D):
var 怪物数组 = get_children()
var nearestEnemy: Node3D = null
var nearestDistance: float = INF

for enemy in 怪物数组:
if enemy is CharacterBody3D: # 假设敌人是 CharacterBody3D 类型
var distance = player.global_position.distance_to(enemy.global_position)
if distance < nearestDistance:
nearestDistance = distance
nearestEnemy = enemy
return nearestEnemy
  • 最远
1
2
3
4
5
6
7
8
9
10
11
12
13
func 获取所有怪物并返回离玩家最远的怪物(player: CharacterBody3D) -> Node3D:
var enemyArray = get_children()
var farthestEnemy: Node3D = null
var farthestDistance: float = 0.0

for enemy in enemyArray:
if enemy is CharacterBody3D: # 假设敌人是 CharacterBody3D 类型
var distance = player.global_position.distance_to(enemy.global_position)
if distance > farthestDistance:
farthestDistance = distance
farthestEnemy = enemy

return farthestEnemy

获取血量最少的敌人,并返回

1
2
3
4
5
6
7
8
9
10
11
12
13
func 获取所有怪物并返回血量最少的怪物(player: CharacterBody3D) -> Node3D:
var enemyArray = get_children()
var lowestHealthEnemy: Node3D = null
var lowestHealth: float = INF

for enemy in enemyArray:
if enemy is CharacterBody3D: # 假设敌人是 CharacterBody3D 类型
var health = enemy.health # 假设敌人有一个 health 属性
if health < lowestHealth:
lowestHealth = health
lowestHealthEnemy = enemy

return lowestHealthEnemy

GUI

游戏设想

  • 我想制作一个通过部件来强化装备赋予装备效果的游戏,比如通过雷达锁定敌人,通过枪管放大子弹,不过我在开发过程中遇到了难题,就是怎么组合这些武器并给玩家装备上呢,我也希望在GUI上能够实时展示玩家组合后的武器样式。

    • 于是我得出了这个思路

    • 首先将配件单独作为一个资源类,这个类只是存储图标,模型和一些属性和方法等

    • 然后在设计一个类,这个类可以将这些组件和主武器组合起来成为一个新场景,然后赋予玩家使用。

    • 我有个疑问,这个场景文件是怎么记录属性的呢

拖拽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var 物品:武器基类=武器基类.new()
@export var color = Color(1, 0, 0, 1)
func _get_drag_data(position):
#使用不在树中的控件
var cpb = ColorPickerButton.new()
cpb.color = color
cpb.size = Vector2(50, 50)
set_drag_preview(cpb)
return 物品


func _can_drop_data(position, data):
# 检查是否为武器基类
if data is 武器基类:
return true
else:
return false

#数据处理
func _drop_data(position, data):
# 处理拖放的数据
print("Dropped data: ", data)
  • 拖拽改良
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
func _get_drag_data(position):
if 背包.背包[索引ID]:
var cpb =TextureRect.new()
cpb.texture=背包.背包[索引ID].icon
set_drag_preview(cpb)
return 背包.背包[索引ID]


func _can_drop_data(position, data):
# 检查是否为武器基类
if data is 雷达基类:
return true
else:
return false

#数据处理
func _drop_data(position, data):
if 背包.背包[索引ID]!=null:
var ite=背包.背包.find(data)
var temp=背包.背包[索引ID]
背包.背包[索引ID]=data
背包.背包[ite]=temp
else :
var ite=背包.背包.find(data)
背包.背包[索引ID]=data
背包.背包[ite]=null
  • 装备槽
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
extends PanelContainer

@onready var texture_rect: TextureRect = $TextureRect
var 背包:装备槽UI
var 装备:雷达基类
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
背包=get_tree().get_first_node_in_group("装备槽")
pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
刷新纹理()

pass


func _gui_input(event: InputEvent) -> void:
if Input.is_action_just_pressed("鼠标左"):
for i in 背包.背包.size():
if 背包.背包[i]==null:
背包.背包[i]=装备
装备=null
pass

func 刷新纹理():
if 装备!=null:
texture_rect.texture=装备.icon
elif 装备==null:
texture_rect.texture=preload("res://材质/空纹理.png")

#func _get_drag_data(position):
#if 装备:
#var cpb =TextureRect.new()
#cpb.texture=装备.icon
#set_drag_preview(cpb)
#return 装备


func _can_drop_data(position, data):
# 检查是否为武器基类
if data is 雷达基类:
return true
else:
return false

#数据处理
func _drop_data(position, data):
if 装备!=null:
var ite=背包.背包.find(data)
var temp=装备
装备=data
背包.背包[ite]=temp
背包.更换雷达.emit(装备)
else :
var ite=背包.背包.find(data)
装备=data
背包.背包[ite]=null
背包.更换雷达.emit(装备)