1
\$\begingroup\$

I'm working on a game to learn the basic for game concepts. I end up with the following problem. I got a class called enemy, but now I want different types of enemies. These enemies extend from this class enemy. So I can have different enemies with that share different properties. The problem is that I want to spawn a different enemy each time. But to do this I need to know all the enemies available to choose on randomly.

I have been thinking and I got two approaches to solve this. The first one I end up is to have an enum with different enemies, and get a random value from the enum and spawn that enemy, but for this, I need to hard code all the enemies into the enum. And another one is to have a GameRegister class, that have a register for all available enemies, like when you do modding in Minecraft for example. I can have a registered class to register enemies or objects. And if I want to select a random enemy I know all the enemies available. I think is the best approach because if I want to add more enemies or anything, I only need to register for that class.

I don't have any idea at all to how to implement this pattern, and I didn't find anything on the internet. Can someone give some tips or clarify what I want to do? Because I have the main idea but I get completely lost when I need to design this.

I'm working on Java using libGDX, if is useful for some reason.

\$\endgroup\$
1
\$\begingroup\$

I would go a bit further than SpacemanSpiff and use the Abstract Factory Pattern.

Create an interface IEnemyFactory with a method public Enemy createEnemy().

Then for each class of Enemy, also create a corresponding factory class (like GoblinEnemyFactory) which implements that interface by returning a newly created enemy of that type.

You can now register a new type of enemy by creating an EnemyFactory object and putting it into your collection of all available IEnemyFactorys.

The nice thing about this pattern is that you can theoretically have multiple enemy types which are actually implemented by the same enemy class. This is useful when you have enemies which behave identical but just have different stats. You can do that by creating different factory classes or by creating multiple instances of the same factory-class and then set some different variables on those instances. Here is an example which mixes both approaches by having two variants of goblins generated by two instances of the same factory-class and one variant of bat generated by an instance of a different factory-class:

EnemyFactory goblinFactory = new GoblinEnemyFactory();
goblinFactory.setName("Goblin");
goblinFactory.setHp(40);
goblinFactory.setAttack(10);    
EnemyFactory eliteGoblinFactory = new GoblinEnemyFactory();
eliteGoblinFactory.setName("Elite Goblin");
eliteGoblinFactory.setHp(80);
eliteGoblinFactory.setAttack(20);
EnemyFactory batFactory = new BatEnemyFactory();
batFactory.setName("Bat");
batFactory.setHp(20);
batFactory.setAttack(10);


enemyFactories.add(goblinFactory);    
enemyFactories.add(eliteGoblinFactory);    
enemyFactories.add(batFactory);

By the way, in the long run you might want to put all the different properties of your enemies into a config file, so you can easily tweak them and add more enemies.

\$\endgroup\$
0
\$\begingroup\$

You could look into the Factory Design Pattern. Using this your enemy factory class is the only place where you need to store the list of available choices.

From your description you would be fine with just a single generate method for random enemies. But if you want to make it more complex later you could also give your factory additional methods or have it take optional input and generate different results based on it. For example:

//Gives a random enemy
Enemy enemy1 = enemyFactory.getEnemy();

//Gives a goblin enemy
Enemy enemy2 = enemyFactory.getEnemy("goblin");

//Gives a troll, bat or something else classed as cave monster
Enemy enemy3 = enemyFactory.getEnemyCave();

Maybe you sometimes want to generate more of whatever enemy is first generated to create small groups of similar enemies, which you can do without your calling class knowing the full list of choices by just looking at the type of the first one generated and use as input for the next one. Or you may want specific types of enemies to be more common on certain levels. But this is just examples you may not need for your game.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.