|
|
|
 |
Reply From: |
Inces |
- You need to have a dictionary of tile position : tile content for every tile.
var tiledata = {Vector2(0,0) : -1, Vector2(0,1) : empty,............. }
- You need to code a method to recognize a tile during interaction
for example
targettile = startingtile + movement direction
or check surrounding tiles within a square.
- You need to check the contents of targettile in relation to content of startingtile and design IF statement for corrent interaction, for example :
if tiledata[startingtile] == 1 and tiledata[targettile] == 2 :
animation.play()
important thing is to design when grid is supposed to check for interaction. Obviously it cannot happen in process(). There must be a queue, an order to grid events, for example : whenever button is pressed grid checks if there will be an interaction with a wall, and only if there is no wall grid changes, and checks for surrounding tiles for additional interaction, and turn ends.
If You need a method to check tiles around a square range, just search it on this site, I have been answering this question a lot lately
Hello Inces! Thank you so much for helping with my project so far <3 it really means a lot! I forgot to mention that the entities in my world are not bound by player input, instead they change their positions by checking if there is an empty tile in their 4 direction vision and changing direction based on that. Would I have to loop over the tiledata dict to update their positions?
I should have known it was the same project, I was like “why is everyone using the name entity ?” 
So your entity doesn’t react to input, but YOu still need to abide to the rule of keeping queue/order of grid events.
Are they moving constantly in process() ? Are they constantly checking 4 directions in process() ? I faintly remember I did show You setget method earlier, so they can only check once whenever they approach a new tile.
Now You need to design a way they will check for another collisions with other moving entitites only once. I think this should no longer be a method for individual entities. Because when every entity approaches new tile in different timing than the other, recognizing collisions will be a total mess. You need to either make entities move perfectly simultanously, or force the gridmap to check all possible collisions every few moments.
And yes, You would have to loop through tiledata to update their positions.
Do you have any useful resources for a queue system thats related to my game? Also is it possible to give these entities some sort of ID like with tilesets?
Hey Inces, do you think it would be a better idea to create separate scenes for tiles instead of using the tilemap?
No, I think it would be highly inefficient 
However tilemap does have some serious drawbacks. I believe the only huge problem is applying shaders to tiles. If You want to have multiple visual effects for separate tiles on various interactions, then You might want to create custom tilemap using multimesh instances as children. Other than that it is better to use built_in tilemap
Hey sorry for the late reply, I was super busy this week. I figured it would be a little cumbersome. But I won’t lie I’ve been stuck on this for about a month now and I think I’ve made some progress in the way the data should be structured:
Is this good enough or are there flaws in this approach? Thank you again! Also, there is a tile called “empty” which is an actual tile that I gave to the tileset which is equal to an id of 28 instead of -1 for empty tiles by default.
ahm, it looks overengineered 
What do You need such complicated structure for ?
One dictionary should be enough to keep every stable data for your tiles. You can keep it in autoload and read data from it. You can also make such data in Google Sheet and save it as JSON file, if it is easier.
I don’t know why would You need these subroutine functions, that only return pretty much the same info they intake with arguments. I suspect such structure will require tedious coding later
I totally agree that this might be a little too much. I don’t think I mentioned this and this is also why I’m a little confused about using your method, I want to be able to generate a random world, and setting each position with its corresponding id seems very tedious. On top of that the world generation is like so:
Is it still possible to use 1 dictionary for this? Also, some tiles can change at runtime.
You need one dictionary for all stable data, and one for changable data.
All the information, that You designed to be always the same should be kept in one data structure. Like properties of a tiles
{ "grass" : {"walkable" : true, "index" : 1, "maxdurability" : 5, "Sprite" : "res/tiles/grass"},
"dirt" : { and so on }
This dictionary should be kept in Autoload script, because a lot of nodes will want to read this data, like your game menager node and tooltips.
Second dictionary, for changable data, can be much simpler, and only contain current properties regarding to tile position :
{ Vector2(0,0) : {"tile" : "grass", "durability" : 3}, Vector2(1,0) : { so on }}
So when generating a random layout You only iterate through currentdata dictionary to randomize tile types ( “grass” “dirt” “water” ), and when it is done, You set changable tiles properties to default values using stabledata dictionary
Hey, do you have discord or something? Can we message on there if that’s fine with you since Im its pretty hard to message each other like this.
I don’t have a discord and I only have time to answer here and there occasionally, sorry. I can see your question is more like a wide general problem, it is not something that can be answered once and for all, unforutnately I can’t become your project menager 
No thats understandable, and I really appreciate the help so far! But its just like you said, Im just having a hard time fully understanding this specific problem. I hope you dont mind is all. And I dont want you to feel that Im asking for everything, its just that this problem doesnt seem to have a lot of resources for godot at least. But like I said… Thank you so far!
So I created two dictionaries, one autoload and one inside my tilemap script. And just to test it out I did this:
And I still dont know if im using this autoload correctly

Since my textures are a tileset how would I get the sprite from it? Would I have to get the region and texture?
It is kinda what I had in mind 
My entries were examples though, You dont need sprites if You use tilemap, You can use tile index instead. You don’t even need to use string names, You can use tile index as a key data in stable dictionary. Still I would stick to names, because it is easier to understand.
I don’t quite get why is tile_ids
structured like this. Is it supposed to be base of tiles, that are used for random creation ? You don’t need dictionary for this, array is enough, like
["dirt","natural_level_1","grass"]
Look, You can even add some randomrollchance
key in your stable data dictionary, and it will define an individual chance for each tile type to be randomized on game start. With this You can iterate your stable data dictionary on world creation instead of creating another chunk of data elsewhere.
Also I noticed, that You are willing to add some NPCs or monsters as a part of tilemap. Now I understand what You asked before. I believe any “living” tiles with some kind of behavior should be Sprites childed to tilemap. Otherwise You will have to abide to very strict movement rules, that will be similar to some kind of wooden puzzle riddles. I don’t think You want to swap your entities with other tiles every time a movement occurs, I remember You wanted free movement or even fluid. Or how do You imagine it ?
Got it, just changed that to an array. I will add a rarity key as well. As for the entities, they spawn from breaking one of the tiles for example if I broke a "natural_level_1"
tile, I would set the tile from "natural_level_1"
to a "walkable_tile"
and spawn the appropriate entity at the position of "walkable_tile"
. The movement is going to be a pixel-by-tile style movement. I will have an array of available directions that the entity can move and choose one direction from the array. Before it moves, ill have it check if there is already an entity there and if there isn’t then it moves but otherwise, it starts the attack sequence. The question is though, is a process method even necessary? This seems to be a good solution as well: Update Method · Sequencing Patterns · Game Programming Patterns
I cac’t open that page, but I agree this shouldn’t be updated in process. As I mentioned earlier, there should be strict timing of updating tilemaps as a whole, either by command chain or by timer ticks. But not every frame 
If You make entites as tiles, they will only be able to teleport as snapped to tilemap grid size. So You can use tiles to spawn them and detect their position/surroundings, but actual entities should be separate objects with sprites. This will allow You to interpolate their movement, for example by using tweens.
However it is still a good idea to keep track of entities and their positions in another changable data dictionary. I mean You could use just one dict for everything, but are You sure there will be only one tile/object at one position ? Or there can be both “walkable_tile” and “entity” in the same spot ?
I’m sorry, I put a period at the end of the link, it should work now. But it is possible for there to be 2 entities on the same tile.
Ok but too long 
So it is decided - entities must be separate objects moving on a tilemap. They will use global position for movement, but they will also need to always translate their real position into tilemap position. This is best done by setget
var tilepos = Vector2(0,0) setget gettile
func process():
self.tilepos = Tilemap.world_to_map(global_position)
gettile(value):
if tilepos != value:
tilepos = value
#here goes all code to check surrounding tiles
#and possibly a code to update entity position in dict
All is left is to design how are entities going to move alltogether. Will they appear simultanously and move in the same speed or rhytm ? What is going to change their movement ?
Each entity has its own movement speed, but it is possible for 2 instances of the same entity to have the same movement speed
If they may have different speeds and move non-simultanously, I would go for collision objects. Let them detect collisions with each other, by making them kinematic bodies or areas. They don’t need to collide with tilemap, but it also might be a good sollution.
Originally it looked as your project is some tilemap puzzle, but now it seems to be very classic. So Zombie objects collides with Bear object and their animation begin. No need to check surrounding tiles. Checking surrounding tiles may be useful if You want to know about collision ahead of time.
So there is no way to implement this without using a kinematic body or area2d? I already implemented a collision system for the entities but it was very buggy.
tilemap alone is only good for very stiff movement, like tic tac toe or classic ASCII roguelikes. If You want any visual aesthetics You shouldn’t go this way.
You need to combine tilemap functionality with dynamic collisions, and it will not be buggy. Imagine something like this :
On entitity colliding with another entity :
if checksurroundingtiles() detects empty walkable tiles around :
change movement direction towards one random detected walkable tile
This way You don’t have to rely on physics processing and buggy slide movement, but use singular properties of physics engine to enforce stable moevement rules
What movement behavior do You have in mind ?
Okay, then I will reimplement the collision handling with a kinematic body. The behavior is actually pretty simple if a bear collides with a zombie then start the attack attack animation and have them attack each other until one dies. I don’t even need to check for surrounding tiles.
But You may want them to approach each other in a way they stay in their tiles, not overlapping. So You will need check of surrounding tiles to detect future collision and make entity wait or go. You will also need tile detection to predict collision with unwalkable tile, so entity may take a turn before it collides and it won’t jitter into a wall
How would I be able to have them stay in their tiles and not overlap? Do you think some sort of line of sight algorithm would be good too?
Whenever your entity starts moving towards a direction, it can update its position in your stabledata for the future tile. So whenever another entity is going to approach a new tile, it will check stabledata if it can move to this position ( is there a wall, or is there another entity just walking into it ). If it detects another entity coming, it can wait in the center of its tile, until another entity reaches the center of its tile, and then both play the animation.
You might have seen something similar in old RTS like warcraft2. When 2 units collide in ugly angle, one of them makes a little stop, another one positions itself in fixed distance. This is also a system of a quare tilemap working with collision physics