Posted October 13, 2025 by MezzSoft
#Landsword #Progress Report
Hello. It's October now, and things have been pretty quiet here for the past three months. I'm going to try and put out these progress reports more frequently. I admit I can be a bit shy about what I share, since I find I almost always change things right after showing them publicly.
This post will mostly be going over pathfinding and some of the technical challenges I've been tackling so it might not be very thrilling to read, but I'll try my best to keep it interesting with GIFs.
In a top down shooter, how enemies move probably isn't the most important thing to worry about. You can get away with some rather basic movement since players are likely going to be blasting them the second they have a clear shot. At a bare minimum, they really just need to wander around and record the player's last seen location when they find them. Currently in the game, aside from occasionally following the player when they run away, the enemies mostly just move from point to point in a straight line, sliding around corners when they meet them.
It's nothing special or particularly interesting, but more importantly they really like to do this:
This problem is something I've been aware of and promised would be fixed for a long time, but sitting down and solving it between trying to solve a bunch of other challenges with the game — both art and code related — ultimately delayed it until now. In some ways it's a good thing however, since we've got levels mostly figured out, and we don't have too many different kinds of enemies in the game to rework.
So let's get right into it.
Breadcrumbs
I mentioned on the previous update that enemies had become slightly smarter using a "breadcrumb system", but I neglected to show how it really works. In short, when you're spotted by them you start leaving behind a trail of points, and those who are aware of your presence can follow the trail, thus allowing them to chase you around buildings and far away distances when you're off screen.
Very simple to implement, extremely lightweight, and instantly adds an extra layer of depth to the gameplay. I added this as an attempt to fix the issues with them getting stuck, but it's still basically a band-aid solution to the problem.
We need to start from scratch.
Let's take a closer look at how the movement in the game works...
Look at this poor bastard. He's trying his best, okay?
If you're wondering how the actual pathfinding in the game works, the answer is quite simple: There isn't any.
Well, not in any smart way.
All of the land enemies use Game Maker's built in mp_potential_step functions to navigate the building objects in the game. While they do react to things like collapsing structures, explosions, or debris knocking them into alert mode, none of them really have a way to smartly negotiate obstacles. They brute force their way to target coordinates with mp_potential_step, which allows them to slide along walls, and if they hit an obstacle in their way they simply reverse the direction of sliding and try to move along until they hit another obstacle. This process will then repeat forever since it's not actually pathfinding.
For the most part, I thought this wasn't so bad as the maps tend to be decently open, and I think in a tight urban environment you would want to stick close to the walls for cover. The underground sections I think are also mostly fine with this rigid type of movement. However, the limitations of using mp_step are quite clear — enemies get stuck in corner traps, constantly.
So why don't we try adding some real pathfinding using the built in functions of Game Maker? No more of this mp_potential_step_object() nonsense. Let's have an actual terrain grid using the mp_grid functions to check the buildings, and have the enemies draw and follow a real path to their target coordinates. That should solve corner traps, right?
Well, this isn't really working either...
mp_grid functions require you to generate grids to work properly, as the name implies. Landsword's levels don't have objects that are snapped to a grid, with the exception of the walls in underground levels, but even those contain pillar objects that are placed down randomly. We're putting objects literally anywhere we want, at any angle, and with varying hitboxes that come in all different shapes and sizes. Not only that, but every one of those objects is destroyable and can even be pushed around by bullets and explosions, so if we generate a grid to use for pathfinding it's going to have to be updated probably every 10-20 frames or so.
It would also need to be an ultra dense grid at a high resolution of at least 12 x 12 pixels per cell, as we need to flag every building's hitbox at the cell coordinate points with a 1 or 0. That's obviously really bad considering the size of levels (usually 3200x3200) and the amount of buildings. Even if we could optimize it so it only checks small areas the enemies and players are in, it would still need to be actively maintained with how things are getting wiped out left and right during gameplay. We haven't even figured out how we're going to compute a good path for them to smoothly follow on top of this.
If we had grid snapped objects at fixed sizes (e.g. 16x16, 32x32) and way smaller maps this could theoretically be done in an optimized way, but these built-in functions just don't work for this kind of game.
We want some nice smooth pathfinding between points without tanking the game to 2 FPS, and we want enemies to at least try to stop getting stuck in corner traps. What can we do here?
Weighted steering behavior
Essentially, we're still doing the same thing of picking a coordinate and brute forcing our way to the other end, but unlike the mp_potential_step commands of Game Maker which use a collision mask, we're constantly doing 2D raycasts around us for buildings and directing the enemy away from them relative to their distance and value. We can give certain types of objects different values of "weight", for example buildings and solid structures have the highest value since they're the most important to avoid. Cars, trees, and light posts have a low weight since they can be driven over, but the enemy will still give a little bit of care to avoid them instead of plow directly through.
To keep it optimized, we can increase or decrease the total amount of rays being cast depending on how many enemies are returned in a radius count, and we can also increase the amount of frames between each time we run a check. The found object coordinates are all stored in a temporary array which is cleared every time it runs, so it's not necessary to check if they exist every frame.
Let's apply this system to a Mantis crawler and see how it behaves now...
Check out that smooth turning! It's a small thing, but it looks like the pilot is actually steering his vehicle, and it feels like there's some weight behind it now instead of just a sprite moving between two coordinates.
Using this method you can see obstacles are actually somewhat negotiated now, and putting the end coordinates between some buildings no longer causes them to beeline directly into the side and try to slide around the edges.
Does this mean we're free of enemies getting stuck and wiggling?
Oh no. He screams for he knows not what to do...
This still isn't actual pathfinding, as you can see. It's not going to really stop them from getting stuck in corners. In a way it's basically just a more advanced version of mp_potential_step — we're still trying to force our way to a point but just using whatever direction gives us the least resistance. In tighter spaces where enemies are completely surrounded by buildings, it's definitely not going to work. So let's try writing and integrating our own pathfinding system, with nodes and an adjustable LOD.
Now we've got some real navigation! The cool thing about combining this with steering behavior is we can actually have our enemy skip pathfinding points if it chooses a different route. It's not just following the line of points rigidly, it tries to find the nearest one relative to its location, and since it's still weaving around buildings it can basically take shortcuts to ignore them. The path is almost like a suggestion or last resort if it can't find any other way to its destination, which I think makes things feel more dynamic during gameplay.
(Also the zig-zagging of points you see is a product of the object calling it not rounding the coordinates, but I forgot to capture a GIF of the fixed version.)
So what's actually happening here?
This is a greedy pathfinding system which starts from the enemy object, checks the end destination, then attempts to advance from the start coordinates to its goal by doing a bunch of 8 direction circle collision checks spaced out between each other until it either reaches the end destination or at least returns the last node before it failed to find an empty spot.
The benefits of using this system are that it's decently fast in levels, highly adjustable for optimization (we can use different types of collision checks, vary their amount, the spacing between them, or even add randomization), and it works roughly 70% of the time, which is much better than our mp_step functions which I'd say had a success rate of roughly 50-65%.
But for obvious reason, this isn't a great way of actually finding paths. It's still trying to force its way to an end point, and not really sorting results to find an optimized chain of positions to make a path.
Most of the developers reading this probably know what's coming next. We're going with the tried and true solution...
This is an A* pathfinding system that starts from our object’s current location and works its way toward the goal by exploring a ton of potential positions in a grid generated on the spot. We're still calling collision_circle checks in eight directions like before, but each position is scored based on how far it has traveled from the start and how close it is to the goal, allowing us to prioritize the most promising routes first. We save each of the positions that have already been explored into an array to avoid revisiting them, and gradually build a network of nodes that can be traced back from the end coordinates to create a traversable path.
This is way more reliable than simple greedy approaches. It consistently finds paths around obstacles, and I'd say it has roughly a 90-95% success rate. Combined with the steering behavior it isn't particularly accurate in how close it follows the path of nodes, but what matters is it nearly always finds a way to negotiate the complex building layouts, avoiding the infamous corner traps which the previous two systems sent the enemies into a loop of spinning in place. It's not completely perfect nor a guarantee that they won't ever get stuck of course, but it changes the current state of pathfinding from "likely going to see multiple enemies get stuck in place every mission" to "might see an enemy get stuck for a moment every two to three missions", which I consider a large improvement. Even AAA games have an enemy glitch out every once in a while, it's just something that's hard to eliminate the more dynamic your game's environment is...
Now this process can become very CPU-intensive depending on the number of buildings in a level and how far the destination is, since greater distances require sorting through more nodes to find an optimal path. To keep things efficient, I added checks that adjust the number of nodes it can loop through based on how far the goal is. I also implemented timers to prevent enemies from calling the script too frequently, and prioritize on-screen enemies being able to use it over those off-screen.
With these simple optimizations, this pathfinding system turned out to be extremely lightweight, using less processing power than the current mp_potential_step commands use. The reason for that is mp_potential_step runs every frame to check nearby hitboxes in order to perform the sliding, which means expensive collision calculations happen constantly regardless of what's around them. Previously I tried to optimize this by doing a radius check for buildings and only using the mp_step functions if they find one closeby, but performance still wasn’t great. The new A* pathfinding system works by just running a single script every 2-10 seconds which produces a list of coordinates for an enemy to move along without doing intensive collision checks every frame.
Enemies can also now be way more aggressive and pursue the player throughout the level. Something that's bothered me a lot aside from them just getting stuck is how quickly they seemingly lose interest in you if you're hidden for a few moments. I've done away with the breadcrumb system and instead added an alert variable in each of the enemies that builds up if they see you, and ticks down when you're hidden. If it's greater than zero, the enemies are aware of your general location even if you're hiding across a city block, so you'll have to really evade them for some time if you want to get them off your trail. I realize this might make the game way harder for some of the less experienced players, so eventually I may add adjustable difficulty that has the alert system tick down relative to the hardness.
A tag team in action. The combined steering behavior that keeps them separated means they tend to spread out way more now.
With the implementation of steering behavior, tanks can now move smoothly around corners and buildings instead of scraping back and forth until they push them over. I plan to design some IFVs and other more conventional armored vehicles to fight now that we can have vehicles properly steering. If you have any suggestions for them, let me know.
Pushable enemies
Another small thing that I've been meaning to correct is how the enemies react to the player driving into them, or rather the lack thereof.
Early test footage (March 2024)
Sometimes when enemies such as the grubs push the player around, the player's mech can get embedded into buildings. In those cases, the collision code switches to handle the overlap and destroys the building if you're stuck inside it. Up until now, all enemies were treated the same way by simply being forced away from them, so when you collide with mechs or tanks you just bounce against them without any reaction. In a really bad scenario you can even get stuck with them blocking your escape path, which while amusing can be a bit frustrating.
I implemented some basic shoving code since an earlier problem of cars and pickups getting stuck in structures was solved. You should be able to drive into them and force them out of the way if you need to. This isn't a major thing, but I think it does matter in making enemy interactions feel a bit more natural.
Weapon tweaks
Increased knockback on plasma slashes
There are a few weapons in the game right now that are particularly unpopular, specifically the rotary cannon, the smartgun, the flamethrower, and the scattergun. I've been working on making them more satisfying to use, and for the rotary cannon in particular I've doubled the amount of bullets it fires, increased the fire rate, the damage, and lowered the ammo consumption. It has a way larger spread now, and I also added impact flashes to all bullets when they strike solid objects.
(Damage lowered to show impact flashes)
Additionally, since bullets have a maximum range before they hit the ground, I added bullet holes and smoke emitting from their impact points, so when you're going around the level you'll see these tiny craters peppered everywhere that you had an encounter:
Updated rotary cannon spraying
The smoothbore cannon has been overhauled so it now has some penetration. Shells go through cars without stopping, and it can also 1-hit kill enemies such as tanks and helicopters. I think people don't like the thermal projector very much since you can't really blind-fire with it, so I'll probably try increasing the spread area around the reticule so you can be less precise. Eventually I do want to have some missions where you're supposed to limit the amount of collateral damage, and that's where picking something more accurate like the regular autocannon would come into play.
One other thing I also recently fixed was missiles and rockets not flying over buildings when you're targeting helicopters. I forgot to actually add the altitude checking to the secondary weapon scripts, so they simply always had their altitude variable set to 0 unlike the primary weapons. All the code for switching collisions off to fly over buildings was already written in the objects, but they never actually used it. Oops.
I've begun making assets for a new set of areas in the game that take place in a series of large ruined cityscapes. I wanted to have an area for a while now that's ravaged by sandstorms and completely abandoned following some sort of disaster like a large asteroid impacting the area. I'm thinking you'll have to rescue some downed pilots here maybe, and also fight some very aggressive organic enemies. These are still a work in progress, so mind any visual errors.
Intel Log
Pretty much all of the graphics in the section right now are placeholders, and much needs to be redone and redesigned. Here's a few things I've been tinkering with the past month:
I wanted Val’s casual outfit to have a bit of an early 2000s flair — that classic tank-top and baggy-jeans combo that highlighted the midriff — though she'll probably only appear like this when she’s in the hangar. The quadtank has a nuclear battery, so during servicing orange anti-radiation coveralls are worn by engine technicians while taking the core out. I've thought about adding little minigames where you assist with maintenance in various ways, but the scope creep of the game has already been quite extreme.
This artwork is what the revised character files will look like too. It's scaled to fit the 960x540 resolution, and it's also a lot closer to my vision of what this character looks like in my head. I'll probably end up revising the in-game pop up portrait to look closer to it.
I do hope this style is appealing enough for the character art. I considered using dithering and more shading tones but I think I'm going to stick with this 2-3 tone cel-shaded style since it's already very time consuming to color. As shown on the previous post, in order to speed up the art creation process I've created several 3D models to use for pose and angle reference, though it's still a slow process; there's only so many corners you can cut before things start to look bad. If people are interested, I might do a deeper dive on how the artwork is made some other time.
Minotaur
I'll be honest — this version in the game right now with the manipulator arms just looks really bad. For a five day deadline I guess it's not the worst thing in the world since it gives people a better understanding of what they're fighting, but I still wish I could've done a better job. I cope with this by imagining it to be the prototype or some early desk model. This artwork below is too large to use in the game, but it's what a "production" version of it looks like.
East German hexapod crawlers during WWIII were getting sniped by these after riding across the highways of the post nuclear bombardment autobahn. You'll be seeing those very hexapods in the game eventually as well.
I think this next one could probably go for another pass, but here's a revised illustration of the chemical grubs. Their huge mouths aren't visible at this angle since it's underneath the "head" segment like that of a lobster or crab. I may make a separate illustration showing said underside.
Lastly, this is a somewhat crude design of what will become one of the weaker cannon fodder enemies in the game. It's far from finished — the suspension and turret need more work — but the overall shape is in I think. It'll probably be roughly the size of a car or van in-game and have just as little health. They'll mostly be added to fill some of the empty areas in certain levels without being as challenging to fight as MBTs or Mantises.
These have been requested ever since I added grenades to the game. I've procrastinated on implementing them since I thought they would be pretty underwhelming at the time, but now that there's some higher level enemies such as the mortar and LOSAT carriers, I've found these are incredibly useful in combat and actually change up the gameplay quite significantly. It's so much so I'm actually considering removing the smoke screen due to them, but I'll keep those in the game for now.
If you throw them too close to your mech your radar will be jammed for a short while, in addition to this new feature —
Another feature that's been hotly requested and promised for a long time now was a shield or active protection system for the player's mech. This APS module has a total of eight rounds that deplete every time it stops something from hitting you. At the time I recorded this GIF it wasn't implemented, but I've even added a little smoke trail emerging from the turret to imply the interceptor launched and hit the incoming projectile.
This is one of the few things in the game that I think you'll just purchase upgrades for over time versus buying separate pieces that you can swap out. At the start it'll only intercept missiles and mortar shells, but later on as the game progresses you might be able to have it intercept tank shells and maybe finally low caliber cannon bullets. You'll also be able to increase the capacity of rounds that you can carry, maybe with a maximum of 20. I'm considering having an ECM system also instead of an APS which would basically curve incoming enemy rockets rather than destroying them, in addition to preventing missile lock-ons and radio calls by command centers, but I'm not sure if it'll be useful enough yet.
If you've wrote in the comments that the game is now noticeably running a lot slower than the previous build (v.7.1), then I just want to say that I appreciate it greatly and I want you to keep me in check.
There's no way around it — the latest build runs poorly, and I'm not proud of it. I apologize for this, and I promise the next version will run a lot smoother. I know for the majority of people this might not be too apparent if you have a computer made in the last five years, but there's a sizable portion of players with older hardware such as myself where the change is quite clear. I would like people to continue to be able to play my game even on 15+ year old hardware and have it run smoothly. I don't think you should have to upgrade your PC to play it, as I certainly won't be doing that.
The new additions to the particle effects and destruction are surprisingly not what's been behind most of the performance dropping, but rather a lot of redundant code and unnecessary calculations by increasing the amount of building and foliage assets. I've spent a full week doing nothing but optimizing and cleaning up old code that I've neglected, and the next build of the game should be running way faster than ever before.
I'm even considering pushing out an early update with just the optimization changes, but I may wait until all ground enemies have been rewritten to use the new pathfinding system. I'm not entirely sure yet.
Will there be an endless mode in the game?
Definitely. Some kind of arena, or VR sim. There will also be a tutorial added at some point, since I noticed people aren't using the melee option very much, and some neglect to use the overdrive.
Will there be a level editor?
I don't want to promise anything, but I do think with the layout of the game and the way objects are placed in levels it's entirely possible. As far as I can tell, making an editor and basic UI won't be too difficult, mostly just time consuming with cataloguing all of the different objects in the game. The real challenge will most likely be figuring out how to save/load the levels and making sure everything carries over and reads correctly. Copying over all of the settings for every single object + background asset in a level and saving it to a file is going to be hard. I might need to recruit some help for that part.
Any chance for Steam workshop support?
Some people have told me they want to mod the game to be like VOTOMs or 86, and I'm honestly all for it. I would love for people to be able to add their own custom content and make their own little campaigns, but I'll need to really look into what implementing such a thing would entail. I assume some of the code in the game will need to be rewritten, and I'll probably have to overhaul a bunch of things so it's more compatible with outside changes. I can't promise this will be a feature when it launches as a result, but it's definitely something I want to see.
Any chance for multiplayer modes?
This one is admittedly quite low on my list of priorities, but I can't deny it would be a lot of fun. Honestly, if by some miracle I finish the game and it's a success, I'd probably hire someone else who could do it for me. AAA games tend to farm out their multiplayer modes to small studios as well; network code is not fun nor easy to write, and I consider it sort of its own separate field of gamedev, like being able to write shaders. You really need to know what you're doing, there's so little room for error and its an area that I have very little experience in.
That’s all for this progress report! There are other things I've been working on such as a crawler boss, more characters, a shop system, and more artwork of the designs in the game, but they’re not quite ready to show yet. I know these updates take a lot of time and things can get quiet between them, so I'm deeply grateful to everyone who continues to follow the project and look forward to the next release. Your support and feedback truly means a lot, so I hope the next update will be worth the wait. Thank you.
As a final GIF to end this post, here's a visualization of how the sprite-stacking in the game works:
P.S.