6
\$\begingroup\$

I have the following code that works just fine for collision detection. The only problem is its size and its performance. I'm trying to do it and many other things 60 times per second, which doesn't work out very well. Is there any way to condense it as it's much the same stuff over and over again?

for(int x=0; x<40; x++) {
     for(int y=0; y<28; y++) {
        if(tiles[x][y]==0) {
            if(keyManager.up) {
                Rectangle player = new Rectangle(you.getX(), you.getY()-1, 10, 10), tile = new Rectangle(x*25, y*25, 25, 25);
                if(player.intersects(tile)) {
                    return;
                }
                if(x==39 && y==27) {
                    you.setY(you.getY()-1);
                }
            } if(keyManager.down) {
                Rectangle player = new Rectangle(you.getX(), you.getY()+1, 10, 10), tile = new Rectangle(x*25, y*25, 25, 25);
                if(player.intersects(tile)) {
                    return;
                }
                if(x==39 && y==27) {
                    you.setY(you.getY()+1);
                }
            } if(keyManager.left) {
                Rectangle player = new Rectangle(you.getX()-1, you.getY(), 10, 10), tile = new Rectangle(x*25, y*25, 25, 25);
                if(player.intersects(tile)) {
                    return;
                }
                if(x==39 && y==27) {
                    you.setX(you.getX()-1);
                }
            } if(keyManager.right) {
                Rectangle player = new Rectangle(you.getX()+1, you.getY(), 10, 10), tile = new Rectangle(x*25, y*25, 25, 25);
                if(player.intersects(tile)) {
                    return;
                }
                if(x==39 && y==27) {
                    you.setX(you.getX()+1);
                }
            }
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ why is the size a problem? can you show the intersects function? \$\endgroup\$ – depperm May 21 '18 at 12:09
  • \$\begingroup\$ @depperm the intersects method is something built into the Rectangle class. \$\endgroup\$ – TheJavaNub May 21 '18 at 12:10
7
\$\begingroup\$

You are creating a new Player and Tile every time this code executes. That is likely your performance hit. Try moving the existing player rather than creating a new one in a new location.

Does performance slow down further the longer the game runs? This is because your objects are piling up.

For further reading I recommend looking at AABB Collision Detection and Quad Trees.

\$\endgroup\$
4
\$\begingroup\$

You seem to have a player that changes coordinates when keys are pressed and tiles that are stationary.

On each "tick" (~60/second), for each of the tiles (~1000) that is 0 (tiles[x][y]==0) you're creating a Player rectangle, a Tile rectangle and checking whether these intersect or not.

How many Player rectangles should in fact be created? Since the Player moves once per tick, you should have one Player rectangle created per tick.

How many tile rectangles should be created? On first glance, you could get away with creating all of the tile rectangles on game start (since they don't change position between ticks). An even better approach is to not create any tile rectangles, but based on the position of the player determine which tiles he is intersecting.

Observation 1: since the tiles are well behaved - first tile on first row goes from 0 to 25, second tile from 25 to 50, etc, you can determine easily determine which tile a random point belongs to.

Observation 2: since the player is a square of side length 10 and the tiles are squares of side length 25 (bigger), the player can intersect at most 4 tiles - one per corner of the player.

Hopefully it's become obvious now that you can decide if the player intersects tiles of value 0 a lot easier:

  1. Update player position
  2. Compute corners of player square
  3. Compute tiles mapping to those corners
  4. Check if any of these 4 tiles have value 0

But what if my tiles/player are not squares, what if it's harder to compute the intersection between player and tiles?

Any shape can be inscribed in squares. You can use this algorithm to eliminate all of the tiles that are too far away from the player to intersect it and make a list of all the tiles that "could" intersect the player. Then you use your custom Tile.intersects(player) method on the reduced set of tiles to determine exactly which tiles intersect the player.

But what if my tiles are not tiles, they are objects scattered around a map?

You can divide your map into conveniently sized tiles and assign each of the (stationary) objects to the tiles they intersect - this is a one-time operation. Then you use the same algorithm described above to determine objects that possibly intersect the player (by eliminating all of those in the tiles the player doesn't belong to).

\$\endgroup\$
  • \$\begingroup\$ Creating a new Player as apposed to moving the existing one still seems performance costly. \$\endgroup\$ – brug May 21 '18 at 17:41
  • \$\begingroup\$ @burglesco agreed, a new Player instance should not be created, that is why step 1 updates the position instead. \$\endgroup\$ – Tibos May 22 '18 at 4:57
  • \$\begingroup\$ Just saying @Tibos the custom Tile.intersects(player) is just Rectangle.intersects(Rectangle) \$\endgroup\$ – TheJavaNub May 22 '18 at 11:40
  • \$\begingroup\$ @TheJavaNub I extended the answer to cover more generic cases, for example if your player is a stick figure. In your simple case where everything is a rectangle you don't even need to create Rectangle objects, you just need some math with the coordinates of the corners. \$\endgroup\$ – Tibos May 22 '18 at 14:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.