I was going to check my map for the nearest x-object, using a floodfill. However, I can't seem to write one that makes sence.First I was going to go in spirals, but now I'm not so sure. I end up using a lot of lines, and way too many checks for silly things toeven be considered a valid solution. I want to floodfill in four directions, until I find the first of my x-objects (which would therefore be the nearest, right?).

The only things google came up with was redundant to my case, or gave me just as silly spaghetti-code.

//Start and end flipped since we get the path backwards by traversing the parents of the goal nodeDijkstraDatastart = getData(level.getNode(destX, destY));DijkstraDataend = getData(level.getNode(startX, startY));

You can ignore the cost variable and simply use a normal list for the open list. A note about the lastOpened and lastClosed variables: These could've been booleans marking if the node has been visited/closed, but that will force you to reset all tiles to false/false after each job, which is obviously really slow if you have a large map (1024x1024 maps = >1 million nodes for example). By using an int instead, you can just increase the jobID before each job, and all nodes not having the same ID haven't been visited/closed yet. You still have to reset the whole map every 2^32 = 4294967296th job though xD. A similar optimization could be used for the open list. Instead of calling clear() on it which nulls out all elements in the backing object[] you can just set the size to 0 similar to how ByteBuffer.clear() works to.

The thing is that I know what I'm looking for, but not where it is. I have no such thing as a destination when the algorithm starts, so it just has to spread outwards until something that'll do is encountered.

I must be missing something completely here though. I definitely see a destX/destY variable in the Job. I'm not really interrested in the pathfinding part of this, just finding the coords of the nearest X (only knowing what should be on the tile I'm looking for, but not where it is).

Oh, I just realized I can just take the neighbors of neighbors until I find my tile!

However, how do I avoid searching in just one direction? If I always add all the neighbors to the open list, and then look for neighbors to the open list from the top, then I will only go in one direction. How do I avoid that?

You'll go in one direction til you can't any more, then you'll "bounce" over to another edge of your filled region and start from there. What your filled area looks like depends on how you store your open list. Check out the wikipedia page on floodfill for some visual comparisons of how the fill progresses depending on the data structure you use. If you use a queue for your open list, you'll get a nice diamond-shaped fill, while the stack gives you more of a scan behavior. You can also choose randomly, though that will cost you some overhead.

Dijkstra is like flood fill except you record whole paths, not just nodes, and you stop when you get to your destination. If you're looking to visit every node, you don't keep paths, so you get floodfill.

You'll go in one direction til you can't any more, then you'll "bounce" over to another edge of your filled region and start from there. What your filled area looks like depends on how you store your open list. Check out the wikipedia page on floodfill for some visual comparisons of how the fill progresses depending on the data structure you use. If you use a queue for your open list, you'll get a nice diamond-shaped fill, while the stack gives you more of a scan behavior. You can also choose randomly, though that will cost you some overhead.

Dijkstra is like flood fill except you record whole paths, not just nodes, and you stop when you get to your destination. If you're looking to visit every node, you don't keep paths, so you get floodfill.

My area is infinite though How would I code-wise go about making the diamond?

Oh, I just realized I can just take the neighbors of neighbors until I find my tile!

However, how do I avoid searching in just one direction? If I always add all the neighbors to the open list, and then look for neighbors to the open list from the top, then I will only go in one direction. How do I avoid that?

I don't see what you mean. Taking the neighbors of neighbors should go in all directions.

Oh, I just realized I can just take the neighbors of neighbors until I find my tile!

However, how do I avoid searching in just one direction? If I always add all the neighbors to the open list, and then look for neighbors to the open list from the top, then I will only go in one direction. How do I avoid that?

I don't see what you mean. Taking the neighbors of neighbors should go in all directions.

The map is definitely too big to check every single tile. I only want to search within.. let's say a 100 tile radius of the starting point.

I'm having some trouble here, implementing it. In my A*, I have nodes in a map (2D array) equal to the size of the map I'm searching. It's a double/replicate of it, holding just the values I need.

With this dimaond-shaped-floodfill, I'm looking for a Tile that has a specific type of object on it/in the class. Therefore, I can't just use nodes because they need to know both what is on their representative Tile, and where they belong in the map (coordinates). I wanted to just use my actual TileMap, and ignore the overhead, but the tiles themselves (in my actual map) don't know their position.

/** * Finds the location of the tile that hosts nearest WorldObject of a given type. * * @param obj The object type we're looking for (not the actual object - they just need to be of the same type) * @param sx The source x * @param sy The source y */publicPointfindTile(WorldObjectobj, intsx, intsy) {closed.clear(); // Initial clear of both lists for safetyopen.clear();open.add(map.getTile(sx, sy)); // Add the starting point

//XXX: Add a check for how far into the search we are (loop).. How big of an area are we currently covering? Should we stop?

Tilecurrent = map.getTile(?int?, ?int?); //open.get(open.size()); // Getting the last element in the queueopen.remove(current);closed.add(current);

Have a max count of nodes to search, decrement it every time you search a node, quit when it hits zero. If you have any obstacles in the way, then the size of your search area is indeterminate. If you don't have obstacles, then let me reiterate how wrong this algorithm is.

Have a max count of nodes to search, decrement it every time you search a node, quit when it hits zero. If you have any obstacles in the way, then the size of your search area is indeterminate. If you don't have obstacles, then let me reiterate how wrong this algorithm is.

Take the manhattan distance ("straight line" without diagonals) to all the visible trees. Pathfind to the nearest one, and remove from the list of nearby trees anything with a manhattan distance greater than that path's length. Repeat the process for remaining trees in the list, then out of the ones you have paths for, take the one with the shortest path.

Large obstacles present some corner cases for this algorithm, but you can fudge the calculated distance if you find that obstacles impinge on your straight line between your start position and the destination.

Take the manhattan distance ("straight line" without diagonals) to all the visible trees. Pathfind to the nearest one, and remove from the list of nearby trees anything with a manhattan distance greater than that path's length. Repeat the process for remaining trees in the list, then out of the ones you have paths for, take the one with the shortest path.

Large obstacles present some corner cases for this algorithm, but you can fudge the calculated distance if you find that obstacles impinge on your straight line between your start position and the destination.

I can't just do that. I have lots of lakes that would screw this up. Also, my entities work even when not rendered, so I would have to take all trees in the level, which could be thousands.

"Visible" here refers to some arbitrarily determined set based on your current position, not real actual visibility as rendering is concerned. You don't need to render for this, nor do you need to select every tree. Just all the trees in some reasonably sized rectangle.

Also, with lots of obstacles, flood fill is virtually guaranteed to end up with pathological cases, such as taking a very loooong trip through a narrow "corridor". Using a queue might mitigate this, but I bet I could still cook up a way to break it even with plausible map topology.

"Visible" here refers to some arbitrarily determined set based on your current position, not real actual visibility as rendering is concerned. You don't need to render for this, nor do you need to select every tree. Just all the trees in some reasonably sized rectangle.

Also, with lots of obstacles, flood fill is virtually guaranteed to end up with pathological cases, such as taking a very loooong trip through a narrow "corridor". Using a queue might mitigate this, but I bet I could still cook up a way to break it even with plausible map topology.

Tried it now, and making one guys visible range 10 in all directions causes me to loop through 400 tiles. If those are all trees, or even half, I'dhave to make 200 patfinding calls to see which is closer. With many trees and many guys, that causes trouble - sadly.

I have a feeling making a spiral around the guy until a tree is hit, can improve both visible distance, and speed with many trees around.

You do not make 200 pathfinding calls, you sort the trees by distance, start with the closest one, then discard anything with a straight-line distance longer than the shortest path you have. If your tree density is 50%, then you start with a smaller rectangle, like, oh, looking for trees right next to your position, then widen it as needed. Using a spiral is certainly a good way to go there, since it'll find trees in sorted order automatically -- not quite perfectly, but close enough.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org