Feature restored: Aeox and Shaedu Attacking

As is usually the case with a major code overhaul, I disabled many features so I could test stuff out and get it working with each existing system, one at a time. One of the final things I need to restore is the summon AI for targeting and attacking enemies. Their behavior is slightly different from monsters, because they never move to reach another target, but it uses the same code at least.

attacks1

So far, Aeox attacks properly (now with 8-way attacking!) and Shaedu also aims and hits properly. There’s still an issue with her firing trick shots at moving targets between obstacles (like through a doorway if the monster walks past it), which probably has to do with her search interval and vision check code. Something to fix tomorrow, along with the Bloodfire attacks.

Pathfinding Exhibition

I’ve gotten things to a state where it’s good enough that I want to show it off.  This video shows all the features I’ve put in place, and what happens when they’re removed. It’s kind of like that elementary school science experiment where you bake several batches of cookies and leave out a different ingredient each time, to see the results.

The pathfinding AI is a collection of features:

  1. Gauntlet Movement: Monsters move towards the summoner. They will slide along walls with diagonal movement, but can’t navigate around corners and will get stuck easily.
  2. Sidestepping: Even without any maze solving code, the Gauntlet movement can be improved a bit. When monsters sense that they have been blockaded for about one second, they randomly try moving in a diagonal towards the summoner, which helps them get around walls.
  3. Raw Pathfinding: A maze solving algorithm points the monsters towards the closest viable path to the summoner. If the monster has a direct, visible path to the summoner, it switches back to Gauntlet movement, because that tends to be faster than using the path. Notice how the rats on the right side get stuck because they get to the doorway at precisely the same time. I call this the Three Stooges Effect, and I came up with a pretty cool solution for it:
  4. Traffic Fields: A traffic director data type watches the monster movement, and adds vectors to each floor tile.  If a monster tries to walk on a tile that has a vector pointing in the opposite direction, it gets blockaded just like a wall. This way, whoever gets there first sets up the flow of traffic for that particular tile. Each vector times out after a second or so of inactivity, which lets the patiently waiting rats through. Look at the rats on the right now–they are behaving so orderly!  Even though both rats reach the doorway at the same time, the top one got evaluated first, got its movement vector placed there, and successfully repelled the lower rat (and all his friends).  The visualization lets you see the tile vectors as arrows.
  5. Creature Weight: The numbers you see on each tile in the Traffic Field visualization are the “weights” of each tile. These are used in the maze solving algorithm. They actually represent the number of steps it takes to get to that particular tile from the point of origin: in this case, the summoner. The fastest route is easily generated by starting at the monster’s location, and just picking the lowest number from the eight available directions.  With creature weight taken into account, any tile occupied by a creature gets its weight bumped up by a couple points, or 5 points if the creature is blockaded. Notice how the rats don’t all take the same path: once a few have started using a particular route, the weight to cross it is now larger than another route. Not only does this decrease the time it takes for a large crowd to solve the maze, but it also has the great side effect of flanking.
  6. Uncrowding: This last one is subtle, but makes a difference. When a monster has been blocked for more than a couple full seconds, it picks a random direction to move which is roughly in the opposite direction they were originally trying to go. This breaks up congestion and slightly improves the maze solving time.

At this point, the pathfinding AI is good enough to leave alone for a while. I just wanted to get it to a point where the monsters don’t get stuck, and you won’t be able to cheese them (at least not easily).

Pathfinding AI Improved

So many rats, it's almost unbelievable
So many rats, it’s almost unbelievable

Pathfinding on the pixel level works great now.

As you can see in the above screenshot, the rats will find their way to you really fast. It’s so much better than the tile based pathing that it’ll take some rebalancing. If an interior room full of fast moving monsters suddenly gets opened, they’ll swarm you really fast if they have a path to you. One archer or knight is not going to be able to take them out. AOE attacks from the bomber will be a bit more effective though, and maybe even necessary if you face something like the above scenario.

A new dimension in balancing will also be the monster AI. The red rats above are using omniscient pathing, meaning they have a psychic awareness of the summoner’s location, and will find the fastest route there. This type of behavior might need to be used sparingly, because it’ll get overwhelming. A lot of lower level mobs will wander aimlessly, use Gauntlet style movement, or need vision to be aggroed. Boss creatures can also affect the AI of the lower level mobs, for example granting them awareness of the player’s position.

We’ve Achieved High Resolution

I could post a screenshot, but you wouldn’t be able to tell the difference… but today was entirely focused on getting ready for the move to HD. I have decoupled the tile pixel dimensions from their world dimensions. With the change of a single line, I can set the world up to use tiles of any size (32×32, 24×24, or 64×64 like Escape Goat 2). The move speeds and hitbox dimensions are calculated independently of this.

I still need to figure out a good native grid size: how many tiles are visible on screen at once. Soulcaster II had a visible size of 22×16 tiles. I’ve currently got the tiles scaled to 40×40 pixels, which at 1280×720 gives me a maximum visible grid of 31×17.  Here’s what that looks like:

maxsize_31x17Right now that seems a bit larger than I want. Bringing in the width a bit, here’s 29×17:

29x17A bit more manageable, and I think the aspect ratio is a little nicer.  Narrowing it a bit more, to 27×17:

27x17The beauty of this game being procedurally generated is that I don’t have to decide on a visible tile size (default room size) right now. I can make patterns of a variety of sizes, and have the game arrange them in larger rooms. Since the game will have scrolling in two dimensions, there will be some enormous rooms, where you can’t see all the enemies and obstacles at once.  The engine also supports variable room sizes, and will center the room in the viewport with optional zooming. (Escape Goat 2 did this, and would zoom in up to 25% larger than default size).