使用物品

  • 添加拾取物品代码 inventory_data

  • 创建新的pickup文件夹,创建item_pickup场景和脚本

    • 需要包含Area2D,用来检测碰撞
      • 这下面要有CollisionShape2D
    • 需要添加sprite2D和audiooStreamPlayer2D用来展示图片和音频
  • item_pickup.gd

    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
    @tool
    class_name ItemPickup extends Node2D

    @onready var area_2d: Area2D = $Area2D
    @onready var sprite_2d: Sprite2D = $Sprite2D
    @onready var audio_stream_player_2d: AudioStreamPlayer2D = $AudioStreamPlayer2D

    @export var item_data: ItemData : set = _set_item_data

    func _ready() -> void:
    _update_texture()
    if Engine.is_editor_hint():
    return
    area_2d.body_entered.connect(_on_body_entered)
    pass

    func _on_body_entered(b) -> void:
    if b is Player:
    if item_data:
    if PlayerManager.INVENTORY_DATA.add_item(item_data) == true:
    item_picked_up()
    pass

    func item_picked_up() -> void:
    area_2d.body_entered.disconnect(_on_body_entered)
    audio_stream_player_2d.play()
    visible = false
    await audio_stream_player_2d.finished
    queue_free()
    pass

    func _set_item_data(value: ItemData) -> void:
    item_data = value
    _update_texture()
    pass

    func _update_texture() -> void:
    if sprite_2d and item_data:
    sprite_2d.texture = item_data.texture
    pass
    • 如果玩家碰撞则触发拾取操作
  • item_data.gd

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class_name ItemData extends Resource

    @export var name: String = ""
    @export_multiline var description: String = ""
    @export var texture: Texture2D

    @export_category("Item Use Effects")
    @export var effects: Array[ItemEffect]

    func use() -> bool:
    if effects.size() == 0:
    return false
    for e in effects:
    if e:
    e. use()
    return true
    • item_data是物品最基本的信息,包含多个效果
  • inventory_data.gd

    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
    class_name InventoryData extends Resource

    @export var slots: Array[SlotData]

    func _init() -> void:
    pass

    func add_item(item: ItemData, count: int = 1) -> bool:
    for s in slots:
    if s:
    if s.item_data == item:
    s.quantity += count
    return true
    for i in slots.size():
    if slots[i] == null:
    var new_slot = SlotData.new()
    new_slot.item_data = item
    new_slot.quantity = count
    slots[i] = new_slot
    new_slot.changed.connect(slot_changed)
    return true
    print("inventory is full!")
    return false

    func connect_slot() -> void:
    for s in slots:
    if s:
    s.changed.connect(slot_changed)

    func slot_changed() -> void:
    for s in slots:
    if s:
    if s.quantity < 1:
    s.changed.disconnect(slot_changed)
    var index = slots.find(s)
    slots[index] = null
    emit_changed()
    pass
    • inventory_data是库存,里面有多个slot_data,用来保存数据
  • inventory_slot.gd

    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
    class_name InventorySlot extends Button

    @onready var texture_rect: TextureRect = $TextureRect
    @onready var label: Label = $Label

    var slot_data: SlotData: set = set_slot_data

    # Called when the node enters the scene tree for the first time.
    func _ready() -> void:
    texture_rect.texture = null
    label.text = ""
    focus_entered.connect(item_focused)
    focus_exited.connect(item_unfocused)
    pressed.connect(item_pressed)
    pass # Replace with function body.

    func set_slot_data(value: SlotData) -> void:
    slot_data = value
    if slot_data == null:
    return
    texture_rect.texture = slot_data.item_data.texture
    label.text = str(slot_data.quantity)
    pass

    func item_focused() -> void:
    if slot_data != null:
    if slot_data.item_data.description != null:
    PauseMenu.update_item_description(slot_data.item_data.description)
    pass

    func item_unfocused() -> void:
    PauseMenu.update_item_description("")
    pass

    func item_pressed() -> void:
    if slot_data:
    if slot_data.item_data:
    var used = slot_data.item_data.use()
    if used == false:
    return
    slot_data.quantity -= 1
    label.text = str(slot_data.quantity)
    • inventory_slot用来展示

    Resource

    • Resource创建出的tres资源,在多个节点共享时修改互相影响
    • 也可以用preload来加载tres资源,同样与拖拽的共享