BLOG
BLOG
Welcome back! This week was a bit of a slow one, so this update will be pretty quick (and mostly technical).
Originally I was going to work some more on resource management and placeables (i.e. creating placeable walls, an HQ building, some sentry guns) but I decided to start tackling a more pressing issue.
One of the core elements of this game is that the world will be procedurally generated, and ever-expanding (or at least big enough that the player can progress through all the stages I have planned), but there's been a problem: performance. I know that, judging by the screenshots from previous updates, the game doesn't look like much, so hearing that it has some performance issues could be surprising. Regardless, it does; anything bigger than 50x50 tiles tanks the performance, and trying to generate a map bigger than 100x100 just crashes the process immediately. Or at least, it did, until this week I started taking a look into performance.
I did some research into optimizing systems in Godot, and implemented a few different methods (mainly just pausing the processing of any offscreen node). Now, the game is able to launch (and runs smoothly) at 100x100 tiles, but testing much larger boards (i.e. 200x200) still either tanks performance or crashes on launch (part of me thinks it's to do with giving the engine that much to load right on launch, as dragging that initial process on too long may be what's causing it to close down; a deferred approach could be preferential, for instance with a loading screen).
There's still lots more to do! Next week I'm planning on looking into optimizing the tiles more, and hopefully boosting the framerate. More importantly, I want to start designing the actual procedural generation system. I'll start on pen and paper, so it's entirely possible next week's update will be a hypothetical system that's only half implemented (depends on how much time I get to work on it, it's only the first week of lectures so I doubt it'll be all that busy lol).
That's all for this update! Sorry there's no fun screenshots or interesting new features, hopefully the next update I'll have something cool to show off. Happy Wombat Wednesday! :)
This week I finished off the defuser system by adding in flagged-tile assignment (as I mentioned last time), and began work on resource management.
Now, when a tile is flagged, the nearest available defuser (one that is not already defusing a different mine) will walk over and defuse it, clearing the space and earning you some cash. This means you can go about clearing tiles and flagging potential mines without having to worry about manually calling defusers over; the closest one will make its way over on its own.
From a technical standpoint, this system was a little more complex than it may sound. I was worried about certain edge cases that may upset the player.
For example, if there is only one defuser, a basic system that pops the next flagged tile in the queue and assigns it to the defuser one at a time could work, but in some cases would be very annoying (what if there's a flagged tile right next to the defuser, but instead of assigning them that one it assigns them one all the way across the map? That wasted travel time would make the defusers seem really unintelligent.) Alternatively, you could make it so that the system either
Uses the defuser’s position to find the nearest flagged tile, and assigns it that way
or,
Uses the flagged tile’s position to find the nearest defuser, and assigns it that way.
Either way, there are issues. Say we have two defusers, defuser A and B, and two flagged tiles, tile 1 and 2. System A would use defuser A’s position to find the nearest flagged tile, tile 1. But what if defuser B was closer? We wouldn’t know, because the system only checked which tile was closest to defuser A, not which defuser was closest to tile 1. We have the same problem in reverse with system B: what if tile 1 chooses defuser B, when defuser B was right beside tile 2? Watching a defuser walk away from a flagged tile they were so close to, to go defuse one that is much further away, would be aggravating.
To fix this, I basically mixed the two systems. If there are no available defusers, but there are flagged tiles, and a defuser becomes available, then just assign it to its nearest flagged tile (system A). Otherwise, if there are no flagged tiles, but there are available defusers, and a flagged tile is added, use that flagged tile to find the nearest defuser, and assign it to defuse the new tile (system B). I’ve done a fair amount of testing with this system, and so far it’s worked with arbitrary numbers of defusers and flagged tiles without making me pull my hair out, so I’m quite happy with it.
Other than that, all that was needed for the system was a signal to cancel flagged tiles (so if a defuser is assigned a flagged tile, and it’s on its way there - or even currently defusing it - and the tile is unflagged, then cancel the defusal). This will be extra important in combination with resource management, because I’m planning on having the player lose money if they defuse a tile that wasn’t actually a mine, so being able to cancel them is crucial.
Speaking of resource management, the base system was implemented this week! Now, when a defuser defuses a mine, the player’s currency count goes up (currently by $185, but obviously that’s subject to change with balancing as the game expands). If the player incorrectly flags a non-mine tile, and a defuser defuses it, the player loses money. The total currency count is displayed at the top right of the screen, and the most recent transaction is shown just below in either red or green to show whether it was a gain or a loss (i.e. +$185 in green, -$185 in red). The most recent transaction also fades after about a second to avoid any confusion.
From a technical standpoint, this was primarily about setting up signals between the tiles and the GameManager (and UI) to display currency updates. It was pretty simple, and I made it quite modular so that the same system can be used with different revenue sources/sinks.
I think that’s about it for this week! Next week I’m planning on updating the placeables (structures) system so that placeables actually cost money, and cannot be placed unless the player has enough (hopefully I’ll get some other stuff done too; I’ve got to check up on the ol’ Trello board and see what's next lol). Thanks for checking out the blog, and I hope you have a lovely Wombat Wednesday!
Welcome to the first official Wombat Wednesday! This will basically just be a way for me to check in weekly with progress on upcoming projects and other cool stuff I'm up to. I've been wanting to do this for a while, for a few reasons:
To keep anyone interested in our work up to date with what's going on, and to show that we haven't abandoned our projects.
To hold myself accountable. In order to post these updates every Wednesday, I have to have done actual work worth posting. I'm hoping this will drive me to work on projects more consistently, and actually see more of them through to completion (crazy, I know).
To serve as a timeline/time capsule. I figured it would be fun in the future to look back on the development of our early projects and see what decisions we made, why we made them, and how long it took to reach certain milestones (the latter will hopefully be helpful in the nearer future as well, mostly when estimating dev time when starting a new project).
Anyway, on to what I've been up to!
Right now, I'm working on (the tentatively named) Project Mine Settler, which is a city building strategy game. Here's the gist of what's planned:
You land in the middle of a grey expanse, and the goal is to clear the tiles (not unlike a certain classic PC game about mine removal) in order to reveal the landscape below, and make space for your ever-expanding settlement. Using the mouse you can click tiles to reveal them, but be careful: some tiles are mines, and will have negative repercussions when uncovered. Using the numbers displayed on uncovered tiles (which show you how many mines are in the 8 tiles surrounding that one), you can deduce which ones are mines, and flag them. In order to remove flagged tiles, you can build a defuser tent, which will spawn defusers - little troops who march around defusing flagged tiles, earning you money.
As you expand, you'll uncover different monuments, biomes, and occasionally enemy encampments, triggering combat encounters. During combat encounters, your troops will duke it out with enemy combatants in a deadly tug-of-war: whoever manages to push their way into the enemy camp and destroy their HQ first wins, eradicating that enemy entirely and claiming its resources.
There will be tons of things to build, of all different types and sizes. Generally, the categories I'm thinking of at the moment are defensive structures (i.e. walls, sentry turrets, repurposed mines), resource generation structures (i.e. a gemstone mine, an oil pump) and spawner structures (structures that spawn different troop types, like the defuser tent, or barracks for spawning armed troops, or even an army depot for spawning larger units like tanks). Those will most likely be the bulk of it (unless I think of more, lol) other than obvious things like decorations.
I currently have the tile-grid generation up and running. The player can specify integers A and B and receive an AxB sized grid of tiles, which is sprinkled with mines. The player can then clear those tiles, using the aforementioned mines-in-proximity count to deduce which not to uncover (which they can then flag).
I'm not sure how technical I really want to get here (I want to avoid boring any potential non-technical reader to death) but the gist of how the general clearing system works is that when a mine is clicked it sends a signal to all of its neighbours (each of who it stores a pointer to) to check whether or not they should be cleared. If they're not mines and they have no mines surrounding them, then they are cleared, and they send the same signal to all of their neighbours. If they're not a mine but they do have a mine somewhere in their proximity, they clear themselves but stop the signal there (not sending it to their neighbours, thus stopping the recursion).
I've also implemented a system for placing structures, and have created a couple of stand-ins to test the structure (one of which is a very, very basic version of the defuser tent). Additionally, I added a basic version of the structure selection menu so that I can test different structures (though it is very much a work in progress).
On the more technical side of things, essentially the system just spawns an instance of the building and makes it a child of the cursor. Then, using an Area2D, I detect when it's colliding with tiles, and using that information I can dictate whether or not the structure can be placed (a shader is applied to either highlight the structure red, if no, and green if yes). When placed, the structure is re-parented to the board and is sent a signal so that it knows to start doing whatever it's supposed to do (i.e. for the defuser tent, it starts its 'spawn defuser' timer, which spawns a defuser troop upon timing out).
(As you can see in the gif, I am still very much operating with placeholder art lol. I figure it's a bit early to pull in Louisa, though I'm planning on asking for her help to think of an overall art style soon)
Last but not least, I implemented the defuser's base functionality. They can move anywhere within the cleared space, and will move towards flagged tiles, defusing then when within range.
From the more technical side, this implementation is definitely not done. While entirely functional, there is a lot of work to be done in terms of flagged-tile assignment. Currently, defusers aren't actually moving towards flagged tiles - they're moving towards wherever the mouse has right clicked most recently. Then, when they arrive there, if they have also entered an Area2D that is in the group "flagged", they send a signal to the area to defuse the associated tile. This presents a whole lot of technical issues, like what if the defuser is right between two flags and defuses the wrong one, among other things (like just refusing to defuse a tile if it was within range and flagged when it defused the previous tile). And that's not to mention the obvious big issue: if all defusers just move towards the mouse's most recent right click, then they'll all be defusing the same mine, making having more than one defuser useless (and leaving the player to have to micromanage one defuser the whole time).
The next step in this implementation will be to create a system for flagged-tile assignment, meaning that when a tile is flagged it's added to a queue, and when a defuser becomes free it moves towards the position of that tile (though it most likely won't be that simple; if there are free defusers at the time when a tile is flagged, we will want to ensure that the nearest defuser is dispatched, so I'll have to loop over available defusers and get their relative distances and choose the shortest). But that's a job for later (potentially tomorrow, but hopefully at the very least between now and the next Wombat Wednesday).
That's all for this update! Thanks for checking out the blog, and please make sure to come back next Wednesday for more!
In the future this end segment might have calls to action, like "Wishlist the game on steam here:____", but there's no steam page for the game at this point (still very early on, especially with the $100 upfront fee lol, 'tis a lot of money for a student).
Anyway, hope you're having (or had... it's pretty late at this point) a lovely Wombat Wednesday!