1

I wonder if my aproach into modelling difficulty level for my game is good.

public abstract class AbstractDifficulty {

    public AbstractDifficulty() {

    }

    public abstract int enemyWaves();
    public abstract int enemiesInWave();
    public abstract long enemyWaveIntervalMilis();
}

And then several subclasses which implement those methods, for example.

public class EasyDifficulty extends AbstractDifficulty {

    @Override
    public int enemyWaves() {
        return 1;
    }

    @Override
    public int enemiesInWave() {
        return 10;
    }

    @Override
    public long enemyWaveIntervalMilis() {
        return 500;
    }
}

I wonder if there is a simpler way to do this, but the same easy and clean to use as this.

Edit: Could someone be so kind to explain to me why this question got minus votes. Is something wrong with this code, or my explanation ? Thanks.

4
  • 4
    This looks perfectly fine by me. The only other way to do this, I think (which is less flexible, btw) is to have one class that governs your actions and setting a difficulty modifier. This modifier can then be used to calculate settings based of a base number. E.g.: enemiesInWaveBase = 10 * difficultyMod, and then setting difficultyMod to 0.7 for easy, 1.0 for normal and 1.5 for hard or something. Less code, less flexible. Commented Mar 18, 2015 at 12:37
  • 2
    It depends on what you consider difficult. This looks like an arcade style game, so other factors could include player health, the goal of the game/level (if one exists) etc. I'd personally use interfaces instead since it is easier to add more interfaces if a new feature comes up. Modifying parent classes can be a bad idea. Commented Mar 18, 2015 at 12:42
  • @ryanyuyu Could you please explain or give me some simple example, which would illustrate this situation, when you want to add new feature. Thanks. Commented Mar 18, 2015 at 14:37
  • @ryanyuyu OK nevermind, I think I understand now what you mean. Thanks anyway, I will consider this. Commented Mar 18, 2015 at 14:51

3 Answers 3

5

Your design will do the job, but it seems what you want to have is a container class. So instead having a method for each value, have a (final) field with the value and a getter. They can be set e.g. in the constructor.

If your difficulty modes are known and few, consider having an enum, which are final and easier to use.

enum Difficulty {
    EASY(1, 10, 5000),
    MEDIUM(2, 15, 4000),
    HARD(4, 20, 3500);

    private final int enemyWaves;
    private final int enemiesInWave;
    private final long enemyWaveIntervalMilis;

    Difficulty(int enemyWaves, int enemiesInWave, long enemyWaveIntervalMilis ){
        this.enemyWaves = enemyWaves;
        this.enemiesInWave = enemiesInWave;
        this.enemyWaveIntervalMilis = enemyWaveIntervalMilis;
    }

    public int getEnemyWaves() {

        return enemyWaves;
    }
    public int getEnemiesInWave() {

        return enemiesInWave;
    }
    public long getEnemyWaveIntervalMilis() {

        return enemyWaveIntervalMilis;
    }

}
Sign up to request clarification or add additional context in comments.

4 Comments

The fields have to be public final, or you'll never read them.
Man that is exacty what I wanted I think ! I never used enums, but dont know why I thought about them first.
Are enums polymorphic ? I dont want to use even single IF statement in this particular code, like i can have with abstract classes. Like will it work like some method will get argument Difficulty, but it could be any of the three ?
Jep, you can set the current difficulty at some place (maybe some WorldConfiguration or UserSettings object) and then always access it regardless of its actual value. => worldConfiguration.getDifficulty().getEnemyWaves();
2

One alternative is to not have different difficulty classes, but just one difficulty class with different instances being the different difficulties (so, a class with attributes enemyWaves, enemiesInWave and enemyWaveIntervalMilis, and different instances with different settings).

Comments

2

Your solution looks fine. If you want to increase readability you can just remove the constructor from the abstract class, since that is created by Java as default anyway.

I also vote for an interface instead of an abstract class unless there is a specific reason to use abstract class.

I also feel that for the specific problem you do not need different classes, but rather different instances of the same class. In that case I would use the final fields set by constructor and then the methods return the values.

public class Difficulty  {

  final private int enemyWaves;
  public Difficulty(final enemyWaves){ this.enemyWaves = enemyWaves; }

  @Override
  public int enemyWaves() {
      return this.enemyWaves;
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.