Suppose I'm making a top-down 2D shooter kind of game, with a pretty big explorable world. If you think of the Diablo games that would be close enough for this discussion.
I'm very big on randomness. The world is randomly generated, and now I'm working on randomly placing enemies and items. Its quickly turning into a huge mess and I'm looking for advice on how to design the world/enemy/item generators better.
Suppose I have 26 different enemies: enemyA to enemyZ. They are in increasing order of difficulty. For example maybe enemyA is a stupid little rat and enemyZ is a badass dragon. I more or less want to have the easier enemies close to the player start point, and the harder ones further away, obviously so that the player slowly encounters harder enemies as he explores further away. Additionally I plan to tweak specific instances of the enemies for additional randomness. For example, when I spawn a rat, he'll have a random speed between 4 and 7, and random maxHP between 80 and 100, etc etc.
For any given point (tile) in the world, I want a range of possible enemies to be able to spawn. For example, near the player start point, I want enemyA to enemyE to be possible, with most enemies being A, and fewer being B, fewer still being C, and E being quite rare (since E is pretty tough for a player just starting).
Another example: a bit further away from the player start point, I want the possible enemies to be H to Q, with the middle one ( L ) being most frequent, while H and Q would be rare at this location (because H is very easy and Q is very hard for the player at this point in the game).
I hope this makes sense so far.
Basically I'd like some tips on how to structure all this in the code. With a focus on having everything easy to change, because I'm sure I will need to be tweaking things A LOT when I get to the game balancing stage.
What I have now is becoming a maintenance nightmare. For example see the code below.
Note that _difficulty01 is a helper variable that I have pre-calculated for every single tile in the game. Its a double between 0.0 and 1.0 and basically indicates how far the tile is from the player's start location. I figured I could use this to decide what kind of an enemy to create (0 = easy, 1 = hard).
// For each tile in the game,
if (GameMath._random.Next(0, 1000) > 900) // 10% of the time, we should maybe spawn an enemy on this tile
{
if (GameMath._random.NextDouble() < theTile.__difficulty01 ) // only proceed if difficutly test passes (affects frequency / number of baddies - more difficult = more baddies). {
// weve decided to add a baddie. what type? difficulty factors in to the type selection
Baddie.TYPE typeToSpawn = Factory.GetRandomBaddieType(theTile.__difficulty01);
Baddie theBaddie = GameObjectManager.MakeBaddie(theTile.__Xpixel, theTile.__Ypixel, typeToSpawn, theTile.__difficulty01);
GameObjectManager.SpawnBaddie(theTile, theBaddie);
}
}
else if (GameMath._random.Next(0, 10000) > 9550) // if there is no enemy (ie, 90 % of the time) then 4.5% of the time, spawn an item
{
// add some kind of item. what kind?
int randItem = Factory.GetRandomItemType();
Item theItem = GameObjectManager.MakeItem(theTile.__Xpixel, theTile.__Ypixel, 0, randItem);
GameObjectManager.SpawnItem(theTile, theItem);
}