1. Star Child
  2. News
  3. Star Child Dev Log #8

Star Child Dev Log #8

Jay Ingle - lead developer, designer, and artist:

This week I buried myself in code. I have worked with GDScript for about 3 years now, and I finally feel like I have a handle on the basics. The very basics. I am a novice programmer. I can make things work, eventually. This week gave me a bit more confidence though. Even though there are still things that intimidate me, confuse me, or frustrate me, I can see the progress.

I worked through piles of scripts. I reworked badly designed sections, using more enumerators and dictionaries.



I changed every get_node() i found into using a signal or a global value instead. get_node() is dependent on scene tree structure, and should rarely be used. If there is a value that you need in another script, you can make it a global value in an autoload instead. If you need to trigger something, or send some information, signals are perfect. A Global Signal Bus is a great way to store all of your signals in one place, call them easily, and keep them organized.



This was also a time for commenting. If you don't properly comment your code, which I hadn't been doing, shame on you (me). Anyway, welcome to the new era of me commenting my code.



Also I need to put types into all the arguments of my functions. Yep, back to work.


Janne - the other guy:

Unlike Jay, I've been programming since I was a young child and also have decades of professional experience in coding and leading software projects. With Star Child I've been trying to slowly introduce better coding practices in a way that doesn't make it too difficult for Jay to work with.

One of the recent opportunities for this was the automap, one of the last completely missing features we had. I had a vision on how to build it based on flexible structures that will allow us to forget the internals of the automap as long as we follow a few basic patterns when building the game.

As an initial target, I wanted the automap to build its own data structures based on the levels we actually have in the game, and the easiest most easy-to-comprehend way to make this kind of "auto-discovery" was based on filenames. Our levels normally go somewhere under res://Levels, and I decided that adding a prefix to the filenames could be used as a grid coordinate system, A-Z for rows, followed by a number for columns. It gets a bit more complicated than that since Star Child has rooms spanning multiple rows and columns in the grid, but not significantly more complicated.

With this target, I decided on the following patterns:

- B4 = Row B, Column 4
- A-B3 = Rows A-B, Column 3
- C4-5 = Row C, Columns 4-5
- D-E5-6 = Rows D-E, Columns 5-6

To keep things easier, I wrote 4 separate Regular Expressions to match each of those cases separately as well as splitting out the rows and columns from it, and then functions to find all scenes recursively under res://Levels, and identify which of them look like a level - having this coordinate at the start followed by an underscore. Once identified, I build a grid of all the coordinates used, and find the min and max ranges for rows and columns, and fill in the blanks. Now we have our basic map as a grid. This script is autoloaded as a global script, and additionally processes the grid into maps of which coordinate maps to which scene, and extracts various properties from the filenames for easy access later e.g. the full path to the scene file and the ranges for the columns and rows.

Next up we needed a data structure for what the player actually knows of the map, so I created a dictionary with the list of current coordinates for the player (as a single level can span multiple), and all known coordinates and added it to our save + load logic. All the logic above is in an automap_data script. To get data into it, I replaced all previous "switch to level" -logic with a single central function, that also calls enter_level with the scene path. This can then be used to again determine the coordinates from the filename, and simply update current coordinates, and add any missing ones to known coordinates. In the end we also send a map updated -signal.

Rendering of this is currently functional but not quite ready. Added a new automap scene with a script attached to our HUD. The scene has a few basic visual elements attached, background image, a CenterContainer, and then a Control with a unique name "MapGrid" for easy access in code. Every time the automap is rendered, it first fetches data from the automap_data, and processes a few lists to make rendering easier:

- List of all non-blank coordinates
- Available size for each grid cell inside the container, with margins removed, rounded to nearest full pixel, and approximately centered with offsets
- A map of coordinate to their visual element in the grid

For the visual elements I tried multiple approaches that didn't end up working right, and in the end ColorRect inside a Control seemed to be a reasonable way to accomplish what I had in mind. Each of them needed a custom_minimum_size and then position, and to be added to the MapGrid, but that was pretty easy.

Then after the automap has been initialized, and every time we get a signal that map has updated, we'll refresh the automap. Refreshing simply means taking the current coordinates, known coordinates, and non-blank coordinates, and looping through every coordinate and updating their colors. We default to black color, but if it's in the current coordinates we set it as green, if it's known then light gray, and if it's just a non-blank coordinate we make it dark gray.

This renders the full map and tells you which areas you've visited, and where you are rather effectively. Now of course we'll want to refine the list of which areas we'll highlight that you've not visited, but the structures are now in place.

One last thing that I wanted to update based on this, was our level changing logic. We have a Scene Changer node we can add to areas where we want you to transition to the next screen from, and previously each of them needed the full resource path of the target level. Since we now have coordinates for the levels, I decided that we could just give the Scene Changers clear names like "ToB2" and have it automatically find the scene based on that name, and transition there - so that's what I made it do.

Now all Jay has to do is create a new level res://Levels/tests/Z99_some_test_room.tscn and the automap will automatically know where it is and update accordingly, and then add a Scene Changer with the name "ToZ99" and it will work. The one remaining thing we'll want to try out is automatically identifying where the player should be spawned in based on a corresponding Scene Changer name, so if you're going from B2 to B3 with Scene Changer names "ToB3", you'll probably want to spawn in by the Scene Changer pointing to the level you just came from, "ToB2".

To make writing all of this easier initially I wrote logic to just print the map grid and automap state to the console, so just building a string where every empty cell is a space, and then assigning characters for "current", "visited", and "not visited", appending to the string before printing. This made it a lot faster to know when I had logic that was fully functional for the internals without having to worry about the visual glitches on the rendering, of which there were many on the initial attempts.

The background is fully a placeholder and generally tweaking the visuals further we'll post-pone until the full size of the map grid starts taking shape, so we know the final size of the cells, how and if we want to highlight connections between rooms and all that.