背包系统(二)
在编写代码之前,先来熟悉熟悉几个Control节点的一下方法和属性。
void _gui_input ( InputEvent event ) virtual
由用户实现的虚拟方法。使用该方法来处理和接受UI元素的输入。参见 accept_event。
示例:单击一个控件。
func _gui_input(event):
if event is InputEventMouseButton:
if event.button_index == BUTTON_LEFT and event.pressed:
print("I've been clicked D:")
在以下情况下,该事件不会触发。
在控件外点击(见has_point);
控件的mouse_filter设置为MOUSE_FILTER_IGNORE。
控件被它上面的另一个控件挡住了,而这个控件并没有将 mouse_filter 设置为 MOUSE_FILTER_IGNORE。
控件的父控件有mouse_filter设置为MOUSE_FILTER_STOP或者已经接受了该事件。
该事件发生在父节点的矩形之外,并且父节点启用了 rect_clip_content 或 _clips_input。
MouseFilter mouse_filter
控制控件是否能够通过_gui_input接收鼠标按钮输入事件,以及如何处理这些事件。还控制控件是否可以接收鼠标输入和退出的信号。参见常量来了解每个常量的作用。
MouseFilter::
- MOUSE_FILTER_STOP = 0 — 控件如果被点击,将通过_gui_input接收鼠标按钮输入事件。而该控件将接收到鼠标输入和鼠标退出的信号。这些事件会被自动标记为处理,它们不会进一步传播到其他控件中。这也就造成了其他控件中信号的阻塞。
- MOUSE_FILTER_PASS = 1 — 控件如果被点击,将通过_gui_input接收鼠标按钮输入事件。而该控件将接收到mouse_entered和mouse_exited信号。如果这个控件没有处理该事件,则会考虑父控件(如果有的话),以此类推,直到没有更多的父控件可能处理该事件。这也允许在其他控件中发射信号。即使根本没有控件处理,事件也会被自动处理,所以未处理的输入不会被发射。
- MOUSE_FILTER_IGNORE = 2 — 控件将不会通过_gui_input接收鼠标按钮输入事件。 该控件也不会接收mouse_entered或mouse_exited信号。 这不会阻止其他控件接收这些事件或触发信号。 忽略的事件将不会自动处理。
CursorShape mouse_default_cursor_shape
该控件的默认光标形状。对于Godot插件和使用系统鼠标光标的应用程序或游戏非常有用。
注意:在Linux系统中,根据系统的光标主题,形状可能会有所不同。
CursorShape:
CURSOR_ARROW = 0 — 当用户悬停节点时,显示系统的箭头鼠标光标。 与mouse_default_cursor_shape一起使用。
CURSOR_IBEAM = 1 — 当用户悬停节点时,显示系统的I-beam鼠标光标。I-beam指针的形状类似于“I”。它告诉用户可以高亮显示或插入文本。
CURSOR_POINTING_HAND = 2 — 当用户悬停节点时,显示系统的手形鼠标光标。
CURSOR_CROSS = 3 — 当用户将节点悬停时,显示系统的鼠标十字光标。
CURSOR_WAIT = 4 — 当用户悬停节点时,显示系统的等待鼠标光标,通常是一个沙漏。
CURSOR_BUSY = 5 — 当用户悬停节点时,显示系统繁忙的鼠标光标。通常是一个沙漏。
CURSOR_DRAG = 6 — 当用户悬停在节点上时,显示系统的拖动鼠标光标,通常是一个闭合的拳头或十字符号。它告诉用户他们当前正在拖动一个项目,就像场景dock中的节点一样。
CURSOR_CAN_DROP = 7 — 当用户悬停节点时,显示系统的放下鼠标光标。它可以是一个张开的手。它告诉用户可以放下一个他们当前正在抓取的物品,比如场景dock中的一个节点。
CURSOR_FORBIDDEN = 8 — 当用户悬停节点时,显示系统禁止的鼠标光标。通常是一个交叉的圆圈。
CURSOR_VSIZE = 9 — 当用户悬停节点时,显示系统的垂直调整鼠标光标。一个双头的垂直箭头。它告诉用户可以垂直调整窗口或面板的大小。
CURSOR_HSIZE = 10 — 当用户悬停节点时,显示系统的水平调整鼠标光标。一个双头的水平箭头。它告诉用户可以水平调整窗口或面板的大小。
CURSOR_BDIAGSIZE = 11 — 当用户悬停节点时,显示系统的窗口调整鼠标光标。光标是一个从左下角到右上角的双头箭头,它告诉用户可以在水平和垂直方向上调整窗口或面板的大小。它告诉用户可以在水平和垂直方向上调整窗口或面板的大小。
CURSOR_FDIAGSIZE = 12 — 当用户悬停节点时,显示系统窗口调整鼠标光标的大小。光标是一个从左上角到右下角的双头箭头,与CURSOR_BDIAGSIZE相反。它告诉用户可以在水平和垂直方向上调整窗口或面板的大小。
CURSOR_MOVE = 13 — 当用户悬停节点时,显示系统的移动鼠标光标。它显示2个90度角的双头箭头。它告诉用户他们可以自由移动UI元素。
CURSOR_VSPLIT = 14 — 当用户悬停节点时,显示系统的垂直分割鼠标光标。在Windows上,它和CURSOR_VSIZE一样。
CURSOR_HSPLIT = 15 — 当用户悬停节点时,显示系统的水平分割鼠标光标。在Windows上,它和CURSOR_HSIZE一样。
CURSOR_HELP = 16 — 当用户悬停节点时,显示系统的帮助鼠标光标,一个问号。
思路
制作格子
首先制作存放物品的格子,新建一个场景,添加一个panel节点。
设置最小大小为:
这时根据自己的素材图标大小来设定。
这是我设置好的,你可以自己更改样式。
以上所有过程,其实可以用代码完成。就是新建个脚本,然后继承Panel.在代码设置属性。但为了可观我用所见即所得的方式。
制作物品
物品其实就是个textureRect节点。这个节点可以设置纹理,这样可以显示物品出来。
新建一个场景,然后添加textureRect,设置最小大小为34x34。并命名为Item。
它看起来空白,因为什么纹理还没添加。
为Item添加代码
extends TextureRect
class_name Item
var is_pickup:bool
func _init(_item_icon):
texture=_item_icon
mouse_filter=Control.MOUSE_FILTER_PASS
mouse_default_cursor_shape=Control.CURSOR_POINTING_HAND
# Called when the node enters the scene tree for the first time.
extends TextureRect
#命名为Item类
class_name Item
#判断物品是否是拿起了
var is_pickup:bool
#使用new创建实例使初始化对象。
func _init(_item_icon):
texture=_item_icon
mouse_filter=Control.MOUSE_FILTER_PASS
mouse_default_cursor_shape=Control.CURSOR_POINTING_HAND
#设置鼠标过滤和是否为拿起状态
func up():
mouse_filter=Control.MOUSE_FILTER_IGNORE
is_pickup=true
#设置鼠标过滤和是否为拿起状态,还有就是当物品放入格子时,应重新调整位置,
#不然物品的位置就会设置为从viewport放入格子前的全局鼠标位置
func down():
rect_position=Vector2.ZERO
mouse_filter=Control.MOUSE_FILTER_PASS
is_pickup=false
这里有一点和重要,回到上面讲得方法和属性。_gui_input(),提到控件被它上面的另一个控件挡住了,而这个控件并没有将 mouse_filter 设置为 MOUSE_FILTER_IGNORE,事件不会触发。也就是当你拿起物品时,你的物品跟随你的鼠标,如果物品mouse_filter 没有设置为 MOUSE_FILTER_IGNORE时,你无法触发格子的_gui_input事件,也就无法放入物品。
所以放我拿起物品时,物品应该不接受鼠标点击事件,也就是控件将不会通过_gui_input接收鼠标按钮输入事件。 该控件也不会接收mouse_entered或mouse_exited信号。 但这不会阻止其他控件接收这些事件或触发信号。 忽略的事件将不会自动处理。
这样我就可以点击格子,来触发格子的_gui_input函数了。
为ItemSlot添加代码
extends Panel
class_name ItemSlot
var slot_index:int
#item属性存储着对Item类的实例的引用
var item
func _ready():
mouse_filter=Control.MOUSE_FILTER_PASS
#添加物品:把物品作为子节点加入
func set_item(_item):
add_child(_item)
item=_item
#拿起物品:移除物品并添加到根视口作为其子节点,把这个格子的item属性设置为空
func pick_item():
#物品拿起时,设置mouse_filter为忽略,这样才能穿过物品点击到格子,然后让格子处理鼠标事件回调。
item.up()
remove_child(item)
get_node("/root").add_child(item)
item=null
#放入物品:把拿起的物品放进格子,成为其子节点,并在根视口移除物品,这时item属性为这个物品
func put_item(_item):
item=_item
#物品放入格子后设置mouse_filter为传递,只有这样当我放下物品我才能点击到格子,然后让格子处理鼠标事件回调。
item.down()
get_node("/root").remove_child(item)
add_child(item)
#移除物品,并删除
func remove_item():
remove_child(item)
item=null