On object change, alter it's closest/linked text object

I have a City object, and each one has a text object below with the City Name.
I’ve got ~20 of these pairs on the map in my game.

When the City is ‘captured’, (a variable is changed) I’d like to change the City Name text object colour, but I can’t figure out how to ‘target’ the nearby text object to change it.
I’ve looked into linking objects, but the neither the City objects or City Name text objects are unique, so it affects all of them in the scene.
I also considered the following:

  • Collisions, but text objects don’t have collision masks!
  • Pick the Nearest Object - in order to ‘capture’ a city, a player unit has to be in contact with the city collision mask (about 10 pixels out) and for design reasons, the text object is about 20-30 pixels away from the city object depending on the zoom level

Is it possible to somehow target the closest text object? Or is there an expression that I can use in the Link Two Objects action that I’ve not found?

Ok, so it turns out that text objects do have collision boxes after all… :laughing:

That solves the main problem, but then creates a new problem with the text objects being too close to/overlapping the city object icon, and I can’t expand the collision box because that’d mess with my city capture mechanic.

I’ll have another play around - perhaps I could make use of multiple collision boxes? I read somewhere that you can create then specify collision boxes in events - is that correct?

That doesn’t matter for linking, but linking would normally be done in events, so you would have a loop in which you create the city object, then create the name text object, then link them. Then create the next city, next text object and so on. That way GDevelop always knows which city instance goes with which text object instance.

If you are manually creating and placing cities and names then GDevelop won’t know which to link, so the standard solution here would be to use object variables to link them with a unique ID number i.e. manually give both the city object and the name text object the same value for an object variable called ID.

Then you can use a condition something like

city.Variable(captured)=1 city.Variable(ID) = name.Variable(ID) Trigger once
with the action to change the colour of name. This should mean GDevelop knows which instance of name to change the colour of.

You know what, it hadn’t even crossed my mind to create the cities + names programmatically. However, I don’t like the idea of having a global variable structure with ~40 child structures each containing X + Y coordinates, names, and the 11 variables associated with each city.

It’s times like these where I’d love to just use a SQLite DB and handle it there in a calm and collected fashion, but that’s not possible or practical in this ecosystem, AFAIK (right?). I saw the docs about using JSON, but I’m planning an Android app so can’t use it.

I’ll give this a whirl and let you know how it goes :smiley:

Maybe you don’t need to create the cities programmatically but the text objects only.
If the cities on the map are single objects only, It can be an instance of the same object displaying a different animation.
Then, using the for each event you can loop through all the city instances , create the text for each, link the text to each and update the text.

For each city: -create text in position city.X(), city.Y() + 20 or something -link text to city -do = city.VariableString(name) to text of text

After, to change text color of captured cities just do:

For each city: -if city.Variable(captured) = 1 then take in to account text linked to city and change colour of text.

[quote=“ddabrahim”]

For each city: -create text in position city.X(), city.Y() + 20 or something -link text to city -do = city.VariableString(name) to text of text

So I implemented your idea, but I don’t think I’m using the Linked Objects actions properly:

The Wiki documentation on linking objects is pretty minimal, so I’ll take what I learn here and see if I can improve the Wiki page for it

EDIT: In case it wasn’t clear, the text object isn’t being displayed with that event

For one thing, you are using the Always and At he beginning condition in the same event. I don’t know what effect it has as I never tried it but it is two opposite condition. Always means, run it every frame, At the beginning means, run it only the first frame. Both can’t be true. It might be the problem.

Also you don’t need to take in to account the text object right after you have linked the text. At that point, you should be able to set the name without taking in to account.

Next, make sure you spelling the object names right.

Finally, to change the colour of the text should be checked every time the owner of the city can change. If the owner can change anytime during the game then you must check the owner every frame for each city but ideally whenever the owner change, you need to perform this check.
So it needs to be a separated event and this is where you need to take in to account the text as I have explained before.

EVENT1:

At the beginning: For each city: -create text in position city.X(), city.Y() + 20 or something -link text to city -do = city.VariableString(name) to text of text

EVENT2:

For each city: -if city.Variable(captured) = 1 then take in to account all text linked to city and then change colour of text.

I made it yesterday but I forgot to share it :unamused: , here are some examples to “link” an object and a text label through simple conditions, and an example for the link extension:
LinkedObjects.zip (14.5 KB)

Thank you all for your help!

So in the end, I experimented with the different solutions and decided to use @Lizard-13’s solution with the linking of the City object and cityMapLabel text object using the City Name as the unique identifier (it’ll make adding new cities easier, as using a a unique number ID would’ve definitely resulted in me losing track and duplicating IDs down the line).

Here’s what it looks like in Events:

and here’s how it looks in my in-game WIP:

Thanks again guys!