分享一波自己写的背包脚本godot4
extends Nodevar utils = load("res://script/utils/index.gd").new()
@onready var items_library_img = load("res://static/items.png")
# 临时物品节点(拖拽时显示)
var dragged_canvas_layer
var dragged_item
# 丢弃提示标签
var drop_label: Label
# 记录拖拽开始位置
var drag_start_position: Vector2
# 最小拖拽距离(超过这个距离才会触发丢弃)
var min_drag_distance: float = 60
# 是否满足丢弃距离条件
var can_drop: bool = false
# 拖拽层级(确保在背包之上)
var drag_layer: int = 10
func _ready():
print("初始化背包系统")
func register_inverntory_handle():
var grid_container = self.find_child("GridContainer")
print("grid_container", self, grid_container)
if grid_container:
for _index in grid_container.get_children().size():
var patent_node = grid_container.get_child(_index)
if utils.has_node_child_by_type(patent_node, "TextureRect"):
var _node = utils.get_node_child_by_type(patent_node, "TextureRect")
_node.connect("gui_input", Callable(self, "_on_inverntory_drop").bind(_node, _index))
#_node.connect("pressed", Callable(self, "_on_inverntory_click"), [], CONNECT_DEFERRED)
func clear_inverntory_handle():
var grid_container = self.find_child("GridContainer")
if grid_container:
for _index in grid_container.get_children().size():
var patent_node = grid_container.get_child(_index)
if utils.has_node_child_by_type(patent_node, "TextureRect"):
var _node = utils.get_node_child_by_type(patent_node, "TextureRect")
_node.disconnect("gui_input", Callable(self, "_on_inverntory_drop").bind(_node, _index))
# 拖拽包中的物品
func _on_inverntory_drop(event: InputEvent, node:TextureRect, index:int):
var dragged_item_pos = Global.PLAYER.get_local_mouse_position()+ Vector2(Global.PLAYER.get_viewport().size / 2)
if event is InputEventMouseButton && event.pressed && event.button_index == MOUSE_BUTTON_LEFT:
drag_start_position = dragged_item_pos
if dragged_canvas_layer:
dragged_canvas_layer.queue_free()
dragged_canvas_layer = null
# 1. 开始拖拽:创建临时物品
dragged_item = Sprite2D.new()
dragged_item.texture = node.texture# 设置物品图标
dragged_item.position = dragged_item_pos
dragged_item.modulate = Color(1, 1, 1, 0.8)
# 创建丢弃提示标签
drop_label = Label.new()
drop_label.text = "丢弃"
drop_label.add_theme_color_override("font_color", Color(1, 0, 0))# 红色文字
drop_label.visible = false# 初始隐藏
# 添加到玩家场景
dragged_canvas_layer = CanvasLayer.new()
dragged_canvas_layer.add_child(dragged_item)
dragged_canvas_layer.add_child(drop_label)
Global.PLAYER.add_child(dragged_canvas_layer)
dragged_item.z_index = drag_layer
drop_label.z_index = drag_layer + 1# 标签层级高于物品
can_drop = false
#
elif event is InputEventMouseMotion && dragged_item:
## 2. 拖拽中:更新临时物品位置
var mouse_pos = dragged_item_pos
dragged_item.position = mouse_pos
# 标签显示在物品右下方
drop_label.position = mouse_pos + Vector2(20, 10)
# 检测是否丢弃
var current_distance = drag_start_position.distance_to(mouse_pos)
var grid_container = self.find_child("GridContainer")
# 检测是否移出背包
if current_distance >= min_drag_distance and grid_container.get_global_rect().has_point(mouse_pos) == false:
if !can_drop:
can_drop = true
dragged_item.modulate = Color(1, 1, 1, 1)# 恢复不透明度
drop_label.visible = true# 显示丢弃文字
else:
if can_drop:
can_drop = false
dragged_item.modulate = Color(1, 1, 1, 0.9)# 降低不透明度
drop_label.visible = false# 隐藏丢弃文字
elif event is InputEventMouseButton && !event.pressed && event.button_index == MOUSE_BUTTON_LEFT && dragged_item:
# 检测是否为交换物品的格子
#
if inverntory_get_slot_at_mouse():
inverntory_swap_items(index, self.find_child("GridContainer").get_children().find(inverntory_get_slot_at_mouse()))
# 检测是否丢弃
var current_distance = drag_start_position.distance_to(dragged_item_pos)
print("current_distance", current_distance)
# 触发点击
if current_distance <= 10:
_on_inverntory_click(node)
## 3. 松开鼠标:丢弃物品
if can_drop:
drop_item(node)
# 清理临时节点
dragged_canvas_layer.queue_free()
dragged_item = null
drop_label = null
dragged_canvas_layer = null
# 把物品加入背包中
func push_inverntory(data, callback):
var is_inverntory_max = true
var toast_node = preload("res://script/utils/toast.gd").new()# 替换为实际节点路径
var grid_container = self.find_child("GridContainer")
for _rect in grid_container.get_children():
var _node = TextureRect.new()
if utils.has_node_child_by_type(_rect, "TextureRect"):
pass
else:
var _atlas_texture = AtlasTexture.new()
_atlas_texture.atlas = items_library_img
_atlas_texture.region = data.icon_rect
_node.texture = _atlas_texture
_node.set_meta("data", data)
is_inverntory_max = false
callback.call()
_rect.add_child(_node)
break
if is_inverntory_max:
toast_node.show_message(self, "背包已满")
self.clear_inverntory_handle()
self.register_inverntory_handle()
# 交换背包
func inverntory_swap_items(start_index, end_index):
if start_index == end_index:
return
var grid = self.find_child("GridContainer")
# 交换网格中的节点
var item1 = grid.get_child(start_index)
var item2 = grid.get_child(end_index)
grid.move_child(item2, start_index)
grid.move_child(item1, end_index)
clear_inverntory_handle()
self.register_inverntory_handle()
# 丢弃背包的品
func drop_item(node):
var item = preload("res://script/items/item.tscn").instantiate()
var game = get_node("/root/game")
game.add_child(item)
item.setTexture(node.texture)
item.setPosition(Global.PLAYER.position)
item.set_meta("data", node.get_meta("data"))
node.queue_free()
# 点击包中的物品
func _on_inverntory_click(node):
Global.PLAYER.equipment_node.equip(node)
# 检测行为是否为交换背包中的物品并且得到该格子
func inverntory_get_slot_at_mouse():
# 获取鼠标下的物品槽
var grid_container = self.find_child("GridContainer")
var mouse_pos = Global.PLAYER.get_local_mouse_position()+ Vector2(get_viewport().size / 2)
for slot in grid_container.get_children():
if slot.get_global_rect().has_point(mouse_pos):
return slot
return null
这个是不是打包成文件比较好,Godot 的资源不多,感谢分享啊
页:
[1]