Enemy Loading/Saving in a Top Down Shooter

Started by
7 comments, last by theOcelot 14 years, 10 months ago
In my 2D top down shooter I'm using XML to save/load level information such as map tiles. I'm going to use that to store information on the levels' enemies too but I have some questions about the exact way to do things: Naturally, I plan to have a couple of different kinds of enemy. They'll be different in health, damage etc. I've thought of making different AI attack patterns for each one too. This would mean for example; all grey planes travel in a straight line but all black planes attack diagonally. In that situation I'd just have to store enemy positions the same way I'm storing tile positions; a single number representing the enemy type in whatever position it's in. However, what if I make planes that move across the screen diagonally to the left but then I also want to make them move right sometimes? That completely messes it up. Unless I completely randomize the AI of each plane (which would probably lead to some insanity and generally sloppy looking gameplay) that just can't be done in a system where an enemy is represented by a single digit unless I make an exact duplicate of that enemy type but with the one difference being the direction of attack. That would work but it would be tiresome and not very flexible. Maybe then I want every plane to be able to attack in any of the set AI patterns? I'd need an EnemyTypes*AIPatterns number of different enemies. So what I'm asking is: What is a good way of storing enemy information for a specific level using XML for a top down shooter? Different types for every slight variation on an enemy type is surely a bad idea, right? So, how might you logically store more than a simple number while not ending up with a garbled mess? I would suppose that a pretty good way to store an enemy's information would be like this:

<enemy type="1" xpos="22" ypos="10" attackpattern="2"/>
That would allow changing of the AI, health, etc. of any specific enemy regardless of type but how then should it be organized inside the XML file? Should they just be one after the other, in order of appearance in the level with the first at the top? That'd wind up very long but I suppose that doesn't matter. Would that make sense or is there an obvious better way? Also, in a top down shooter, should the "waves" of enemies that come together in formation be in any way linked by the game code or level files or should they just be enemies that happen to appear side by side and use the same attack pattern?
Advertisement
Quote:Original post by Sean_Seanston
However, what if I make planes that move across the screen diagonally to the left but then I also want to make them move right sometimes? [...] that just can't be done in a system where an enemy is represented by a single digit.


Sure it can.

enum AttackPattern {    ATK_NONE = 0,    ATK_STRAIGHT = 1,    ATK_LEFT_DIAGONAL = 2,    ATK_RIGHT = 4,    ATK_SOME_NAMED_COMBO = ATK_RIGHT | ATK_STRAIGHT};

<enemy type="1" xpos="22" ypos="10" attackpattern="6"/>

Defines an enemy with ATK_LEFT_DIAGONAL and ATK_RIGHT. This gives you n possible attack patterns in an n bit unsigned type, where any of them can be combined. You can also name combinations as above.

If you want to store more, like how often they switch attack patterns, then you'll need more than 1 value.
Anthony Umfer
Ya but I mean describing the entire enemy with just a single number.

You'd need at least 1 number for the enemy type (grey plane maybe) and 1 for the attack pattern.

Like currently I have the tile map saved like this:
        <row id="0">9,9,13,9,15,9,19,20,9,9,9,9,9,9,9,9,9,9,9,9</row>        <row id="1">4,4,4,4,4,4,4,4,9,4,4,4,4,4,4,4,4,4,4,4</row>


I was going to do the enemies in a similar way where 0 is no enemy and 1/2/3 are different types of enemy but then this problem cropped up.

Does anyone actually have any information on how something like this was actually handled in old 2D games like SWIV or Aero Fighters etc.? That would be interesting too...
Think of the density of your enemy data in relation to the density of your map data. Compared to the size of the map, I imagine on average that there are only going to be a handful of enemies. Therefore, you should store an entry for each enemy on the map, but not store anything for enemies that aren't on the map. If you store enemies the same way you store tiles, you not only limit yourself to one enemy per tile but you also store null data by enumerating a bunch of tiles where there aren't enemies (i.e. by using an ID of 0). If there is no enemy on a particular tile, then simply exclude that information instead of storing fluff. Otherwise, you're inclined towards a much less expressive and flexible way of storing the enemy data. You've already observed what problems can arise when you collapse it all down to a single value. Just store exactly what information you need for every enemy individually. Don't bother trying to come up with a list of all possible permutations of enemy state and assigning each one an ID, there's no need.
I would say the better way to do this is, have a basic data store for all your enemy units that has nothing to do with the map at all... it defines the basics for the enemy unit, and then in the map ref these units and whatever modifiers they may have. Allows for the most flexibility.
Quote:Original post by ZipsterJust store exactly what information you need for every enemy individually. Don't bother trying to come up with a list of all possible permutations of enemy state and assigning each one an ID, there's no need.


Alright cool... I'll just use a sequential list of enemies.

Quote:Original post by wacko420
I would say the better way to do this is, have a basic data store for all your enemy units that has nothing to do with the map at all... it defines the basics for the enemy unit, and then in the map ref these units and whatever modifiers they may have. Allows for the most flexibility.


Ya, what I plan to do is have an XML file that describes the characteristics of each enemy type, like health and damage and whatnot. Then I'll load from the map XML file into a vector of enemies.
You could have elements like this at the top of each level:
<enemy_type_definition type_id="1">    <ship_type>gray</ship_type>    <attackpattern>2</attackpattern>     <otherinfo>foo</otherinfo></enemy_type_definition>
Then whenever you used the number 1 in your row arrangment like so:
<row>0,0,0,1,0,0,1,0,0,0</row>
it creates a gray ship with attack pattern 2, whatever that might be. That particular row created two of these ships.

You could use this in combination with Zipster's (superior) idea, where you write lines that have a position and a ship type, instructing the game to place a ship of the requested type at that position.

You could also expand this system to have all the ships' properties specified at run-time, loaded from these enemy type definitions.
An interesting idea too... though it still has the 1 enemy per tile limitation. Still not totally sure how I'll do it... making it so you can select attack patterns for enemies in the editor is giving me a lot to think about, especially with multiple enemies on 1 tile which isn't going to be visible unless some kind of numeric display of the enemies on the tile is implemented. I'll find a way soon enough though...
You can always just ban having more than one start on each tile. That doesn't strike me as a heart-breaking feature to cut. [smile]

This topic is closed to new replies.

Advertisement