0

I've recently begun to learn the concepts of OOP in Java, and have started building a game which involves a ball and pegs scattered around a screen. The aim of this game is to remove all the pegs off the screen by having the ball collide with them. There are different types of pegs which have certain behaviours when they are destroyed. (I.e. black pegs can't be destroyed, red pegs spawn two new balls etc.)

The following method is what I am using to check for collisions between the ball and the peg by iterating through each peg in an ArrayList. If a collision is detected, the peg will execute an action before getting removed from the ArrayList.

// inside MainGame class
public void checkCollisions(Ball ball) {
    for (GameObject peg: pegs) {
        if (peg.checkCollision(ball)) {
            // peg does something before getting removed from the ArrayList
        }
    }
}

My first approach was to have a bunch of if statements to check the type of the peg using instanceOf, but although it may work for a small game like mine with very few peg types, I doubt that this solution would work elegantly in a game with many different types of game objects such as an RPG.

What if some types couldn't be destroyed (such as the black peg), or that it affected other pegs around it?

I'm trying to find a flexible solution which would make it easy to add "death" behaviours which could potentially affect/create other pegs / game objects, but I am unaware of a design pattern which addresses this problem and would love some tips/resources that could aid me with this question.

kwhk
  • 27
  • 1
  • 8
  • To assign a class-id (actually C++ rtti is doing the same trick, but hard for you to use) to each class, and then use **dispatch table** by class-id is a neater (bad perf though) approach. – tibetty Oct 16 '19 at 01:39
  • Instead of a dispatch table, you could add an ID (like what tibetty said) to each type of peg and handle each one differently in a method that is called upon peg collision. – Leftist Tachyon Oct 16 '19 at 02:02
  • Please clarify "dynamic solution ... add "death" behaviours," - do you mean that, say, black pegs might have one behaviour at one time, then at another time (while the game is stll running) they might have a totally different behaviour ? Or do you simply mean than you code black peg's behaviour today, and then 6 months down the track you want a maintainable way to change that behaviour (or add more types of pegs) ? The latter seems to me to be straight polymorphism - but is it that or the former ? – racraman Oct 16 '19 at 02:17
  • @racraman It would be the latter case. I could have an abstract `handleCollision()` in a Peg class, and have it be implemented for every sub class of peg (when creating new types of pegs). But since all game objects are stored in the MainGame class, there would be the problem of some peg types such as the red peg type (which would spawn two extra balls on collision) that require going back to the MainGame class to create new balls / game objects. – kwhk Oct 16 '19 at 02:39
  • You could modify `handleCollision` to take a `MainGame` argument, so that it could perform those actions. Alternatively, each peg could "know" how to access the main game - eg, maybe it could be a Singleton. – racraman Oct 16 '19 at 02:48
  • @racraman I have not thought of passing `MainGame` as a parameter, but would that be too much to expose to a peg? Also I am confused with the second suggestion, could you elaborate on that please? Thanks! – kwhk Oct 16 '19 at 02:55
  • Not too much to expose at all; The peg gets supplied with what it needs to do its job. For the second, the idea behind Singletons is that they enable anywhere in the system to access the single instance - in your case, anything anywhere in your game application can access the current main game (eg, by calling a static method `MainGame.getInstance().doSomething()` ), so main game wouldn't need to be passed everywhere in arguments. See https://stackoverflow.com/questions/70689/what-is-an-efficient-way-to-implement-a-singleton-pattern-in-java – racraman Oct 16 '19 at 03:07
  • and of course the other option is that each Peg knows the MainGame that it belongs to - ie. the `abstract class AbstractPeg` has a `public AbstractPeg(MainGame mainGame)` constructor. Depends on how much interaction you reckon pegs might get over time - and how you feel about that exposure :) – racraman Oct 16 '19 at 03:20
  • Have you considered interfaces and/or lambdas? – Bakna Oct 16 '19 at 04:03

0 Answers0