Jonathan
Jonathan

Reputation: 77

Java: Checking rectangle collision against multiple objects

I've been learning Java by experimenting with a little "game" that started with just trying to make a ball jump. I've got 3 classes (JumpingBall3, BallSprite3, & Floor) and have achieved a gravity of some sorts, a jump that works consistently, and hit detection against floors to stop the ball falling infinitely. With this last point I've spotted a potential issue with future development. Right now I have two floors created by JumpingBall3 ("floor1" & "platform") and I detect collision within the BallSpite3 using the following code:

public boolean collision() 
{

    if (game.floor1.getBounds().intersects(getBounds()) || game.platform.getBounds().intersects(getBounds()))        {
        onFloor = true;
    }
    else 
    {
        onFloor = false;
    }

    return onFloor;
}

If I were to keep adding more floors or platforms that "if" condition is quickly going to spiral out of control in terms of length. Is there a way to create a method that cycles through all visible Floor objects created in my JumpingBall3 class?

I've posted the full code online here, it seemed a bit lengthy to include within this post.

Upvotes: 4

Views: 2488

Answers (3)

NESPowerGlove
NESPowerGlove

Reputation: 5496

An approachable solution to this problem is to have your "game world" contain a list of entities (where an entity can be a ball or wall or any other in game object), and have some mechanism that detects which entities are near which other entities. This would end up calling some type of entity.checkCollision(neighborEntity) method.

You still need to have different behaviors for colliding with different entities. You can do this by having the base Entity class have some common attributes you can turn off or on, or store behaviors that you can apply directly to the collided entity.

// within some game loop, check for collisions
for (Entity entity : collidableEntities)
{
    ball.checkCollision(entity);
}

Your classes could look like this to have programmed behaviors.

public Entity
{
    public void applyCollisionBehaviorTo(Ball ball) { // Override to do something}

    public void onCollision() { // Override to do something }

    public collidesWith(Entity neighbor) { // your collision math }

    public void checkCollision(Entity neighbor)
    {
        if (collidesWith(neighbor))
        {
            onCollision()
        }
    }
}

public Wall extends Entity
{
    @Overide
    public void applyCollisionBehaviorTo(Ball ball)
    {
        ball.reverseDirection();
    }
}

public Ball extends Entity
{
    @Overide
    public void onCollision(Entity collidingEntity)
    {
        collidingEntity.applyCollisionBehaviorTo(this);
    }
}

Upvotes: 2

Nicolas Filotto
Nicolas Filotto

Reputation: 45005

The simplest thing to do is to keep all the objects that you want to check in a Collection like for example a List, then iterate over this List.

So for example, here a good choice would be to use a collection of Floor, on which we iterate to check if we have a collision with one of them.

public boolean collision() {
    boolean onFloor = false;
    Rectangle rectangle = getBounds();
    for (Floor floor : floors) {
        if (floor.getBounds().intersects(rectangle)) {
            onFloor = true;
            break;
        }
    }
    return onFloor;
}

Assuming that you use Java 8 , you could rely on the Stream API to do the same thing as next:

public boolean collision() {
    Rectangle rectangle = getBounds();
    return floors.stream().map(Floor::getBounds).anyMatch(rectangle::intersects);
}

Upvotes: 3

Tokazio
Tokazio

Reputation: 530

create a list with all objects. then use a loop over all the object you want to detect (excepting the one that making the detection of course)

Upvotes: 1

Related Questions