I'm developing a simulation in Java where objects move around in a 2D grid. Each cell in the grid can only be occupied by one cell, and the objects move by moving from one cell to another.
This is more theoretical than Java specific, but does anyone have ideas as to how I should approach collision handling with this grid? Are there any algorithms that people have used to handle collisions in a grid-like world?
Please note, I am not talking about collision detection as this is trivial since the objects move from one cell to another. I'm talking about collision handling, which can get extremely complex.
Ex: Object A wishes to move into the same location as Object B, and Object C wishes to move into Object B's current location. Since each cell can only contain one object, if Object A is able to move into its desired location, this will cause Object B to remain stationary and thus cause Object C to also remain stationary.
One can imagine that this could create an even longer chain of collisions that need handled.
Are there any algorithms or methods that people have used that can help with this? It is almost impossible to search for this problem without the search results being saturated with collision detection algorithms.
Edit: All objects move at the exact same time. I want to limit the number of objects that must remain stationary, so I prefer to handle objects with longer collision chains first (like Object B in this example).
According to discussion with OP the objects should be moved in a way maximising the number of all moved objects.
Objects with their references form a forest of trees. If an object A is referencing a cell occupied by B object we may say that B is a parent of A in the tree. So objects correspond to nodes and references correspond to edges in trees. There will be some empty cell in the root of each tree (so this is actually the case when empty cell corresponds to a node). Trees do not have common nodes.
Before moving forward we must admit that there may be situations with cycles. Like this:
[A] -> [B]
^ v or [A] <=> [B]
[D] <- [C]
Such cycles can be easily identified. Some object may be referencing cycle objects directly or indirectly also forming a tree. The cycle can happen only in the root of the tree.
Lets say we have built all trees. Now the question is How can we resolve collisions? keeping in mind that we want to maximise the number of moved nodes. Collisions correspond to a node having more than 1 child.
In cycle-root trees we do not have any other option except of moving only cycle objects while not moving any other object in the tree. It is clear that we cannot do another way.
In empty-cell-root tree first we have to decide which root child will be placed on the root empty cell. Then we will have a new empty cell where we will have to take the same decision. And so on so forth up until a leaf node. In order to maximise the number of moved nodes we have to take the longest chain from root to some leaf and move its nodes. All other nodes do not move. This can be easily done by traversing the tree with some recursive function and calculating the following function f for each node fleaf = 0 and fnode = MAX(fchild1, fchild2, ...) + 1. So aforementioned decision is choosing a child node with the biggest f.
*
/|\
A B C The optimal move path is * <- C <- E <- H
/ /|\
D E F G
/
H
Checking "ahead of time"/"next step" will lead to hard calculations and even explosions.
Instead, you can (in-parallel) use checking "which particle can move to this spot?" on each cell. For this, you need velocity map having a velocity vector in each cell. Then following that vector backwards, you spot a cell. If there is a particle, get it to the cell.
This way no collisions occur because only 1 action per cell is done. Just get closest cell from the negative velocity vector's end point.
This is somewhat tricky to compute since velocity may not land exactly on the center of cell. Needs probability(if it is very close to corners than center) for equality of motion / macro effects too.
So there will be a race condition on only the index of cells, and that will be tolerated by randomness of movement(or particle picking depending on the distance from center of cell)
On quantum physics, particles can leap otherside of a wall, stand still(even if it shouldn't) and do some other things that are not natural for classical physics. So if resolution is high, and velocity is not higher than map size, it should look natural, especially with the randomness when multiple cells compete to get a particle from another cell.
Multiple passes:
calcuate which cells need to gather from which cells,
calculate probabilites and then winning cells
winnings cells gather their particles from source cells in parallel.
(not recommended), if still there are non-picked particles with a velocity, then doing per-particle computation to move them (if their target cell is empty), should reduce stationary particles even further.
diffuse particle velocities on cells for a few times(using a 2D stencil) to be used in next iteration.(this one handles the complex collision calculation easily and in an embarrassingly parallel way, good for multithreading-gpgpu)(if particles can only go to closest neighbours, this also helps to know which one, even without any priority nor probability since each cell bents neighbouring cells velocities with the velocity diffusion)
check for Gauss-Seidel(https://en.wikipedia.org/wiki/Gauss%E2%80%93Seidel_method) method to solve many linear equations.
computation is done on cells instead of particles so the map borders will be implicity bullet-proof and calculation can be distributed equally among all cores.
Example:
particle A going down
particle B going right
they are in collision course
solve for velocity map equilibrium state(Gauss-Seidel)
now particle A's cell has a velocity to down+right
same as B
as if they were collided but they are still on their cells.
Moving them with their cells' velocities will make them look like they are in collision.
Related
I have a map with a hex-grid on it. I'm trying to construct "groupings" of Hexagons in order to create sub regions. I've got actually constructing the regions down, but the problem is the order in which each point of the 'edge polygon' is determined. What I'm looking for is an algorithm that, given a set of points, can (hopefully) construct the proper shape of the outer hexagons. What's important is the order of the points as when I pass that to Dynmap to construct a polygonal region, it's done by point order.
Shape-wise I assume it's a bit like convex hull, I believe, but wherein I don't want a new shape to be constructed with lesser points. As an example, below is what I'm getting and is wrong:
Below is the desired result, so to speak:
Thanks guys!
This might not be terribly efficient, but it's the first thing that comes to mind.
First, forget about the edges and just draw the red background color for every hexagon.
Now you only want to draw exterior edges. That is, edges that are not adjacent to another hexagon. Create an Edge class with proper equals/hashcode (which is agnostic of the ordering of the points). For each hexagon, generate all its edges and collect them into a map which counts each edge. Now draw only the edges that have been counted once.
Map<Edge,Integer> counts = new HashMap<>();
for (Hexagon hexagon : hexagons)
for (Edge edge : edges(hexagon))
counts.merge(edge, 1, (x,y) -> x+y);
counts.forEach((edge,count) -> { if (count == 1) draw(edge); });
There is probably a more efficient way, but this has the benefit of being simple, and it's probably fast enough for your use case.
I have an array with the coordinates of the center of small circles which have the same radius. I know how to find when the mouse is over a circle, but my array is big and I want the fastest way to calculate this operation.
Is there a way of finding if the mouse is over a circle without looping all the array for each movement of the mouse?
Initially, set up some 'zones' for quicker reference:
Separate the whole surface into a small number of rectangles that don't intersect.
For each of these rectangles, list all circles that are at least partially contained in it. (A circle may end up listed in multiple rectangles, but that's okay.)
Every time you want to check whether the mouse is over a circle, you won't have to go through the whole array of circles. Instead:
Figure out which rectangle you're in.
Check only the circles that are listed under that rectangle.
This looks like a problem of optimizing the boundary check for a large number of items. The approach of going linearly does not scale well for thousands of circles.
This is a good topic to read on the net. But first, without going there, I'll try to explain (as an exercise) what I would explore. I would create a binary tree and partition the space, then instead of using an array I would put the circle points in such a tree. Looking the tree elements that are closer to the actual X,Y location becomes a matter of doing a binary search on the tree. The you have the closest point as a result of that search and can check for collision on it. There is still more to be done to the algorithm, and further optimizations are needed. For example, how to check for more points and not only the final one? Potentially I need a tree for the X coordinate, and another for the Y coordinate, etc... But I would explore these ideas. I will come back to this post and expand my reply with an actual example and a more concrete solution.
What if you check the coordinates that are r(radius) distance from the mouse? Then you could narrow your search down in the array if it is ordered.
I'm current working on a pet project that allows a user to create a graph (vertices/edges) on screen in Java. I have the vertices implemented as JComponents but I have the edges implemented as Line2D's. When a user is moving the mouse across the canvas, if it is within a certain threshold of proximity to one of the edges (or Line2D's) that edge (the closest to the mouse) is highlighted.
My question deals with the way I implement which edge is closest to the mouse. Right now I have a mouselistener that detects movement; every time the mouse is moved my program cycles through all the lines (edges) and determines the closest one using Line2D's ptDistSeg() function. If this is within the threshold, then it is highlighted (using a thicker stroke in the paintcomponent).
To me this seems very inefficient as it has to recalculate all edge distances from the mouse every time it is moved. For the vertices this isn't a problem as the mouselisteners are associated with each vertex and therefore the vertices know when they need to handle the event. Unfortunately I can't do this with the edges as they are represented as Line2D's which can't implement a mouseListener.
So is there a more efficient way to find the closest edge or should I implement the edges a different way?
Thanks.
There's probably a better data structure for this out there somewhere, but one option would be to compute the axis-aligned bounding box of each edge to get one rectangle per edge, then to store all of these rectangles in a spatial data structure like an R-tree. R-trees support efficient queries of the form "give me all rectangles overlapping some point," so you could use that to filter down all the line segments to just those that might potentially hit the mouse point, then just test those.
The drawbacks here are that moving nodes around will require a lot of R-tree rebuilding due to the cost of changing the bounding boxes and that you'd need to find a good R-tree library, since R-trees aren't very easy to implement from scratch.
Hope this helps!
For the sake of argument, let's say I want to place a wall object (for simplicity, let's pretend it's just a 1x1 square) on a 2d grid which is 20x20. Let's say I have the object modeled out in coordinates between 0 and 1.
So, my question is, using openGL in the correct manner (I realize there are plenty of ways I could change the coordinates manually, but that doesn't edify me for the future), how do I place this object on the grid in the location (5,5)? Would it be related to the model matrix?
Yes, I think you have the right idea.
If your wall exists in model space from (0,0) to (1,1), and you want to position a particular instance of this wall at (5,5) through (6,6), than an appropriate thing to do would be to draw this wall with a Model Matrix that is translated by 5 units in the x and y direction.
You should not use the transformation matrices to place single primitives. Everytime you change a uniform (aka matrix) it's very likely the rasterizer pipline must be flushed, which is a sure performance killer.
As a general rule, to be efficient, a given transformation matrix should be applied to at least 100 primitives within a scene. So if you have some grid of tiles, it's better to either duplicate-translate them into a larger Vertex Array, or use instancing (if available).
I'm programming a Bomberman in Java following a tutorial (this is my first game).
The tutorial suggests the following code for detecting collisions.
for (int p=0; p<entities.size(); p++) {
for (int s=p+1; s<entities.size(); s++) {
Entity me = (Entity) entities.get(p);
Entity him = (Entity) entities.get(s);
if (me.collidesWith(him)) {
me.collidedWith(him);
him.collidedWith(me);
}
}
By now, entities is an array list containing the enemies and the player.
As I want to also detect the player collides with walls, should I put every single wall or bricks tile in the level into the entities arraylist? If so, isn't this algorithm very inefficient? These tiles aren't going to collide with other tiles, so I was thinking to manage game entities in different lists. What do you suggest? Is there a more efficient algorithm to do it?
Note: I already read other questions related to collisions in 2D games.
Thanks a lot.
I suggest reading this excellent article about how ghost movement and collision detection works in PacMan.
Then I would suggest logically modeling your Bomberman levels as a collection of tiles. Each tile represents a discrete position in your level, and it is not logically possible to ever be "between" tiles or occupying two tiles at the same time. Each tile can track what sort of terrain feature is currently on it, and whether or not it is a valid destination tile for the player (and the enemies, potentially with different rules for each if the enemies are allowed to traverse terrain that is normally impassable for the player).
Then you don't need a collision detection algorithm for every object in the world. When it comes time for an enemy to move, or when the user tries to move their character, all you have to do is check all the tiles that are adjacent to their current tile (4, or 8 max if you allow diagonal movement), see if each tile represents a valid movement direction, and block the movement if it is not in a valid direction.
And to answer your question, yes, iterating every object in the world on every position update will be very inefficient.
There is another way to use grids for collision system. I'm using more complex version of the Aroth's suggestion and using this to fix collision bugs.
Theoretically this system is the fastest(assuming you are doing this check if(Grid[x][y] ==true)) because it only uses a single Boolean check for each entity(the things that can move).
Note: In the above grid check example, I've used a 2 dimensional array of booleans that sets the coordinates of impassable grids to false.`
If you are not worried about physics like bouncing from a wall you can use this:
1- Divide the map into grids.
2- Making every entity only fill a tile would be better but not necessary.
3- Store the previous position or the grid of the entities.
4- Whenever an entity moves, before visually updating their location (also before
doing other calculations) check the grids they are in. If they are in grid
that is not empty or simply in a grid that they are not supposed to
be, return their position back to the previous position (which you have stored).
If you want to allow entities to move freely inside the grids(the grids are bigger than the minimum distance they can move) then you need to put them adjacent to the grids they've entered and they weren't supposed to. Otherwise just return them back to the previous grid.
If you want them to bounce from the wall you can still use this but I'm not sure how many features can be added to a collision system like this.
May I recommend my own project. But it's still wip.
https://github.com/YagaoDirac/Dirac-2d-collision-detection-for-games
It's based on quad-tree which handles sparse pretty well.
It supplies collision group. This conception is also used in both UE and Unity.
It support only circle vs circle and overlapping only for now(2022 feb 22).
I plan to make at least AABB, and collision which at least stop your pawn from leaving the map.
I may also provide another system based on fixed grid.