这一节我们主要学习背包系统中的物品拖拽后,物品放到新的位置,或交换物品位置,如果两个物品属于同一物品则数量相加。具体效果如下:
一、修改item.tscn场景
给item.tscn场景的根节点Item添加Label子节点,命名为NumverCount,用于显示物品数量。然后修改根节点的代码如下:
extends Node2D
@export var number=1 #表示物品的数量
@export var icoUrl="" #表示物品图片
@export var itemname="" #表示物品的名称
@onready var texture_rect = $TextureRect
@onready var numver_count = $NumverCount
func _ready(): #随机载入2张物品图片
if randi()%2==0:#产生个随机数,用2除,余数为0
itemname="宝剑"
icoUrl = "res://Sprites/Inventory/Iron Sword.png"
else:#产生个随机数,用2除,余数不为0
itemname="树枝"
icoUrl = "res://Sprites/Inventory/Tree Branch.png"
setIco(icoUrl)
setNumber(number)
#设置显示数量
func setNumber(numvercount):
number = numvercount
numver_count.text=str(numvercount)
#设置图片
func setIco(icoUrlstr):
texture_rect.texture=load(icoUrlstr)
改代码主要增加了三个属性,一个是物品数量,一个是物品的图片地址,最后一个是物品的名称。增加了2个方法,一个是setNumber方法用于显示物品数量;另一个是setIco函数设置物品图片。
二、修改slot.gd代码。
slot.gd代码修改如下:
extends Panel
#背包背景格子图片,default_text有物品的时候背景格子;empty_text无物品的时候背景格子
var default_text = preload("res://Sprites/Inventory/item_slot_default_background.png")
var empty_text = preload("res://Sprites/Inventory/item_slot_empty_background.png")
var default_style:StyleBoxTexture =null #有物品的时候格子样式
var empty_style:StyleBoxTexture =null #五物品的时候格子样式
var itemClass = preload("res://Scenes/item.tscn") #预加载物品
var item =null #定义物品
func _ready():
default_style = StyleBoxTexture.new() #初始化有物品时候的格子样式
empty_style = StyleBoxTexture.new() #初始化无物品时候的格子样式
default_style.texture = default_text #将有物品时的格子与样式联系起来
empty_style.texture = empty_text #将无物品时的格子与样式联系起来
if randi()%2==0: #产生一个随机数,用2求余 当余数为0时
item = itemClass.instantiate() #实例化物品
add_child(item) #在插槽内加载物品
refresh_style() #刷新样式函数
func refresh_style(): #刷新样式函数
if item==null: #物品为空时,对应设置样式
set("theme_override_styles/panel",empty_style)
else:#物品不为空时,对应设置样式
set("theme_override_styles/panel",default_style)
func getitem(): #返回节点
return item
func removeNode(): #移出节点
if item!=null:
remove_child(item)
item=null
set("theme_override_styles/panel",empty_style)
func PutIntoSlot(textureFrom):#物品拖放功能
if item==null:#如果目标物品栏为空
item = itemClass.instantiate() #实例化物品
add_child(item)
item.texture_rect.texture = textureFrom.item.texture_rect.texture
item.setNumber(textureFrom.item.number)
textureFrom.removeNode()
else:#如果目标物品栏不为空,则物品进行交换
if item.texture_rect.texture==textureFrom.item.texture_rect.texture:
#如果目标物品跟拖放物品数同一商品,则数量相加
item.setNumber(item.number+textureFrom.item.number)
textureFrom.removeNode()
pass
else:#如果目标物品跟拖放物品不同,则交换
var tempItem = item.texture_rect.texture
var tempnumber = item.number
item.texture_rect.texture = textureFrom.item.texture_rect.texture
item.setNumber(textureFrom.item.number)
textureFrom.item.texture_rect.texture = tempItem
textureFrom.item.setNumber(tempnumber)
三、修改一下Inventory场景
在根节点下添加一个Control控件,在该节点上单击右键选择设为场景根节点,这样该场景就变成了Control为根节点了,然后将原来根节点下的子节点拉入到Control节点下,最后删除原来的Node2d节点,并把Control节点命名为Inventory。
最后目录结构如下:
修改根节点代码如下:
extends Control
@onready var grid_container = $GridContainer
#拖拽开始
func _get_drag_data(at_position):
var dragSlotNode = get_slot_node_at_position(at_position) #获取哪个节点被拖放
if dragSlotNode.getitem()==null : return #如果未有物品直接退出
#复制物品节点下的图片作为拖动预览节点
var dragPreviewNode = dragSlotNode.getitem().get_child(0).duplicate()
dragPreviewNode.custom_minimum_size=Vector2(16,16) #设置最小值为16像素
set_drag_preview(dragPreviewNode) # 函数用于设置当节点被拖动时显示的预览图像。
return dragSlotNode
#用于确定一个控件是否能够接受拖放操作中放置的数据。这个函数在控件接收到拖放数据时被调用,允许您根据数据的类型或来源决定是否接受数据。
func _can_drop_data(at_position, data):
var targetSlotNode = get_slot_node_at_position(at_position)
return targetSlotNode !=null
#用于处理拖放操作中数据被放置到控件上时的逻辑。当用户将数据拖放到控件上,并且 can_drop_data() 返回 true 时,_drop_data() 函数会被调用。
#at_position表示接收拖放的坐标数据,dragSloteNode表示从哪个节点拖放过来
func _drop_data(at_position, dragSloteNode):
var targetSlotNode = get_slot_node_at_position(at_position) #获取接收拖放的节点
targetSlotNode.PutIntoSlot(dragSloteNode)
这样我们就实现物品拖拽功能,下节见。