Hey, if you're new around here and are wondering where devlogs for Pre1, 2, 3 and 4 are: they don't exist, and I just now started this new devlog series. So I will release a new devlog for every future pre-release of an update. Stay tuned!
Previous Home Grown Devlog: GameJolt, Itch
Welcome to the 16th Home Grown devlog, and the first actual Home Grown: Beta devlog!
Technically I've published a few after Beta 1 began development, but all of them can be summed up as "I'm very pathetic and keep taking longer than I want to! I wonder why it's not like I spend so much time making devlogs that only consist of me whining. So anyway, the beta is still not releasing anytime soon :P". Basic whiny bitch behavior.
So none of them had me talking about the gameplay, programming, artwork, or anything else. But that changes with this devlog!
– — GAMEPLAY — – -
This pre-release has had the most changes in this area. From pre 1 to 4 I had made a main menu, options menu, basic camera, and empty test scene for the player — that's it, literally. Even the player was simple, with no animations or inventory (the player still had no animations as I have a complex idea for them).
But this pre-release has actual gameplay and generating terrain! So let's start with that terrain...
Terrain Generation (boring technical stuff!)
The World Generator (the class that will handle the generation of terrains, biomes, and buildings) is simple in concept but had a lot of issues.
Firstly, the world is split into World Sections, each handling the loading of their tiles, items, objects, and entities within them. Below is Tile -4 (first tile of Section -1) against Tile -5 (fourth tile of Section -2).
You might notice something off. Unlike other procedurally-generated worlds, Home Grown does not use a grid-based tile system, the World Sections only save the ID of each Tile (along with some data directly linked to the tiles).
Neither the Tile nor the Section positions are saved because it’s purely angle-based. This means I have to align the sections at the load time of a new one.
Later, now that the alignment is fixed and I changed the generator to use Noise instead of generic random numbers, we have the terrain below.
A nearly flat terrain that goes on infinitely in both directions. In the release of Beta 1.0, there will be more types of tiles, along with the textures that also have variations.
So, how does the game determine what tile to load?
WARNING: Very nerdy stuff ahead, watch your brain.
Let's say I wanted to generate Tile 5. First, the World Generator loads the Tileset of the current biome (currently there is no biome system, so this example exclusively uses the 'example' tileset). This is a JSON file with all the data of a group of Tiles, such as the one below:
"display_name":"Place",
"tiles": [
{"id": "hg:tiles/example/flat",
"angle": 0,
"bump": 0,
"canflip": false
},
{"id": "hg:tiles/example/tilt_mild",
"min_angle": 0.28,
"angle": 0.35,
"bump": 0,
"canflip": true
},
{"id": "hg:tiles/example/mound",
"min_angle": -0.1,
"max_angle": 0.1,
"angle": 0,
"bump": 0.5,
"canflip": false
}
]
Each data set inside "tiles"
is the generation data for that specific Tile ID. This is pretty much all the World Generator uses to determine whether that tile will be selected.
Next, it gets the Noise Angle by subtracting the sum of its three right neighbors' Noise values from the sum of its three left neighbors' Noise (the higher the Noise Angle is, the more tilt to the right, and the lower it is the more tilt to the left, with 0 equaling no tilt).
Then, it gets the Noise Bump by subtracting the sum of its six left and right neighbors' Noise values from its own Noise value, and dividing that by 6. (this number is higher when its neighbors’ noises are lower than its own).
Finally, it gets the Tile with an Angle closest to the Noise Angle and the Tile with a Tile Bump closest to the Noise Bump, it checks which is closer to their desired level, and selects that Tile (i.e: If Tile A’s Angle is .1 from the Noise Angle and Tile B’s Bump is .2 from the Noise Bump, Tile A will be selected).
Got all that? Okay...
Oh, and one more thing I forgot to mention. If the "canflip"
of a tile is enabled, its Tile Angle is counted as both negative and positive, so when its opposite Tile Angle is selected, the WorldTile runs its flip()
function, which by default, flips its collision and any display nodes it has (textures, lighting, text positions, etc.).
All this took me about two weeks to finish, and this doesn't even get into the optimization part of the code! So I'm pooped out on terrain-generation shit at the moment.
Now for...
Item Generation (less boring technical stuff!)
The items are much simpler to generate as they don't use Noise... At least, for now.
By the actual release of Beta 1, Itemsets will be biome-dependent and can use customized Noise to increase or decrease item spawn rates in certain areas. For example, I may use a Noise that closely resembles sets of buildings, so scrap and other trash can be more common in city-like areas.
Anyway, here's the most basic form of an Itemset in Pre5.
"rolls": 5,
"chance": 0.5,
"items": [
"hg:items/scrap",
"hg:items/limb"
]
As I said, they are much more simple.
The section Rolls a random number from 0 to 1 five times, and if it's below the Chance value it selects one of the items to spawn.
And this is the most basic form of the itemsets, there is a ton more you can do with them. You can set almost any value of an Item's node with the "data"
value.
You must replace the item ID's string with a dictionary to set these values. Here's an example of the Scrap with all its values at their defaults:
"hg:items/scrap"
## BECOMES >>
{
"id":"hg:items/scrap",
"data": {
"info": {},
"info_deltas": {},
"velocity": "Vector(0,0)",
"world_layer": 1
},
"entries": 1,
}
This does the same thing as the previous example, but now with all the item's default saveable variables. On top of being able to set custom data, I can set "entries"
to 2, which will include that item in the pool twice, with the same data
and id
. I can also set "data.world_layer"
to 2 so it will be active in the world's Building layer (interiors) instead.
Additionally, I only need to add the values I'm changing from their defaults, so if I just wanted to add several entries and make its display name "Bob", the item's dictionary entry will become: {"id": "hg:items/scrap", "data": {"display_name": "Bob"}, "entries": 5}
. There are probably better ways to do this, but this is how it'll be for now.
Currently, for Pre5, I have this Itemset for testing:
"rolls": 6, "chance": 0.2,
"items": [
{"id": "hg:items/scrap", "entries": 2},
{"id": "hg:items/limb", "entries": 1}
]
This rolls six times, each with a 20% chance of spawning an item. The Scrap has 2/3 of a chance to be picked, and the Limb has 1/3.
And this is what it looks like in-game:
Three limbs, and four chunks of scrap! Closely matching the Item Set file's data.
As a bonus, this is easy to expand upon and well optimized, as the generation progress will choose to either queue item spawning or load them all at once depending on how close the player is.
The Finalized Open World
Below is a video of the current finalized world generation, with saving and loading, naturally generating tiles, and scattered items with custom attributes.
Please keep in mind this is at its most basic form with only the example tiles and no biomes.
As you can see, at startup, generating three WorldSections each with four WorldTiles and many items takes about 45ms, and loading a single WorldSection takes about 5ms.
Yes, this is with only three possible tiles, no biome system, and a basic form of the Item generation, but with the way it's set up, I don't see it slowing down by much when I add all that.
– — DESIGN — – -
Here I discuss how I design certain gameplay elements and the art design of the menus.
Player Inventory
There's not much from Home Grown: Alpha that I liked, but its inventory wasn't bad. I loved the rough look of it, it perfectly encapsulates this game's history.
So I took that base and started improving on it!
One major change from the original alpha is that it now only shows one item from your inventory at a time, fading out the two items next to the selected one. I was originally gonna use Godot 4's mask system, which uses a texture to fade out nodes at the edge, but decided to simply change the alpha of each slot's modulate.
Again, I still have much to improve and add, but it works well.
Menus
Something I’ve had an idea for recently is the Save Select menu.
The menu will be a three-column scrolling grid, with icons instead of save names. When you hover over an icon it'll display the world's name below it. Clicking opens the saved game's menu, with options to load, rename, or erase it.
That's the basic structure of the saves menu! But what will the icons be?
It will NOT be a recent screenshot of the world, a zoomed map, or the player's custom character (I won't even allow player customization for single-player). That's all too generic.
Instead, it will be the earth's globe behind the player character's head facing forward. I have plans for a dynamic globe design, but that's coming long after Beta 1 (possibly not even on release). So, for now, it'll only be a simple globe of Earth that changes in brightness depending on the time of day. So, let's focus on the player's severed head, shall we?
At its base, the player's head will be just that; the player's head. But, there will be no customization for the player design, so what makes the icon look unique for each save?
The head will use two of the player's values to decide its appearance: their health and total infection. I'll probably add other values in the future, but it's only these two, for now.
For Health, I will have several blood and bruise layers increase in visibility as the player's health nears 0. It begins at 90 or lower health, getting a new layer of damage every 10%.
For Infection, I will add veins that increase in thickness, and get more green the more infected you are. Unlike Health, you need at least half infection for it to be noticeable on the save menu, getting increasingly disgusting from there.
I may also make it keep scars even after the player has healed. Maybe every time they reach below a certain health percentage it adds a new scar that slowly heals over a longer in-game period.
– — Closing Notes — – -
That's about it! There is more I did, but I can't talk about everything.
Also, I am taking a break from Home Grown, again. So I can catch up on other projects I'll release in 2025. I'll still write ideas and notes, but Six Hours at Diddle's and one other project need to be my focus until they are released, then I can put more time into Home Grown again.
Anyway, I'll be seeing you all.
~ Irøn
0 comments