I'm working on an arcade shoot-em-up game for Android similar to Ikaruga. The problem I'm facing is that it's proving quite difficult to robustly create a move and shoot patterns for the enemies. At the moment I've created two abstract classes EnemyShip and FlightPath from which each different enemy and move pattern derives from respectively. When the World is created it instantiates a LevelManager which stores level info in the form of:
waveInfos.add(new WaveInfo(3, 3f)); // new WaveInfo(NumberOfGroups, spawn interval)
enemyGroups.add(new EnemyGroup(8, EnemyGroup.TYPE_SCOUT_SHIP, EnemyGroup.F_PATH_INVADERS));
enemyGroups.add(new EnemyGroup(1, EnemyGroup.TYPE_QUAD_SPHERE, EnemyGroup.F_PATH_QUAD_SPHERE_L, World.BLACK));
enemyGroups.add(new EnemyGroup(8, EnemyGroup.TYPE_SCOUT_SHIP, EnemyGroup.F_PATH_INVADERS));
// new EnemyGroup(NumberOfEnemies, EnemyType, FlightPathType)
// new EnemyGroup(NumberOfEnemies, EnemyType, FlightPathType, ShipColour)
waveInfos.add(new WaveInfo(2, 0.33f));
enemyGroups.add(new EnemyGroup(1, EnemyGroup.TYPE_QUAD_SPHERE, EnemyGroup.F_PATH_QUAD_SPHERE_L, World.WHITE));
enemyGroups.add(new EnemyGroup(1, EnemyGroup.TYPE_QUAD_SPHERE, EnemyGroup.F_PATH_QUAD_SPHERE_R, World.WHITE));
totalWaves = waveInfos.size();
The levels are split into waves of groups of enemies and right now the EnemyGroup class takes care instantiating, adding the specified FlightPath to the newly created enemy and passing that enemy to the ArrayList in LevelManager for storage until spawned into the world at the time needed.
Once spawned the FlightPath component takes over and starts giving instructions based on its own stateTime and since each FlightPath has a reference field to its EnemyShip owner it can access the ship's functions and members it's controlling.
The EnemyShip class has a few functions for easy instruction such as moveTo(float x, float y, float duration) and shoot() but even with these, the FlightPath derivatives are difficult to make especially when I want different enemies in the same group to have slightly different paths and slightly different time arrivals.
I created a few fields in the FlightPath to keep track of keyFrames:
public int currentKeyFrame = 0;
public int totalKeyFrames;
public KeyFrame[] keyFrames; // Stores duration of instruction to be done, the spreadTime, totalFrameTime and enemyIntervalTime
public int shipNumber; // Stores which ship out of the group this FlightPath is attached to
public int totalShips; // Stores total number of ships in this EnemyShip's group
public float stateTime = 0;
KeyFrame.spreadTime is my attempt to control the time between the first enemy in the group to begin moving/shooting and the last.
KeyFrame.totalFrameTime = KeyFrame.duration + KeyFrame.spreadTime
KeyFrame.enemyIntervalTime = KeyFrame.spreadTime / Number of enemies in this group
While this setup works great for very simple linear movement, it feels quite cumbersome.
Thanks for reading this far. My question is how do I implement a more streamlined pattern control which would allow for complex movement without hordes of if() statements to check what other enemies in the group are doing and the like.
I hope I've provided enough information for you to understand how the enemies are handled. I'll provide any source code to anyone interested. Thanks in advance for any light you can shed on the subject.
EDIT: I found a page which very much describes the kind of system which would be perfect for what I want but I'm unsure how to correctly implement it with regards to overall group keyFrames
http://www.yaldex.com/games-programming/0672323699_ch12lev1sec3.html