Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: How can I make a ball behave as a bouncing and elastic ball?

Tags:

java

I have two classes BouncingBall and another one called ElasticBall. Both classes extends BallImpl which implements an interface called Ball.

public interface Ball {
    int DEFAULT_RADIUS = 50;

    int radius();
    Point center();
    void update();
}

public class BouncingBall extends BallImpl {
    public static final int MOVEMENT_SPEED = 12;

    static final int DOWN = 1;
    static final int UP = -1;

    private int direction;

    BouncingBall(int x, int y, int direction) {
        super(x, y);
        this.direction = direction;
    }

    @Override
    public void update() {
        direction = reverseDirectionIfNecessary();
        y = move();
    }

    private int reverseDirectionIfNecessary() {
        if (movingTooHigh() || movingTooLow()) {
            return switchDirection();
        }

        return this.direction;
    }

    private boolean movingTooLow() {
        return y + radius >= BallWorld.BOX_HEIGHT && movingDown();
    }

    private boolean movingTooHigh() {
        return y - radius <= 0 && movingUp();
    }

    private int switchDirection() {
        return movingDown() ? UP : DOWN;
    }

    private int move() {
        return y + (MOVEMENT_SPEED * direction);
    }

    private boolean movingDown() {
        return direction == DOWN;
    }

    private boolean movingUp() {
        return direction == UP;
    }
}

public class ElasticBall extends BallImpl {
    public static final int GROWTH_RATE = 2;

    static final int GROW = 1;
    static final int SHRINK = -1;

    private int growthDirection;

    ElasticBall(int x, int y, int radius, int growthDirection) {
        super(x, y, radius);
        this.growthDirection = growthDirection;
    }

    @Override
    public void update() {
        growthDirection = reverseGrowthDirectionIfNecessary();
        radius = next();
    }

    private int reverseGrowthDirectionIfNecessary() {
        if (growingTooBig() || shrinkingTooSmall()) {
            return switchDirection();
        }

        return this.growthDirection;
    }

    private boolean shrinkingTooSmall() {
        return radius <= 0 && shrinking();
    }

    private boolean growingTooBig() {
        return radius >= Ball.DEFAULT_RADIUS && growing();
    }

    private int switchDirection() {
        return growing() ? SHRINK : GROW;
    }

    private int next() {
        return radius + (GROWTH_RATE * growthDirection);
    }

    private boolean shrinking() {
        return growthDirection == SHRINK;
    }

    private boolean growing() {
        return growthDirection == GROW;
    }
}

I need to create a BouncingElasticBall which combines the behavior of the BouncingBall and the ElasticBall classes. I have poor knowledge in OOP, and I know Java does not allow multiple inheritance, so how can I solve this problem?

Thanks in advance.

like image 799
lmiguelvargasf Avatar asked Jan 07 '23 17:01

lmiguelvargasf


2 Answers

One way you could approach this is to not extend BallImpl, but make sort-of plugins. Like this:

public class BallImpl implements Ball {
    List<BallBehavior> behaviors = ...

    @Override
    public void update() {
       behaviors.forEach(behavior -> behavior.update(this));
    }
    ...
}

public interface BallBehavior {
    void update(BallImpl ballImpl);
}

And then, just write your elastic and bouncing logic as behaviors.

like image 149
Robert Bräutigam Avatar answered Jan 31 '23 07:01

Robert Bräutigam


Once you diverge hierarchies there's no way to merge them in java.

It's a design matter: if you know that ElasticBall and BouncingBall may be combined together, you should create two interfaces Elastic and Bouncing, both extending interface Ball, with common methods valid for both.

Then the common method implementations may be set into a common abstract class, let's say AbstractBall. At this point you can finally detail your three implementations:

  • ElasticBall extends AbstractBall implements Elastic
  • BouncingBall extendis AbstractBall implements Bouncing
  • ElasticBouncingBall extends AbstractBall implements Elastic, Bouncing

In this way you'll be able to control what to do in each method, reuse code for common stuff (in the abstract class).

like image 21
Davide Rossi Avatar answered Jan 31 '23 05:01

Davide Rossi