+2 votes

I'm trying to implement interactions between tiles but I'm not quite sure how to handle the data.

Every tile have very specific interactions with other tiles that no other tile shares.

Right now I have a resource shared among all the tiles with the basic information every tile needs. I load all the resources into an Array and every resource index matches their tile_id.

And now I'm thinking how to add these very specific behaviours and conditions for every tile.

Should I add a variable for every resource in which I add a script with that tile's specific behaviour? Is there a problem having multiple small scripts loaded all at once? Should these scripts be resources too because they are reference-counted?

Edit: The game is turn based so this conditions only need to be tested once per turn.

If anyone knows of a better way of handling the data for the tiles please let me know.

Godot version 3.2.3
in Engine by (388 points)
edited by

This seems like a problem that would end up like yandere dev's code if not dealt properly, if i were to do something like this i'd use a switch statement but gdscript doesnt have that and using multiple if else statements would really affect performance So i dont really have an answer

Godot has the switch statement, it's called a match if I remember correctly. What is that yandere?

Just as estebanmoica said Godot has match and I use it sometimes for example to check the type of tile and other things the godot documentation says its even has extra functionality over switches match doc:

match card_type:

    TYPE.PATH:
        path_tiles.append(mouse_tile)
        continue

    TYPE.ACTIVATION:
        is_spell = true
        removed_tile_id = map.get_cellv(mouse_tile)

        if path_tiles.has(mouse_tile):
            map.set_cellv(mouse_tile,0)
        else:
            map.set_cellv(mouse_tile,-1)

        for dir in DIRECTIONS:
            var neighbor_id = map.get_cellv(mouse_tile+dir)

            if DB_tiles[neighbor_id] == null:
                continue

            elif neighbor_id != DBase.TILES.PATH && DB_tiles[neighbor_id].adjacent_effect:
                adjacent_tile_effect("Remove",removed_tile_id,neighbor_id)

    _:
        if !is_spell:
            map.set_cellv(mouse_tile,card_tile_id)

Thanks for the link it has a lot of concepts I didn't know about

3 Answers

0 votes
Best answer

I think I got it. What I'm going to do is to have every behaviour be its own script and load them in the Tiles base resource that use them. Then I would have an array of strings with the name of every script and this name would be the same as the name of its function. Every time I put a tile or remove it I would call for the check_behaviours function of every tile that may be affected

extends Resource
class_name Tiles

export (Array,Resource) var Behaviours
var function_names :PoolStringArray = ["foo1","foo2", ...]

func load_behaviour_scripts():
  for x in Behaviours.size():
    var script = Behaviour[x]
    Behaviour[x] = [script,script.new()]  #or use another array to save the loaded scripts

func check_behaviours([param]:Array):
   for x in Behaviours.size():
     var script = Behaviour[x][0]
     var usable_script = Behaviour[x][1]
     for function in  function_names:
       if script == load("path_to_behaviours_folder/"+ function+".gd"):
         usable_script .call(function,[param])

Once I'm done implementing it I'll update the post

by (388 points)
selected by
0 votes

Will this interactions be processed all at once, like in ready() or process(), or will it be like the turn game where You could check these interactions for one tile at a time ? Please tell us something more about Your project, maybe we could figure something out.

by (1,110 points)

You are right, the checks wouldn't be every tick and would only happen once the player uses the tiles that are like resources so you can't spam them freely. Its more of a turn based thing the tiles don't do anything until the next turn others require more turns.

0 votes

I still can't really imagine complexity of these tile bahaviors, but I feel that creating separate script for all of them would be overdoing it. They are tiles in the end, they can't really have complicated bahaviours, I suspect they will be all about influencing some calculations .
Since it is a turn game, can't You implement a scripted Node under actor object, that would be responsible for getting surrounding tiles and calculating their interactions after every move ? Also instead of large if/match statement code You maybe would be able to handle all interactions in this one script via JSON sheet ?

by (1,110 points)

its not complicated is just a lot of if statements.

is this tile under this other specific tile? is the specific tile 3 tiles away? is this tile surrounded? is this tile surrounded by 2 rings of tiles? do something specific depending on the tiles surrounding if they are different between then do another thing, etc.

I haven't designed all the tiles and their behaviours but I want to have a system that allows for as much freedom as possible when it comes to add new behaviours to tiles.

With the separated scripts I would only call the functions that the tile resource has and that function would check only the requirements for that specific behaviour. So every tile would only need to check one or two if statements per behaviour and skip all the others.

How would that pipeline look with the json? Won't you have to check for every behaviour condition even if the tile only have 1 behaviour or do you mean every tile would have its own json? I think you can do if statements in xml but json doesn't have that what would the json file be?

I see, loop hero stuff :)

Yeah, this kind of elastic interactions are not suited for JSON, i was thinking of table json sheet where tiles would be on x and y of a table and cells would contain keywords for calling interaction functions, but that would only work for simple tile vs 1 neighbour bahaviour.

So You are right, multiple scripts seem like only option. You will just put repetitive checks in their parent class.

Yes I started this project as a loop hero clone because it seemed like a really simple game I could imitate for practice but now the project is growing in complexity even changing core mechanics but I liked the idea of using tiles as resources. If I was to copy everything in loop hero even if is not a good habit I could just hardcode the tiles there's not that many interactions.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.