0
\$\begingroup\$

We're developing an isometric game that so far has had a single ground level (y = 0) for the avatar to walk on. Pathfinding for this can be solved with a relatively simple 2D AStar tile map.

We're now looking to add objects in the world that can elevate the avatar. There will be overlapping walkable areas, thus creating a problem of pathfinding in 3D space. These objects are distributed sparsely in the room, so I want to avoid keeping an entire 3D map of the room for a 3D AStar implementation. I've attached screenshots to illustrate.

the avatar is able to walk on top of the tables

What is the best way to accomplish this?

\$\endgroup\$
  • \$\begingroup\$ If the characters can never walk underneath these objects, then you can still use a 2D A* implementation. Just elevate the character by the height of your object. Add a field in each tile, y, and modify your algorithm to only produce a positive result when the y-difference between two tiles is <= 1. \$\endgroup\$ – Thebluefish Feb 2 '15 at 19:01
  • \$\begingroup\$ Thanks for the response. There will be overlapping areas, so the y-offset approach wont work. I've made the edit to the original question. \$\endgroup\$ – Jimmy Xu Feb 2 '15 at 19:03
2
\$\begingroup\$

It depends. If the elevated surfaces could lead to other rooms, it could get very complicated unless the A* optimization function you are running is tailored with information specific to that room layout, it may need to search every possible path (like BFS).

How to handle this issue:

Complexity:

You need a meta graph that represents rooms; i.e to get from room A to room D I go through A => E => B => D. Each room has a few exit nodes, so instead of searching the whole map, I first search the meta graph that represents each room as a single node and then inside each room, I only need to search from the entrance to the closest relevant exit.

Sparsity:

To represent the sparse 3d matrix of surfaces, use a hash table, every elevated surface in a room will have a vector key position in the hash (x, y, z). Each surface will be able to access any other surface in (x +/- 1, y +/- 1, z +/-1). Since you separated the world into rooms or sections, the A* graph hash for each room will be reasonably sized.

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

As long as there are no overlapping walkable areas, you can keep 2D A*. You just need to add a height info to tiles and make a rule, that character can walk from tile to tile if height difference is less than X.

If there are overlapping areas you need to go kind of 3D. You can get away with several separate layers for your room, where each layer contains info about walkable areas on given height. Then to use A* you need to check not only direct neighbors of the tile, but also tiles in +/-1 layer above/below.

\$\endgroup\$
  • \$\begingroup\$ There will be overlaping walkable areas \$\endgroup\$ – Jimmy Xu Feb 2 '15 at 19:01
  • \$\begingroup\$ Thanks for the response, Krom. This is an idea I've been exploring, but my worry is that the inclusion of Y-layers will dramatically decrease performance and increase memory profile. Can you suggest a reference for me to check out that implements this in an efficient manner? \$\endgroup\$ – Jimmy Xu Feb 2 '15 at 19:08
  • \$\begingroup\$ @JimmyXu: We are talking about small rooms, with 32x32 tiles and 8 layers at most, right? Performance and memory hit is going to be minimal. \$\endgroup\$ – Kromster Feb 2 '15 at 19:09
  • \$\begingroup\$ @JimmyXu: There are a multitude of ways to tune the performance of A-star. I have implemented A-star with Landmarks and Triangle-inequality on a 750 hexes x 450 hexes terrain hex grid (so also 3D though not overlapping, with > 325,000 nodes) that calculates paths in less than 100ms on (one CPU of) an Intel i7. The cost of this performance is 3 seconds at start-up on 6 of 8 processors to pre-calculate Landmark distances. Check my profile for a link to an old version of the code. \$\endgroup\$ – Pieter Geerkens Feb 3 '15 at 3:20
  • \$\begingroup\$ You can also prepocess the map to a connectivity graph and use that, you can even do it at runtime on such a small map. \$\endgroup\$ – user29244 Feb 4 '15 at 5:10
0
\$\begingroup\$

I can suggest to transform your "2d space with heigth" into a graph. Them use an A* on that graph . Example each walkable tile become a graph "node", and then add an "arc" for each "adiacent tiles" (even at different heigths)

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

I would prefer to reuse the data structure you already have. So basically a 2D grid that is the floor with a bunch of entities that are put over it.

A* actually works over a graph, so the trick is to make a decent abstract programming interface (API) for a graph. 2D or 3D grid A* is a trick by implicitly converting a grid into a graph with the shape of a lattice graph, where the nodes correspond to the cases of the grid and where the edges connect neighbouring cases of that grid.

In your modified graph,

  • Like a lattice graph, each case of the floor is a node, connected to its four neighbours "by default".
  • However, each entity/object is also a node, connected to neighbour entities provided they have sufficient height so a character can walk across.
  • A case or entity with another entity stacked right on top of it have its connections removed (because you cannot walk onto it since you cannot go through the entity stacked right over it). A node without any connections is a pointless as no node on the graph in the computation of A*, so you can keep it alive (and possibly reconnect it later).
  • ... (Depending on your game rules, you may wish to alter this interface, like adding weight on edges, ... )

Now, all you have to do is to implement A*, but not by following regular 2D or 3D neighbours to travel, but by following connections (a.k.a edges). Two nodes are neighbours if and only if they are connected. You may wish to learn how to do A* on a general graph structure.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.