1
\$\begingroup\$

I'd like to explain this problem with a screenshot from a released game, DROD: Gunthro's Epic Blunder, by Caravel Games.

enter image description here

The game is turn-based and tile-based.

I'm trying to create something very similar (a clone of the game), and I've got most of the fundamentals done, but I'm having trouble implementing pathfinding.

Look at the screenshot. The guys in yellow are friendly, and want to kill the roaches. Every turn, every guy in yellow pathfinds to the closest roach, and every roach pathfinds to the closest guy in yellow.

By closest I mean the target with the shortest path, not a simple distance calculation.

All of this without any kind of slowdown when loading the level or when passing turns. And all of the entities change position every turn. Also (not shown in screenshot), there can be doors that open and close and change the level's layout.

Impressive.


I've tried implementing pathfinding in my clone.

First attempt was making every roach find a path to a yellow guy every turn, using a breadth-first search algorithm. Obviously incredibly slow with more than a single roach, and would get exponentially slower with more than a single yellow guy.

Second attempt was mas making every yellow guy generate a pathmap (still breadth-first search) every time he moved. Worked perfectly with multiple roaches and a single yellow guy, but adding more yellow guys made the game slow and unplayable.

Last attempt was implementing JPS (jump point search). Every entity would individually calculate a path to its target. Fast, but with a limited number of entities. Having less than half the entities in the screenshot would make the game slow. And also, I had to get the "closest" enemy by calculating distance, not shortest path.


I've asked on the DROD forums how they did it, and a user replied that it was breadth-first search. The game is open source, and I took a look at the source code, but it's C++ (I'm using C#) and I found it confusing.

I don't know how to do it. Every approach I tried isn't good enough. And I believe that DROD generates global pathmaps, somehow, but I can't understand how every entity find the best individual path to other entities that move every turn.

What's the trick?


This is a reply I just got on the DROD forums:

Without having looked at the code I'd wager it's two (or so) pathmaps for the whole room:

One to the nearest enemy, and one to the nearest friendly for every tile.

There's no need to make a separate pathmap for every entity when the overall goal is "move towards nearest enemy/friendly"... just mark every tile with the number of moves it takes to the nearest target and have the entity chose the move that takes it to the tile with the lowest number.

To be honest, I don't understand it that well.

\$\endgroup\$
2
  • \$\begingroup\$ In this case you don't need to calculate the path for every unit, just for every group of units, e.g. determine one "leader" that all the other units near him will follow. As soon as the target (this can be the leader or a enemy) is in sight, you don't even need path finding at all, just very simple "move towards". \$\endgroup\$
    – API-Beast
    Jun 10, 2012 at 14:46
  • \$\begingroup\$ I think this would be fairly more complex than understanding how the original game does it. Having a lot of friendlies and a lot of enemies can make group/leader detection pretty hard in my opinion. Also, the original game doesn't do any of this, and still runs without any slowdown. I got a reply on their forums, but I couldn't understand it - I added it in the main question. I've been told that DROD uses two separate pathmaps for the whole room, but I don't get how that could work if there are multiple friendlies and enemies. Paths are constantly changing, after all... \$\endgroup\$ Jun 10, 2012 at 14:52

2 Answers 2

2
\$\begingroup\$

For this situation I would likely try pathfinding with potential fields. Your game would have two such fields, one for friendlies and one for enemies. Which is likely what the forum answer was talking about.

Each field will have tiles just like you game board. Each one of these tiles will point toward the nearest friend or enemy to that tile. Visualized in paint:

crappy paint potential field

You'd use diagonals I suppose, but I didn't want to draw those :)

For obstacles you'd have rules like never point directly into a wall or maybe do some simple path finding in those cases. You'd have to fiddle with it to see what it needs.

Alternatively, instead of vectors to point the way, you can do as the forum people suggested and just put the number of moves required to get to the nearest entity, but it pretty much equates to the same thing.

\$\endgroup\$
1
0
\$\begingroup\$

There's no trick. It's just a simple problem to solve. Every character just runs a breadth-first search, starting from their own position, until they find what they're looking for. Since the map is so densely populated, the search will never have to run for long before finding a target, so it's cheap. Effective use of data structures helps too.

One way in which you can make searches like these cheaper is to calculate influence maps and/or potential fields in the level for each unit type. Then pathfinding can be easily done just by moving from each tile to the most attractive tile next to it. More information here: Using Potential Fields in a Real-time Strategy Game Scenario (Tutorial).

But if you're having specific problems, you will need to state clearly what exactly you're trying (probably showing some code) and in what way it doesn't work.

\$\endgroup\$
3
  • \$\begingroup\$ I tried doing this, but it's slow - consider I have only 100 roaches and a player in the level: every turn, every roach refreshes its nodes (2D array as big as the level, containing G, H and F scores for every tile - every score is reset to 0), then starts expanding until it finds the player. It creates a very noticeable slowdown. And 100 roaches is not that many either. Also, considering the example I just made, the map is not always densely populated - most of the times there only is one player and an enormous amount of monsters. \$\endgroup\$ Jun 10, 2012 at 14:46
  • \$\begingroup\$ I know what the procedure is - the issue is that it doesn't necessarily have to be that slow. Breadth first search over a fairly small structure is cheap. And why are you using A* for a breadth-first search? I will add one suggestion into my answer though. \$\endgroup\$
    – Kylotan
    Jun 10, 2012 at 15:23
  • \$\begingroup\$ I wasn't using A* for breadth-first, sorry for the confusion, I just had the H value and the F value because I used the same node structure for A* and JPS, but I wasn't considering them in the search. \$\endgroup\$ Jun 10, 2012 at 15:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .