Certain lines of code doesn't seem to trigger for some reason

Godot Version

4.4.1.stable

Question

I did some re-designing of my current game, in order to simplify things. Made some progress, but I hit another roadblock. I don’t see the button move on the world map, despite having code lines making a tween. Additionally, the “if” statement under the _on_timer_timeout()" method doesn’t seem to trigger. I do sometimes see the cargo amount be subtracted in the output, but not always. I suppose it is possible I am not seeing the button moving on screen because of the possibility the “create_airship_icon” is not being triggered because of this. I have the “World_Map” image in z-index 0, with the “TileMapLayer” z-index as 1. Below is a screenshot of my node tree, as well as my code, any feedback that would help solve this would be greatly appreciated:

Code for World_Map node:

extends Node2D

var balance: int

#Dictionary that stores city name and its tile coordinates
#City name as key, then city location, then population, then cargo to be delivered, then airship count
var cities = {
	"Los Angeles": [Vector2(78, 165), 1000000, 1000000, 1],
	"San Fransisco": [Vector2(73, 161), 1000000, 0, 0],
	"San Diego": [Vector2(80, 166), 1000000, 0, 0],
	"Chicago": [Vector2(123, 152), 1000000, 0, 0],
	"Houston": [Vector2(113, 169), 1000000, 0, 0],
	"San Antonio": [Vector2(108, 170), 1000000, 0, 0],
	"Dallas": [Vector2(110, 166), 1000000, 0, 0],
	"New York": [Vector2(142, 156), 1000000, 0, 0],
	"Seattle": [Vector2(73, 143), 1000000, 0, 0],
	"Vancouver": [Vector2(71, 139), 1000000, 0, 0],
	"Anchorage": [Vector2(31, 113), 1000000, 0, 0]
}

var active_cities = [
	"Los Angeles",
	"San Fransisco",
	"San Diego"
]

Code for TileMapLayer node:

extends TileMapLayer

const CITY = preload("res://sprites/city.png")

@onready var world_map: Node2D = $".."
@onready var canvas_layer: CanvasLayer = $"../Camera2D/CanvasLayer"
@onready var window: Window = $"../Window"
@onready var window_2: Window = $"../Window2"
@onready var camera_2d: Camera2D = $"../Camera2D"
@onready var balance_label: Label = $"../Camera2D/CanvasLayer/HBoxContainer/VBoxContainer/Balance"
@onready var calendar: Label = $"../Camera2D/CanvasLayer/HBoxContainer/VBoxContainer/Calendar"

var button_status: bool = false
var travel_time_multiplier: int = 3
var timer_counter: int = 1
var year: int = 2025

# Called when the node enters the scene tree for the first time.
func _ready():
	calendar.text = str("Week " + str(timer_counter) + ", " + str(year))
	camera_2d.global_position = map_to_local(Vector2(78, 165))
	balance_label.text = "$ " + str(world_map.balance)
	populate_cities()

func populate_cities():
	for key in world_map.cities:
		var btn = Button.new()
		btn.icon = CITY
		btn.text = str(key)
		btn.flat = true
		btn.alignment = HORIZONTAL_ALIGNMENT_LEFT
		btn.position = map_to_local(world_map.cities[key][0])
		btn.pressed.connect(self.purchase_city_access.bind(btn.text))
		add_child(btn)
		#Makes the button transparent if it is not an accessible city
		if world_map.active_cities.has(key) == false:
			btn.modulate.a = 0.5

#Purpose of this method is to allow the purchase of access to selected city
func purchase_city_access(city_name: String):
	if world_map.active_cities.has(city_name) == false:
		window.show()
		_on_yes_pressed.bind(city_name)

#Used to purchase access to a city
func _on_yes_pressed(city_name: String):
	world_map.active_cities[city_name] = 0
	populate_cities()
	window.hide()

func _on_no_pressed():
	window.hide()

func _on_button_pressed():
	window_2.hide()

func create_airship_icon(cargo_amount: int, city_origin: String):
	var airship = Button.new()
	#Spawns new airship button in World Map
	airship.icon = load("res://sprites/Airship_icon.png")
	airship.position = world_map.cities[city_origin][0]
	self.add_child(airship)
	
	var origin_vector = world_map.cities[city_origin][0]
	var destination = world_map.active_cities.pick_random()
	var destination_vector = world_map.cities[destination][0]
	var distance = origin_vector.distance_to(destination_vector)
	
	#Moves the spawned airship button from the origin to the destination cities
	var tween = airship.create_tween()
	tween.tween_property(airship, "position", destination_vector, distance * travel_time_multiplier).from_current()
	tween.tween_callback(airship.queue_free)
	world_map.cities[destination][2] = world_map.cities[destination][2] + cargo_amount

func _on_timer_timeout():
	for key in world_map.cities:
		#Population growth
		world_map.cities[key][1] = world_map.cities[key][1] + 10000
		#Cargo growth
		world_map.cities[key][2] = world_map.cities[key][2] + 10000
		print(str(key) + ": " + str(world_map.cities[key][1]) + ": "  + str(world_map.cities[key][2]))
		
		if world_map.cities[key][2] > 1000000 and world_map.cities[key][3] > 0:
			var city_origin = key
			var cargo_amount = randi_range(5, 10) * 100000
			world_map.cities[key][2] = world_map.cities[key][2] - cargo_amount
			world_map.cities[key][3] = world_map.cities[key][3] - 1
			create_airship_icon.bind(cargo_amount, city_origin)
			create_airship_icon(cargo_amount, city_origin)
			print("cargo loaded")
	
	timer_counter += 1
	calendar.text = str("Week " + str(timer_counter) + ", " + str(year))

you should probably check the signals of the bottom and if it is connected to the function

and do you have a git for the origin code ?

Despite the code I have for camera movement, the code posted here is all the code I have. In the func _on_timer_timeout(), the city_origin variable is defined by var city_origin = key

what dose the print statement on line 81 print when ran ?
and how long is the timer for the timer node?

This is an example of what I have in my dictionary. Line 81 prints the key (which is the city name), then population, then cargo accumulated in the city. I added this line to debug my code, cause I wanted to make sure the population and cargo amount were growing as expected.

Timer’s wait time is 5 sec.

ok i think i no what is going on

change line 80 so it is like the following

world_map.cities[key][2] = world_map.cities[key][2] + 10000000

next change line 83 to the following

if world_map.cities[key][2] >= 1000000 and world_map.cities[key][3] >= 0:

this should solve one of the problems from the original post

Thank you. Changing the assignment operators like you suggested for line 83 worked. The cargo amount in the city does reduce as intended. I did not make the suggested change on line 80, because that would make the “cargo” amount grow too fast.

In an effort to debug the tween issue, I added a print(“tween”) before line 70, the
var tween = airship.create_tween(), to see if the func create_airship_icon is being triggered. I do see “tween” in the output, so the method is being triggered as intended. However, I still do not see the button with airship icon appearing onscreen for some reason.

1 Like

unfortunately i can’t help with the tween debugging i have never used tween

but i can tall what direction you can go that may have right answer

make shore that you read the Tween documentation and understand what it does

and look at the function

This is a shot in the dark, but for your tweening issue try printing the current position and destination position as well as the distance * travel_time_multiplier duration. It’s possible something isn’t returning quite what you expect and you’re ending up with a duration of 0 or matching starting and target positions or something?

Understood, I did that just now and the tile coordinates it shows in the output are correct. Code is as follows:

	var tween = airship.create_tween()
	print(str(airship.position) + ": " + str(destination_vector) + ": " + str(distance * travel_time_multiplier))
	tween.tween_property(airship, "position", destination_vector, distance * travel_time_multiplier).from_current()
	tween.tween_callback(airship.queue_free)

Since the printed coordinates seem correct, I’m guessing there’s an issue with the tween code itself or something else entirely.

I just realized an alternative solution: instantiate a scene. I can have a PathFollow2D in a separate scene, and then instantiate that scene with the starting and destination Vector2 positions for the airship button. This is what I have so far:

In the TileMapLayer node: have the following code:

func create_airship_icon(cargo_amount: int, city_origin: String):
	var airship = Button.new()
	#Spawns new airship button in World Map
	airship.icon = load("res://sprites/Airship_icon.png")
	airship.position = world_map.cities[city_origin][0]
	self.add_child(airship)
	
	Globals.origin_vector = world_map.cities[city_origin][0]
	var destination = world_map.active_cities.pick_random()
	Globals.destination_vector = world_map.cities[destination][0]
	
	#Moves the spawned airship button from the origin to the destination cities
	world_map.deploy_airship()

	world_map.cities[destination][2] = world_map.cities[destination][2] + cargo_amount

In the World Map node, I added the following code:

func deploy_airship():
	var instance = AIRSHIP.instantiate()
	add_child(instance)

Wrote a Globals script with the following code:

extends Node2D

var origin_vector
var destination_vector

And for the Airship scene (which will be used to “spawn” new airships, I have the following so far:

extends Path2D

var speed: float = 1.0
@onready var path_follow_2d: PathFollow2D = $PathFollow2D

# Called when the node enters the scene tree for the first time.
func _ready():
	var points = [Globals.origin_vector, Globals.destination_vector]
	for point in points:
		curve.add_point(point)

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float):
	path_follow_2d.progress_ratio += delta * speed

Unfortunately, I get the following error:
image

What is causing this?

Unless airship.create_tween() creates a tween object that fires sequentially, you’re immediately killing your airship on the first frame.

I would recommend:

#Moves the spawned airship button from the origin to the destination cities
	var tween = airship.create_tween()
	tween.tween_property(airship, "position", destination_vector, distance * travel_time_multiplier).from_current()
	await tween.finished
	airship.queue_free()
	world_map.cities[destination][2] = world_map.cities[destination][2] + cargo_amount

Thank you! That did cause the button to spawn on screen, which is desired. Unfortunately, I noticed two things afterwards:

  1. The button would spawn in the wrong coordinates. I have local coordinates of the tilemaplayer stored in the dictionary of cities and the game seems to use those coordinates as global coordinates.
  2. The button doesn’t seem to move towards the destination city for some reason.

Below is my updated code (I also made some other changes, but it’s not relevant to this discussion):

func create_airship_icon(cargo_amount: int, city_origin: String):
	var airship = Button.new()
	#Spawns new airship button in World Map
	airship.icon = load("res://sprites/Airship_icon.png")
	airship.position = world_map.cities[city_origin][0]
	add_child(airship)
	
	var origin_vector = world_map.cities[city_origin][0]
	
	#This removes the origin city form the array of possible destinations, so the airship doesn't go to the city it originated from
	world_map.destination_cities = world_map.active_cities.duplicate(true)
	world_map.destination_cities.erase(city_origin)
	
	var destination = world_map.destination_cities.pick_random()
	var destination_vector = world_map.cities[destination][0]
	var distance = origin_vector.distance_to(destination_vector)
	
	#Moves the spawned airship button from the origin to the destination cities
	var tween = airship.create_tween()
	tween.tween_property(airship, "position", destination_vector, distance).from_current()
	await tween.finished
	airship.queue_free
	world_map.cities[destination][2] = world_map.cities[destination][2] + cargo_amount
1 Like

Glad that helped.

TBH local vs global coords are the current bane of my existence in one of my side-projects. So what you can try, is getting the global coords of the TileMapLayer and adding the stored global coords to that. Should work?

I think your problem is here:

tween.tween_property(airship, "position", destination_vector, distance).from_current()

I don’t think you’re using the from_current() function correctly, but I don’t think it’s needed. Try this:

tween.tween_property(airship, "position", destination_vector, airship.position)

Or…

tween.tween_property(airship, "position", destination_vector, 1).as_relative().from_current()

Either way you don’t need this line to calculate distance:

var distance = origin_vector.distance_to(destination_vector)

Did some more testing. As it turns out, the problem was just the coordinates. I had the coordinates for each city based on the tilemap, so I used “map_to_local” to fix it:

func create_airship_icon(cargo_amount: int, city_origin: String):
	var airship = Button.new()
	#Spawns new airship button in World Map
	airship.icon = load("res://sprites/Airship_icon.png")
	airship.position = Vector2(map_to_local(world_map.cities[city_origin][0]))
	add_child(airship)
	
	#This removes the origin city form the array of possible destinations, so the airship doesn't go to the city it originated from
	world_map.destination_cities = world_map.active_cities.duplicate(true)
	world_map.destination_cities.erase(city_origin)
	
	var destination = world_map.destination_cities.pick_random()
	var destination_vector = Vector2(map_to_local(world_map.cities[destination][0]))
	print("Destination Coordinates: " + str(destination_vector))
	#Moves the spawned airship button from the origin to the destination cities
	var tween = airship.create_tween()
	tween.tween_property(airship, "position", destination_vector, 1)
	await tween.finished
	airship.queue_free
	world_map.cities[destination][2] = world_map.cities[destination][2] + cargo_amount

That change alone fixed it. I may change the “1” entry in the tween_property since the airships are moving too fast to make sense in the game. It’ll probably be replaced by a formula that determines the airship’s “trip duration” based on their speed.

But thank you for your help! I can actually move forward with my game dev now, lmao.

2 Likes

Sorry, something else came up. Once the button reaches it’s destination, it would stay there instead of disappearing. This is despite the “airship.queue_free” code. Any ideas why?

You’re code is not calling airship.queue_free().

Instead, your code only gets a reference to airship.queue_free (which you could use for example with call_deferred()).

In short: add function call needs () after the function name:

	airship.queue_free()
2 Likes

Thank you, that worked!

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