0
votes

I'm currently working on a tile collision system for an RPG style game and it mostly working except for some inconsistency with rectangle intersection.

protected void tileCollision() 
{  
    AnimatedSprite player = findPlayer();
    for(int i = 0; i < _sprites.size(); i++) 
    {
        AnimatedSprite spr = _sprites.get(i);
        for(int j = 0; j < tileWithinRange.length; j++) 
        {
            Tile tile = tileWithinRange[j];
            if(tile != null) 
            {       
                if(tile.getBounds().intersects(player.getBounds())) 
                {
                    player.setCollided(true);
                    tileCollision(player, tile, -1, -1);
                } else 
                {
                    player.setCollided(false);
                }
            }
        }
    }   
}

When I first collide with a tile upon launching the game, it always returns true, but if I move along a column of tiles, I start getting false returns and then after a while I only get false returns.

Here is an image of the player intersecting with a tile

There is an obvious intersection here, yet in this scenario, the variable collided returned false.

What is going wrong that the intersection isn't always registering?`

2

2 Answers

0
votes

There is too little info here to really know what's happening, but something looks fishy here:

     if(tile.getBounds().intersects(player.getBounds())) 
     {
        player.setCollided(true);
        tileCollision(player, tile, -1, -1);
     } else 
     {
        player.setCollided(false);
     }

Since you are checking multiple tiles against the player in a loop, what if the player collides with the first tile, but doesn't collide with the second tile? You'd end up calling player.setCollided(false); even though he collided with a former tile, overwriting that true collision state with a false one. That might explain the behavior you're getting where you're getting only false returns after a while (perhaps because of the order in which you are checking the tiles makes it so you keep overwriting true states with false states).

I'm not sure if that's desirable or not to have these kinds of side effects, but it is a bit confusing at the very least to have this kind of collision state first being turned on and then overwritten with off within the same loop. If that's undesirable behavior, perhaps what you're after needs you to break out of the loop if a collision occurs. Or perhaps what you want is something more like this:

    player.setCollided(false);
    for(int j = 0; j < tileWithinRange.length; j++) 
    {
        Tile tile = tileWithinRange[j];
        if(tile != null && tile.getBounds().intersects(player.getBounds())) 
        {
            player.setCollided(true);
            tileCollision(player, tile, -1, -1);
        }
    }
}

Or maybe your bounds/intersection function is genuinely malfunctioning -- it's too hard to tell with so little code/info (we don't know how these are implemented).

It's good to be able to isolate your code and learn how to construct test cases to test out individual functions in little pieces independently. You want to eliminate suspects through a process of elimination with a testing procedure that allows you to figure out, "Okay, this part works perfectly in every case, let's move on to the next thing." Otherwise it becomes a guessing game trying to figure out what went wrong. One of the easiest ways to lose a time of time/productivity in development is to write a bunch of code first and then try to narrow down what went wrong in hindsight, instead of testing each little babystep. Mistakes get more expensive the later you discover them and the more suspects you have to go through in an investigation.

0
votes

I ended up rewriting the method into a boolean which made it return true when colliding and false when not. Here is the new code.

    public boolean tileCollision() {
    AnimatedSprite player = findPlayer();
    for(int j = 0; j < tileWithinRange.length; j++) {
        Tile tile = tileWithinRange[j];  
        if(tile != null) {
            if(tile.getTileBounds().intersects(player.getBounds()) ) {
                return true;
            }
        }
    }
    return false;
}