Escape room problem -- cannot use items/apply them on objects in the scenery

Godot Version

4.3

Problem(s)

Hello! I’m trying to code a simple escape room, I’m entirely new to Godot. I’m in that beginner phase where you simply follow tutorials along, and I figured watching one for escape rooms/point and click would be a good way to be introduced to the genre and eventually deal with it myself.
The only tutorial I found was Robin Lamb’s and the problem began when I finished the second video. It’s dedicated to drag-and-drop inventory features. The person doesn’t explain the code very well so I just copied it word by word and it’s… half-working.
The last part of the video is about using an item that you collected on something that is in the room in order to solve puzzles and that type of stuff. In the video it works fine, in my code it doesn’t at all. (I have a small suspicion the video skipped a few vital parts but I don’t want to accuse someone I don’t know of messing up…)
In my code I used a watering can as the item and a flower as the thing that needs to be interacted with. The flower is supposed to bloom when the watering can’s Area2D enters the flower’s Area2D and the item is released. It does nothing. If you look up the video, you’ll see that it seemingly works.

Here is the entire main script which is where this interaction is being handled. I annotated it a little and the flower interaction is at the very bottom.

extends Node2D

var hand_cursor = preload("res://question.png")
var detail_selected = false
var slot1_filled = false
var slot2_filled = false
var slot3_filled = false
var wateringcan_used = false

#Cursor things
func change_cursor_hand():
	if !detail_selected:
		Input.set_custom_mouse_cursor(hand_cursor)

func change_cursor_default():
	if !detail_selected:
		Input.set_custom_mouse_cursor(null)

func change_cursor_hand_detail():
	Input.set_custom_mouse_cursor(hand_cursor)

func change_cursor_default_detail():
	Input.set_custom_mouse_cursor(null)


# Inventory things
func fill_slot(slot):
	match slot:
		1:	slot1_filled = true
		2:	slot2_filled = true
		3:	slot3_filled = true

func empty_slot(slot):
	match slot:
		1:	slot1_filled = false
		2:	slot2_filled = false
		3:	slot3_filled = false

func choose_slot(item):
	var chosen_slot = 1
	if !slot1_filled:
		chosen_slot = $inventory/Container/slot1.global_position
		slot1_filled = true
		item.drop_location_id = 1
	elif !slot2_filled:
		chosen_slot = $inventory/Container/slot2.global_position
		slot1_filled = true
		item.drop_location_id = 2
	elif !slot3_filled:
		chosen_slot = $inventory/Container/slot3.global_position
		slot1_filled = true
		item.drop_location_id = 3
	return chosen_slot

func set_drop_location(item):
	var drop_location
	match item.drop_location_id:
		0: drop_location = item.global_position
		1: drop_location = $inventory/Container/slot1.global_position
		2: drop_location = $inventory/Container/slot2.global_position
		3: drop_location = $inventory/Container/slot3.global_position
	return drop_location

func _on_slot_1_area_area_entered(area: Area2D) -> void:
	if area.is_in_group("item") and !slot1_filled:
		empty_slot(area.get_parent().drop_location_id)
		area.get_parent().drop_location_id = 1
		fill_slot(area.get_parent().drop_location_id)
func _on_slot_2_area_area_entered(area: Area2D) -> void:
	if area.is_in_group("item") and !slot2_filled:
		empty_slot(area.get_parent().drop_location_id)
		area.get_parent().drop_location_id = 2
		fill_slot(area.get_parent().drop_location_id)
func _on_slot_3_area_area_entered(area: Area2D) -> void:
	if area.is_in_group("item") and !slot3_filled:
		empty_slot(area.get_parent().drop_location_id)
		area.get_parent().drop_location_id = 3
		fill_slot(area.get_parent().drop_location_id)

#Item interactions by clicking (not the problem, I think)
func _on_door_area_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if !detail_selected and event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
		$door_closed.visible = false
		$door_open.visible = true


func _on_door_area_2_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if !detail_selected and event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
		$door_closed.visible = true
		$door_open.visible = false


func _on_chicken_area_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if !detail_selected and event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
		$dialogue_box.visible = true
		detail_selected = true
		change_cursor_hand_detail()

func _on_area_2d_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
		$dialogue_box.visible = false
		detail_selected = false
		change_cursor_default_detail()




#The watering can thing that isnt working
func _on_area_2d_area_entered(area):
	if area.is_in_group("item"):
		if area.get_parent().item_id == 1:
			$flower.visible = false
			$flowerBloom.visible = true
			wateringcan_used = true
			empty_slot(area.get_parent().drop_location_id)
			area.get_parent().queue_free()
			Input.set_custom_mouse_cursor(hand_cursor)

And here is the object script, attached to the watering can.

extends Sprite2D

var dragging = false
var drag_cursor = preload("res://Catpaw holding Mouse icon.png")
var hand_cursor = preload("res://question.png")
var picked_up = false
var drop_location_id = 0
var drop_location
var dropped = false
var timer_off = true
@export var item_id = 1

func _physics_process(delta: float) -> void:
	if dragging:
		global_position = lerp(global_position, get_global_mouse_position(), 30 * delta)
		dropped = false
		Input.set_custom_mouse_cursor(drag_cursor)
	else:
		if picked_up:
			if !dropped:
				drop_location = get_parent().set_drop_location(self)
				if timer_off:
					$Timer.start()
					timer_off = false
			global_position = lerp(global_position, drop_location, 20 * delta)

func _on_area_2d_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
		if !picked_up and !dragging:
			global_position = get_parent().choose_slot(self)
			z_index = 10
			picked_up = true
		else:
			if event.pressed:
				dragging = true
			else:
				dragging = false
				Input.set_custom_mouse_cursor(hand_cursor)

func _on_timer_timeout():
	dropped = true
	timer_off = true

There are also some other smaller things that don’t work but this is the main problem so far since puzzle solving is a key part of escape rooms. Also, I wasn’t sure if this should be placed under Physics since I’m dealing with areas and not bodies.
Both the watering can and the flower have the same structure. They are both Sprite2Ds, with an Area2D and a rectangle CollisionShape2D inside them. The watering can has a Timer which should cause the item to drop…? The person doesn’t explain it very well… Only the root node and the watering can have scripts of their own.
Note: the “wateringcan_used” variable is my own version of a “card_used” var the video uses, since their object is a card. The person doesn’t explain the variable at all. I simply included it to make the code identical.
Any more information will be happily provided. Any help appreciated. I also have a feeling this entire code probably has a much easier way to be made, and advice on that would be appreciated as well.
Have a good day =)

EDIT: Solution

The problem was because of the groups system – I placed the Sprite2D node in the “item” group instead of Area2D, so it wasn’t recognizing the area as an item. Make sure to put the Area in the group and not the Sprite.
Cya!

I can barely read my own code, much less someone else’s, but mainly I use the print statement to find out if things are working. Instead of trying to run an animation, print when the two collide or not. It works for me. Eventually I figure out what I did wrong.

1 Like

That method did indeed work!! Thanks =) I’ll edit the original post to include a solution in case anyone else has this exact problem.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.