简体   繁体   中英

Java more efficient array searching

I am coding a game using LibGdx and I have an array with all of my wall objects that the player can collide with. For those who don't use LibGdx, I am talking about LibGdx's Array class which provides the same functionality as an ArrayList but it's built with memory efficiency in mind. When I check for collision, I am having to go through every wall in the array and check for collision like this:

for(Wall  w : walls) {
    if(w.bounds().contains(player.bounds()) {
    // handle collision
    }
}

I realized this was inefficient because I am going through every wall even if that wall is off the current view of the map. Obviously, if I am checking for collision with walls currently in the camera's viewport (this means they are currently visible by the player) then there is no point in going through the whole array because the player can't collide with them until they come into view. I was thinking of making my game a bit more efficient by only checking for collision with walls close to the player. In my game, I have all of the walls snapped onto a grid with cells 32x32 px. I really don't know how I could create more efficient searching for collision. Could I use like a map of some sort which uses a vector2 position for its key and then look up the player's position and look through walls within a certain range from the player's position in the map? I am just really lost on how to have code that won't go through all 100+ walls in my game when there are only 10 current possible walls that the player could touch because of where it currently is. Does this make any sense? Could someone explain a good way to do something like this? Thanks so much.

There are lots of collision alghoritms out there, you will need to find one that suits your need.

One solution I can think of on the top of my head is:
Keep your wall list sorted on their coordinates. If you create a new wall, use insertion sort to resort your array. When you want to check for collisions, take the objects coordinates (in this case probably the player that is running) and do a binary search to find the closest wall to the player. Then calculate if the player and this wall collides. If the closest wall isn't causing a collision, you can be pretty confident that no other wall is as well.

Each wall is on one or more of these 32x32px grids. Let the coordinates of a grid be x and y. If a grid contains a wall, enter this into a

HashMap<CoordPair,Set<Wall>> xy2wall

To investigate where a location is in contact with a nearby wall, use the coordinates of the location to determine a small set of grid coordinates, fetch the set or sets of Walls mapped by these CoordPairs. I guess the Player.bounds() can provide a suitable set of coordinates.

If the 32x32 grid results in too many entries, you can always use a coarser grid.

I once came into the same realization that you have while developing a top down rpg. There are more walls than you can imagine in a top down rpg.

Here is how I solved it:

First: Segment the map into zones ie.) draw your map on paper or something and cut it up into parts.

Second: Record the pixel boundaries for each segmented section of the map.

Third: Check where your players location is with respect to the boundaries.

Finally: Only check the walls within those boundaries.

In a realm of infinite walls this is not any more efficient (speaking about Big O) but for all practical purposes this is effective in cutting down on lookup times


if (boundary1.contains(player1)) {

    for(Wall  w : Boundary1Walls) {
        if(w.bounds().contains(player.bounds()) {
            // handle collision
        }
    }
}
else if (boundary2.contains(player1)) {

    for (Wall  w : Boundary2Walls) {
        if(w.bounds().contains(player.bounds()) {
            // handle collision
        }
    }
}

.... Continue in this fashion

Take note... I did it like this before going to college for software development, so I did not make use of data structures such as BST which could be used to store walls with respect to their coordinates. Making your lookup time extremely fast.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM