【Godot4自学手册】第四十二节实现拖拽进行物品交换和数量叠加

这一节我们主要学习背包系统中的物品拖拽后,物品放到新的位置,或交换物品位置,如果两个物品属于同一物品则数量相加。具体效果如下:
请添加图片描述

一、修改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)

这样我们就实现物品拖拽功能,下节见。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Godot实现Socket通信可以通过使用Godot的内置NetworkedMultiplayerENet类来实现。ENet是一个可靠的UDP网络库,适用于实现实时多人游戏中的网络通信。 以下是一个简单的示例代码,演示如何在Godot中创建一个基本的Socket连接: ```gdscript extends Node var server := NetworkedMultiplayerENet.new() var client := NetworkedMultiplayerENet.new() func _ready(): # 初始化服务器 server.create_server(1234) server.set_bind_ip("*") # "*" 表示监听所有IP地址 # 初始化客户端 client.create_client("127.0.0.1", 1234) # 连接到服务器的IP和端口 # 将服务器和客户端分别添加到场景树中 add_child(server) add_child(client) # 注册对应的信号 server.connect("network_peer_connected", self, "_on_network_peer_connected") server.connect("network_peer_disconnected", self, "_on_network_peer_disconnected") client.connect("connected_to_server", self, "_on_connected_to_server") client.connect("connection_failed", self, "_on_connection_failed") func _on_network_peer_connected(id): print("Peer connected: ", id) func _on_network_peer_disconnected(id): print("Peer disconnected: ", id) func _on_connected_to_server(): print("Connected to server") func _on_connection_failed(): print("Connection failed") ``` 在这个示例中,我们创建了一个服务器和一个客户端,并分别将它们添加到场景树中。服务器使用指定的端口创建一个服务器,在任何可用IP地址上监听连接。客户端则使用指定的IP地址和端口连接到服务器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游戏自学

生活不易,打赏随意

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值