Finding the nearest polygon out of a list of polygons seems to be quite a challenge on performance, due to lack of optimization.
Consider the following image:
I'll give the concept behind this. The "purple" pointer under the mouse is an entity and each blue blob is a polygon. The red ring denotes the nearest polygon, while the pink line denotes the nearest line of that polygon.
Here is the system:
- Entity: performs a loop through ALL polygons.
- Polygon Loop: loops through ALL vertices of the polygon in the current iteration.
- Vertex Loop: if the distance between the entity and the current vertex is lower than the distance between the entity and the previous vertex, save the current vertex and the ID of the polygon the vertex belongs to.
- Once all loops are finished, take the nearest polygon/vertex and get the vertex of the polygon to the left and right of the nearest vertex.
- Check the left and right vertices to see which is closest to the nearest vertex. Doing so, finds the nearest line of collision to the entity.
In short, I loop through all polygons and all vertexes of each polygon to find the nearest collision line of the nearest polygon to the entity. This allows me to handle terrain, collisions, gravity, etc.
The reason for this, is that the polygons can have any shape. Since this is the case, I have to dynamically find the nearest polygon based off of the vertex of each polygon to the entity. It's costly, but gets the job done...
I know this method is inefficient, but how could I go about making this system better? Or using an entirely different and existing system that is better?
The partial code below does not include finding the nearest line. That part I am not worried about as it's very easy/fast to do.
// srce -> list(1d-array) of polygon object-IDs;
// updated -> polygon vertex array of each polygon object;
// polygon -> current iteration in the srce list(1d-array);
// with( ... ) -> current polygon of the current iteration;
// vertex -> the current vertex in the iteration of vertices of the polygon;
// srcex and srcey -> entity x,y position;
// xvertex -> x-position of the current vertex in the iteration;
// yvertex -> x-position of the current vertex in the iteration;
// nearest* vars -> store the nearest vertex/polygon data;
// size -> total vertexes in the nearest polygon;
// NOTE: Each vertex takes up 2 indexes in the list(1d-array);
// Iterate through all polygon objects;
repeat( ds_list_size( srce ) ) {
with( ds_list_find_value( srce , polygon ) ) {
vertex = 0;
// Iterate through the polygon's vertices;
repeat( ds_list_size( updated ) div 2 ) {
xvertex = ds_list_find_value( updated , vertex );
yvertex = ds_list_find_value( updated , vertex + 1 );
vertex_dist = point_distance( srcex , srcey , xvertex , yvertex );
// Here we get the current nearest point IF it's closer than the previous;
// Here -1 means there is current NO nearest vertex;
if ( vertex_dist < nearest_dist || nearest_dist == -1 ) {
// If this vertex is closer than the previous, store it's data;
nearest_dist = vertex_dist;
nearestx = xvertex;
nearesty = yvertex;
// This one is confusing: nearestv stores the INDEX of the vertex in...
// ... the array of vertices, this is a reference point for the vertex;
nearestv = vertex;
nearest_polygon = id;
size = ds_list_size( id );
}
vertex += 2;
}
}
polygon += 1;
}