At the moment I'm working on a game and things are going pretty good. What keeps me busy at the moment, is making a mob spawner which spawns mobs in a certain area.
The big problem is right now, I'm not really sure how to keep track of all the mobs being spawned by the spawner, as there are different inheritances of mobs.
This is my MobSpawner class:
public class MobSpawner {
protected List<Mob> mobs;
protected Level level;
protected int timer = 0;
protected int spawnTime = 0;
protected int maxMobs = 0;
public MobSpawner(Level level) {
this.level = level;
}
}
And this is my RoachSpawner class:
public class RoachSpawner extends MobSpawner {
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Roach>(); // Roach is an extension of Mob
}
}
This is not gonna work because the List and ArrayList must be of the same type.
So the question is, does anyone have any other ideas how to do this?
Thanks in advance!
I'm presuming that Roach extends Mob.
You can use an ArrayList<Mob> to hold Roaches. So:
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Mob>();
}
And if you just use ArrayList<Mob> in all the implementations, you can allocate it in the base instead (assuming ArrayList is always the container you want -- if you want to use other List types see kwah's answer and have subclasses create list):
public class MobSpawner {
protected final List<Mob> mobs = new ArrayList<Mob>();
...
}
And just have the subclasses use the base's list.
Instantiating the list in the base class and making it final has a bonus side-effect of letting you state the following invariants (presuming you don't violate them with reflection or anything):
A MobSpawner will never have a null mobs, and
mobs will reference the same object throughout the entire lifetime of a MobSpawner.
Being able to make those assumptions can possibly simplify some of your logic in other places.
Making it final also enforces, at compile time, that you're not inadvertently replacing it with another list somewhere.
If you are not already doing so, try taking advantage of supertypes.
In the same way that you can declare a variable to be a List and then instantiate it to be an ArrayList, try saying your List contains Character items and then fill it with specific implementations of the Characters (eg List<Character> is instantiated as ArrayList<Mob> and ArrayList<Roach>).
public abstract class Character { }
public class Mob extends Character { }
public class Roach extends Character { }
public class Spawner {
protected List<? extends Character> characters;
protected Level level;
protected int timer = 0;
protected int spawnTime = 0;
protected int maxCharacters = 0;
public Spawner(Level level) {
this.level = level;
}
}
public class RoachSpawner extends Spawner {
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Roach>();
}
}
public class MobSpawner extends Spawner {
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Mob>();
}
}
Related
I am relatively new to Java and programming, so I apologize if this question seems stupid. I am creating a battle-game for a Java programming class -- I have a Hero class with some basic methods and a subclass Paladin that extends Hero but with its own unique methods added in. I want to have a Battleground object that passes in ANY Hero class but then check which specific subclass was passed in. How do I determine which of the Hero subclasses were passed in?
public class Hero {
private String name;
private int hitPoints;
public Hero (String name, int hitPoints) {
this.name = name;
this.hitPoints = hitPoints;
}
public String getName() { return this.name; }
public int getHitPoints() { return this.hitPoints; }
public void takeDamage(int amount) { this.hitPoints -= amount; }
}
And here is the Paladin Class
public class Paladin extends Hero {
public Hero (String name, int hitPoints) {
super(name, hitPoints);
}
public void heal(int amount) {
this.hitPoints += amount;
}
}
So in the battleground class, I have a method that attempts (incorrectly) to check if the hero passed in is a Paladin. How would I go about doing this? The if statement is a placeholder psuedo-code just to clarify what I mean.
public class Battleground {
private Hero player;
public Battleground (Hero player) {
this.player = player;
}
public void startRound() {
// HERE!!
if (player.equals(Paladin)) {
player.heal();
}
}
}
Thinking in terms of what your classes are actually modelling, it doesn't make much sense for a battleground to know that a Paladin heals themselves at the start of a round, nor for the battleground to be responsible for making sure the Paladin heals themselves.
A more sensible design would be for the game to inform the hero that the round has started, and let the particular Hero subclass control what that kind of hero does when the round starts. For example:
public class Hero {
// ...
public void onRoundStart() {
// do nothing
}
}
public class Paladin extends Hero {
// ...
#Override
public void onRoundStart() {
// your heal method takes an int as its argument
heal(10);
}
}
public class Battleground {
// ...
public void startRound() {
// let the particular Hero subclass control what happens
player.onRoundStart();
// ...
}
}
This way you don't need any if statements or instanceof checks, but also the code defining a Paladin's behaviour is in the Paladin class where it sensibly belongs. If you want to change the rules for Paladins later, it will be easier to know which class you need to edit.
This kind of refactoring is called "replace conditional with polymorphism".
Using Instanceof is Considered a Code Smell Sometimes
Using instanceof can be considered to be a code smell - which means a bad practice.
There is an alternative for you to consider.
Add the heal() method to the Hero class, but leave the implementation blank.
Put only an implementation in the Paladin class. Then, even though heal() will be called on all players, it will only do something inside Paladins.
However... if you still need to detect the class type...
Ways to Detect the class
There are multiple ways to differentiate between classes.
Instance of is one.
Another is having different constructors.
A third is having an ENUM or String field called EntityType.
In your case, I think instanceof or using a special field make the most sense.
Instanceof
if(player instanceof Paladin)
Using a Special Field
Quick Example Hero
public class Hero {
private String name;
private int hitPoints;
private int HeroType;
public Hero (String name, int hitPoints) {
this.name = name;
this.hitPoints = hitPoints;
this.heroType = BASIC_HERO;
}
public static int BASIC_HERO = 0;
public static int PALADIN_HERO = 1;
...
}
Quick Example Paladin
public class Paladin extends Hero {
public Paladin(String name, int hitPoints) {
super(name, hitPoints);
this.heroType = PALADIN_HERO;
}
}
Detecting the Type
You would have a method in both classes called getHeroType().
if(hero.getHeroType == Hero.PALADIN_HERO){
}else if(hero.getHeroType == Hero.BASIC_HERO){
}
If you want, you can use to check the class of the object:
if (player instanceof Paladin)
No question, this will work. If you don't have a lot of "special" behaviour and a limited small amount of cases, that can be a reasonable solution. But assuming that your game will end up with a lot of special handling for each subclass of Hero and probably not only in the startRound() method of your Battlefield class, your code will someday be cluttered with these instanceof checks. Same applies, if you use a specific type field within the Hero class.
In that case a better solution might be to relocate the logic into special classes and try to avoid type checks if possible or at least have a well defined place for them, if necessary.
Update: removed faulty demo implementation
You can always do player.getClass to get actuall class. As for if statements you can use instanceof operator.
So
if (player instanceof Paladin) {
((Paladin)player).heal();
}
I am currently in the process of refactoring the code I wrote for a text/console version of the Mastermind board game. I am a bit stuck with how to best approach improving this section my GameLogic class.
public GameLogic(GameSettings gameSettings)
{
// ..other stuff..
// initialise static members
Board.setTotalRows(gameSettings.getNumOfGuesses());
Board.setTotalColums(gameSettings.getCodeLength());
// InputBoard and OutputBoard extends the abstract class Board
inputBoard = new InputBoard();
outputBoard = new OutputBoard();
}
What I am trying to do is set the static values of totalRows and totalColumns in the Board class BEFORE constructing the inputBoard and outputBoard objects. The reason why I want to do this is because I need to have these values present when constructing instances extending Board (an abstract class). The reason why I am making these values static is because they should be the same across all instances extending from Board and so that I can do something like Board.getTotalColumns() throughout the application.
The reason why I think this is suspiciously bad is because it would be possible to declare inputBoard or outputBoard without first setting the static member variables and of course it would also be possible to accidentally set the values of the static member later on to any arbitrary value.
Another approach I thought of was to make the getters in GameSettings public and static so that I could do something like this instead:
public abstract class Board
{
private static final int totalColumns = GameSettings.getCodeLength();
private static final int totalRows = GameSettings.getNumOfGuesses();
// other stuff...
}
This would allow me to avoid using setters and the problems associated with using them as listed above. But wouldn't this defeat the purpose of instantiating a GameSettings object?
What do you think are better alternatives to approach this?
I am not an expert on design pattern. I would try something like below -
Board.java
abstract class Board {
private final GameSettings gameSettings;
Board(GameSettings gameSettings) {
this.gameSettings = gameSettings;
}
public int getTotalColumns() {
return gameSettings.getCodeLength();
}
public int getTotalRows() {
return gameSettings.getNumOfGuesses();
}
//Other abstract methods
}
InputBoards .java
class InputBoards extends Board {
InputBoards(GameSettings gameSettings) {
super(gameSettings);
}
}
OutputBoards .java
class OutputBoards extends Board {
OutputBoards(GameSettings gameSettings) {
super(gameSettings);
}
}
GameSettings .java
class GameSettings {
public int getCodeLength() {
//return your value;
}
public int getNumOfGuesses() {
//return your value;
}
}
Now I would do -
public GameLogic(GameSettings gameSettings) {
inputBoard = new InputBoard(gameSettings);
outputBoard = new OutputBoard(gameSettings);
}
I have a class Player which contains few private fields of other classes ( I believe it is called composition ).
public class Player
{
private String name;
private Statistics statistics;
private Experience experience;
private Effort effort;
}
I will post only one of them called Statistics
public final class Statistics
{
Pool pool;
Edge edge;
class Pool
{
private Map<Stats, LimitedInt> map = new HashMap<>();
private int freePoints = 0;
void setAvailable(Stats stat, int value){}
int getAvailable(Stats stat){ return 0; }
void setMax(Stats stat, int value){}
int getMax(Stats stat, int value){ return 0; }
void setFreePoints(int value){}
int getFreePoints(){ return 0; }
void spendFreePoints(Stats stat, int amount){}
}
class Edge
{
private Map<Stats, Integer> map = new HashMap<>();
private int freePoints = 0;
void setMax(Stats stat, int value){}
int getMax(Stats stat, int value){ return 0; }
void setFreePoints(int value){}
int getFreePoints(){ return 0; }
void spendFreePoints(Stats stat, int amount){}
}
}
It is not implemented yet of course, but I want to know what is a correct version of changing for example Player's Pool. I can imagine following scenarios:
Player has exactly the same methods as Pool class which are something like
public class Player
{
// something above
void setAvailablePool(Stats stat, int value){ statistics.pool.setAvailable(stat, value); }
}
This solution seems to be ok but then in Player class I would have a lot of 1-line methods which would just redirect orders to composed fields.
I could transfer pool and edge to the Player class and make them public final but I read that mutable objects should be rather private.
Those 2 are my first thoughts, but I wanted to ask generally how to create interface in class when we use composition.
One-line methods are not a problem, but what makes your solution #1 unsatisfying is the violation of the Law of Demeter (statistics.pool.setXXXX). It might be better to have a statistics.setAvailableInPool() method (or to use your idea #2). I can' t offer more help with the specific implementation because It's not very clear what your Pool and Edge classes are supposed to do (or why they're so similar to each other but do not implement a common interface).
In answer to your general question about creating interfaces for composition, take a look at the SOLID principles. Basically, you should think about what behaviors you need from your dependencies, name those behaviors clearly, and depend on the interface rather than the concrete class. That makes the code easier to understand and easier to change in one place without having to change it everywhere.
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.
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;
}
}
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).
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;
}
}
I have a base class FiniteStateMachine which has a list of State. The states can only be instantiated through the FSM, so I can make sure the list is updated.
public class FiniteStateMachine {
private List<State> states = new ArrayList<State>();
public State addState(String name) {
State s = new State(name);
states.add(s);
return s;
}
protected void addState(State s) {
states.add(State s);
}
public static class State {
private String name;
protected State(String name) { this.name = name; }
}
}
Now, I want to extend both the FiniteStateMachine and State classes into MyFSM and MyState classes. I still want to make sure the new MyState states can only be created through the FSM, to ensure they are part of the list.
This is what I have done so far:
public MyState extends FinitStateMachine.State {
private int n;
protected MyState(int n, String name) {
super(name);
this.n = n;
}
}
public MyFSM extends FiniteStateMachine {
#Override
public State addState(String name) {
throw new UnsupportedOperationException();
}
public MyState addState(int n, String name) {
MyState s = new MyState(n, name);
super.addState(s);
return s;
}
}
I am not sure I am doing it right.
First, the original State class is an inner class of FiniteStateMachine, and here I am extending it outside my new class MyFSM.
Second, I had to add a new method to the original FiniteStatMachine
protected void addState(State s) {
states.add(State s);
}
otherwise I don't know how could I have attached a state of my new MyState class to the FiniteStateMachine list.
Third, instead of overriding the addState(name) method I kind of crippled it and throw an exception and instead put a whole new method to return the new class.
If there is a coding pattern for these situations I am not aware of it. But I'd like to know, so I don't go reinventing the wheel.
If you make the list variable protected, you may access it from child classes too, without the add method. It depends on what you want to do later, and how visible you want the list to be. If you want to be able to add states from outside of the inheritance hierarchy, or if you don't want the list to be visible within the whole package,you may need the addState method though.