I am currently developing an indoor path-finding. I have multiple floors and different rooms. How will I be able to implement a* algorithm in the images of each floor using c# wpf?
I use spatial A* for the game I'm working on.
Spatial A* uses movement "cost" to work out the best route between two points. The cost mentions is supplied by an array. Usually a 2d array of number - float uint or whatever.
Moving through a square/cell at position x,y thus costs the number in that 2d array. EG costs[2,3] would be the cost of movement through the cell 2 cells across from the left and 3 down from the top of an imaginary grid projected onto your "room".
If the move is diagonal then there's also a multiplier to consider but that will be in whichever implementation you go with.
Hence you need a 2d costed array per floor.
You would need to somehow analyse your pictures and work out an appropriate size for a costed cell. This should match the smallest size of a significant piece of terrain in your floor.
You would then translate your picture into a costed array. You've not told us anywhere near enough to tell you specifically how to do that. Maybe that would have to be a manual process though.
Blocked cells get the max number, empty cells get 1. Depending on your requirements that might be that. Or alternatively you might have actors leaping tables and chairs etc.
You give the pathing algorithm start and target location (x,y), the appropriate costed array and it works out the cheapest route.
Related
TLDR: I need to average the values of all the surrounding coordinates for a specific coordinate for every coordinate in a 3D array
I am making a simplistic weather simulating program in Godot C# and have run into a few problems along the way.
One of the biggest problems I have encountered is performance, along with a few other things. To simulate air flow, I have a 3D array containing direction (Vector3 objects) for each coordinate. To simulate the airflow, I set each voxel’s direction to the average of the directions of the surrounding voxels.
Each voxel has a pressure value, and a voxel transfers pressure scaled by the magnitude (speed) of the wind direction to the voxels the wind direction is pointing to. For example if a voxel at (x,y,x) has a direction of (1,1,1), the voxel at (x+1,y+1,z+1) will have its pressure set to (x+1,y+1,z+1).pressure + direction.project(Vector3(x+1,y+1,z+1)).length() * (x,y,z).pressure
A voxel will also add Vector3’s pointing towards neighboring voxels if the pressure difference is not 0. The length of these vectors will be scaled by the pressure difference.
There are a bunch of other properties that need to be averaged up such as temperature, humidity, density, etc.
The real issue is iterating through a 3D array in a way that is fast, very fast. The method I am using at the moment has six nested for loops: Three for iterating over each voxel in the array, and three for iterating over the neighboring voxels within a range of -1 to 1 in each direction. I want to simulate a 16x16x16 area, but this algorithm requires me to do 16x16x16x27 iterations every game tick, rendering the application unplayable.
Is there a more efficient way of doing this?
First, make sure your nested loops are accessing memory in order of the memory's physical location. A 3D array is just a 1D array with some extra strides and offsets that occur behind the scenes. If your array is organized as voxels[x, y, z], then your final nested loop should be the z loop. If you prefer to access voxels in a different pattern, then you can populate your array differently to accommodate the other pattern, such as voxels[z, y, x].
Second, try to eliminate repeat access of array locations on different loops. If you access a location on one loop and you plan to access it again on the next, try saving the info to a local variable and test to see if it improves speed.
Third, see if you can reduce the number of calculations. For example, if you are calculating an average of all variables in a 3x3x3 grid and then incrementing the location and repeating, you can try saving a running sum. Then on the next loop subtract the 3x3 section you no longer need, add the new 3x3 section, and then divide to get your new average.
On a side note, maybe your example is truncated or conceptual, but it doesn't look like you are actually averaging the values of all surrounding voxels. Each voxel will be surrounded by a 3x3x3 array of voxels (so 26 adjacent voxels when excluding the center voxel). If we exclude corners, there are still 6 adjacent voxels.
I am trying to build a top down view spaceship game which has destructible parts. I need to simulate the process of depressurization in case of hull breach.
I have a tiled map which has the room partitioning code setup:
What I am trying to do is build some kind of a vector field which would determine the ways the air leaves depressurized room. So in case you would break the tile connecting the vacuum and the room (adjacent to both purple and green rooms), you'd end up with a vector map like this:
My idea is to implement some kind of scalar field (kind of similar to a potential field) to help determine the airflow (basically fill the grid with euclidean distances (taking obstacles into account) to a known zero-potential point and then calculate the vectors by taking into account all of the adjacent tiles with lower potential value that the current tile has:
However this method has a flaw to where the amount of force applied to a body in a certain point doesn't really take airflow bottlenecks and distance into account, so the force whould be the same in the tile next to vacuum tile as well as on the opposite end of the room.
Is there a better way to simulate such behavior or maybe a change to the algorithm I though of that would more or less realistically take distance and bottlenecks into account?
Algorithm upgrade ideas collected from comments:
(...) you want a realistic feeling of the "force" in this context, then it should be not based just on the distance, but rather, like you said, the airflow. You'd need to estimate it to some degree and note that it behaves similar to Kirchoff rule in electronics. Let's say the hole is small - then amount-of-air-sucked-per-second is small. The first nearest tile(s) must cover it, they lose X air per second. Their surrounding tiles also must conver it - they lose X air per second in total. And their neighbours.. and so on. That it works like Dijkstra distance but counting down.
Example: Assuming no walls, start with 16/sec at point-zero directing to hole in the ground, surrounding 8 tiles will get 2/sec directed to the point-zero tile. next layer of surrounding 12 tiles will get something like 1.33/sec and so on. Now alter that to i.e. (1) account for various initial hole sizes (2) various large no-pass-through obstacles (3) limitations in air flow due to small passages - which behave like new start points.
Another example (from the map in question): The tile that has a value of zero would have a value of, say, 1000 units/s. the ones below it would be 500/s each, the next one would be a 1000/s as well, the three connected to it would have 333/s each.
After that, we could base the coefficient for the vector on the difference of this scalar value and since it takes obstacles and distance into account, it would work more or less realistically.
Regarding point (3) above, imagine that instead of having only sure-100%-pass and nope-0%-wall you also have intermediate options. Instead of just a corridor and a wall you can also have i.e. broken window with 30% air pass. For example, at place on the map with distance [0] you've got the initial hole that generates flux 1000/sec. However at distance [2] there is a small air vent or a broken window with 30% air flow modifier. It means that it will limit the amount from incoming (2x500=1000) to 0.3x(2x500)=300/sec that will now flow further to the next areas. That will allow you to depressurize compartments with different speeds so the first few tiles will lose all air quickly and the rest of the deck will take some more time (unless the 30%-modifier window at point [2] breaks completely, etc).
I'd like to generate flat islands existing of multiple hexagons. So far I've been able to create hexagonal meshes with code, but can't figure out how to position them in groups, creating a randomly shaped island. (Any shape that's not a perfect circle, square etc.) I think I would need an algorithm, that places hexagon tiles next to multiple sides of an existing tile. If you can help me with an idea for an algorithm, then that would be great.
Are you looking for something like this?
Place 1 hexagon.
for i in (islandSize-1):
Scan all hexagons for open sides. Place open sides in a list named hexBorders
Choose a random index in hexBorders, attach a new hexagon there
That algorithm should give you a fairly roundish island, roughly centered on the original hex, because older hexes have more chances to get picked.
You can tune this shape by preferring either newer or older hexagons (e.g. you could include hexagon age in hexBorders, and adjust your random choice so it prefers younger hexes).
Recently I was also doing random map generator for tile based map and hit a wall while try to add more advanced features (in tile space) the realism of output was not good. I decided to create a 2D/3D image based map and then convert it to tile map. Still not finished with adding all the features I want but the result is already a magnitude better then before:
map generator
see my simple random map generator in C++. It is based on Diamond&Square algorithm with some tweaking to obtain island like maps.
conversion to tile-map
Simply map Cartesian pixel into your hexagonal grid layout. You can also compute the average of some area instead of using single pixel per cell/tile.
For 3D tile maps this will produce "voxel-ated" output so you need to add additional filtering see
How to procedurally generate tile map for some ideas.
Since is a pretty open ended question, this article by Red Blob Games about hexagonal data structures would be an excellent place to start. The author describes how you can use 2D arrays to store the hexagons, and how you can iterate through them.
Once you understand the relation of hexagons to one another you can start to iterate through them in interesting ways.
Probably the easiest way to generate an "island" would be with a SIR-type model, also known as an epidemic model. This is a model that is commonly used by researchers to simulate the spread of infectious disease, but I've found that you can also use it to generate pseudo-natural shapes (like an island!). SIR stands for Susceptible-Infectious-Recovered. Those are the three states of a "cell", or in this case hexagon. At any given step of the algorithm, an infected cell can infect a neighboring cell. Think about it like this: at the start of your algorithm, one hexagon is "infected" (land) and the rest are not (water). At each iteration of the algorithm, cells adjacent to an infected cell have a chance (say, 1 in 10) of being infected as well (turning into land). After many iterations, you'll find that the shape of the infected group of hexagons is pretty random looking, but they're all touching. For a grid-bsed example, here's some images I've uploaded to imgur. Pseudo-code for this algorithm is below.
cellsToDo = [originCell]
for 100 iterations:
for each cell in cellsToDo:
for each neighbor to the current cell:
if randomValueBetween(0, 10) == 1:
set the current cell as infected
add the current cell to the cellsToDo list
There are definitely other algorithms, but I'd start with learning how the hexagons are related to each other and can be stored.
I have a grid of 3D terrain, where each of the coordinate (x,y,z) of each grid are known. Now, I have a monotonously increasing/ decreasing line, which its start point is also known. I want to find the point where the terrain and the line meets. What is the algorithm to do it?
What I can think of is to store the coordinate of the 3D terrain in a nxn matrix. And then I would segmentize the line based on the grid in the terrain. I would then start with the grid that is the nearest to the line, and then try to compute whether that plane intersects with the line, if yes, then get the coordinate and exit. If no, then I would proceed to the next segment.
But is my algorithm the best, or the most optimum solution? Or is there any existing libraries that already do this?
A different approach would be to triangulate the terrain grid to produce a set of facets and then intersect the line with those.
Obviously you'd need to do some optimisations like only checking those facets that intersect the bounding box of the line. You can do a quite cheap/quick facet bounding box to line bounding box check which will discount most of the triangles in the terrain very quickly.
If you arrange your triangles in to an octree (as #sum1stolemyname suggested but for the points) then this checking can be done from the "top down" and you should be able to discount whole sections of the the terrain with a single calculation.
Not directly and optimisation, just a few hints:
If your grid is large, it might be worthwhile to build an octree from your terrain in order to quickly reduce the number of grid nodes you have to check your line against. This can be more efficient in a huge grid( like 512*512 ndoes) since only the leafnodes your ray is passing through have to be considered.
Additionally, the Octree can be used as a means to decide wich parts of your grid are visible and therefore have to be drawn, by checking which leave-nodes are in the viewing frustum.
There is a catch, though: building the Octree has to be done in advance, taking some time, and the tree is static. It can not be easyly modified after it has been constructes, since a modification in one node might affect several other nodes, not necessarily adjacent ones.
However, if you do not plan to modify your grid once it is created an octree will be helpful.
UPDATE
Now that i understand how you are planning to store your grid, i believe space partitioning will be an efficent way to find the nearest neighbour of the intersection line.
Finding the nearest Neighbour linearly has a runtime complexity of O(N), while space-partitioning appoaches have an average runtime complexity if O(log N).
If the terrain is not built via a nice function you will have to do a ray trace, i.e. traverse the line step by step in order to find an intersection. This procedure can take some time.
There are several parameters for the procedure. E.g. there is the offset you walk alogn the line in each step. If you take an offset too large, you might leave out some "heights" of your terrain and thus not get the correct intersection. If the offset is to small, it will slow down your procedure.
However, there is a nice trick to save time. It's described here resp. here. It uses some kind of optimization structure for the terrain, i.e. it builds several levels of details the following way: The finest level of detail is just the terrain itself. The next (coarser) level of detail contains just a forth of the number of original "pixels" in the terrain texture and combines 4 pixels into one, taking the maximum. The next level of detail is constructed analoguesly:
. . . .
... . ... .. .
....... .... .. .
........ => .... => .. => .
01234567 0246 04 0
1357 26 4
fine => => => => => coarse
If now the ray cast is performed, first of all, the coarser levels of detail are checked:
/
/
/.
.
.
.
If the ray already misses the coarse level of detail, no finer level has to be examined. That's just a very rough idea how the optimisation works. But it works quite well. Implementing it is quite a bunch of work, but the paper is a good help.
as my personal project i develop a game to which users can join at any time.
I have a tiled worldmap that is created from a simple Bitmap which has resources at random positions all over the map except for oceans.
When a player joins i want to create his starting position at a place that has at least 1 tile of each of the 4 resources in range (circle with a still to decide diameter, i think about 3-4 tiles) but no ocean tiles (Tile.Type != "ocean") and not conflicting with a field belonging to another player (Tile.Owner == null).
The map size can vary, currently it's 600x450 and it's implemented as a simple Array: Tile[][] with Tile.Resource being either null or having Tile.Resource.Type as a string of the resource name (as it's configurable by plaintext files to fit any scenery i want to put it in, so no built-in enums possible).
I currently have a loop that simple goes through every possible position, checks every field in range and counts the number of each resource field and discards it if there are none for one of them or if one of them belongs to a player or is an ocean field.
I would prefer if it finds a random position but thats not a requirement, mono-compatibility however is a requirement.
What would be the best way to implement an algorithm for that in C#?
Edit
The Area of players can and will increase/change and resources can be used up and may even appear randomly (=> "Your prospectors found a new goldmine") so pre-calculated positions will propably not work.
Instead of looping through all your positions, why don't you loop through all your resources? Your resources are likely to be more scant. Then pick one of the sets of resources that meet your clustering criterion.
You might consider simulated annealing ... it's not very complex to implement. You have a set of criteria with certain weight, and randomly "shake" the position at a certain "temperature" (the higher the temp, the greater the radius the position may randomly move within, from it's previous position), then when it "cools" you measure the value of the position based on the total weights and subtract negative things, like spawning too close to where they died, or next to other players, etc..., if the value is not within a certain range, you decrease the temperature, but "shake" the positions again, cool down, check weights and overall value, repeat until you get an acceptable solution.
Simulated annealing is used in map making, to label cities and features with maximum clarity, while staying within range and minimizing overlap. Since it's a heuristic approach there is no guarantee that there will be an optimal solution, so you keep "lowering the temp" and eventually just choose the best result.
Let's suppose that once your map is created you don't have to create a new one often.
Just add the following to each Tile and calculate them once after your map was generated:
-int NrOceanTiles
-int NrResourceA
-int ...
Now when you want to get a tile you can do it quite a bit faster:
IEnumerable<Tiles> goodTiles = tiles.Where(tile => tile.NrResourceA >= 1 && tile.NrResourceB >= 2);
Tile goodTile = goodTiles.ElementAt(randomI);
Predefined data would still be the best way forward.
As modifying the map size, and adding/losing resources would not happen as often, just update this data table when they do happen. Perhaps you could do the map/resource changes once per day, and have everything done in a daily database update.
In this way, finding a valid location would be far faster than any algorithm you implement to search all the tiles around it.
If the game isn't going to be designed for a huge number of players, most games implement "start spots" on the map. You'd hand-pick them and record the positions in your map somehow, probably similar to how you're implementing the map resources (i.e., on that spot, there exists an item you can pick up, but on top of the tile map).
Since the resources spawn at random, you could either not spawn resources on the start spots (which could be visible or not), or simply not spawn a player at a start spot on which there is a resource (or look within a 9-cell box to find a close alternate location).
Certainly you would want to hold the set of possible starting locations and update it as resources are created and consumed.
It seems like your best bet is to calculate open locations at map generation. Have your start location calculation function optionally take grid location and size or rectangle corners.
Have a list for Free locations and Occupied locations. Player occupies territory? Move resources in range to the Occupied list. Player gets crushed mercilessly? Move resources in range to the Free list. Resource eliminated? Delete any locations that used it in your Open/Occupied lists. Resource added? Recalculate using your effect radius to determine effected area. When your map area expands, just run the initial calculations on the new section of your grid + effect radius and add the new locations.
Then you just have to set the events up and pick a random Free value when someone joins.