This will possibly repeat some of the feedback already given but a lot of this will depend on what type of game you are creating. If you are aiming at a flight simulator (or something close) then there a variety of maneuvers (such as the Immelmann turn) that could be implemented (and which flight simmers would probably hope to see). If on the other hand you are developing a real time strategy game then you can probably get away with simpler movement AI that gives the impression of real flight without overloading the processor with AI management (critical as the number of units for the AI to control in a RTS game is likely to be higher than in a flight sim).
Personally (for a RTS) I started with simple flocking / collision avoidance code (which quickly gave me something good to look at and work from) before then adding unit targeting (flight to a waypoint or target another aircraft). From there I added formation flying (flight towards a constantly updated waypoint which is actually a position in a formation).
What really helped was having a two layer AI, the first dealing with the tactical situation (movement in the next few loops of the game logic concentrating on avoiding other aircraft and the ground, working out what is the best way to orientate towards the waypoint / target, rotating turrets and firing weapons ... oh and crashing which is fairly simple AI occasionally involving parachutes) and a higher level AI dealing with the 'strategic' situation (choosing a target or the next waypoint, responding to being attacked, deciding whether to run for it if damaged, checking if there is any fuel left, etc). Despite taking a while to get right (and it still needs some final polishing) this two layer approach (coupled with a third, squadron level logic) really made the organisation of the AI pretty easy to conceptualise and break down. While the AI is the big overhead in my code I can now effectively handle dogfights between anything up to (and beyond) 80 aircraft without the lights starting to flicker and brown-out.
If performance is poor there are two things that can be done,
- Simplify the AI for out of sight objects (simplify collision detection or even ignore it, don't actually fire weapons and track projectiles but just apply damage to the target, etc) - if the player cannot see the AI being more stupid then it isn't really a problem (although initially I did have problems with quick switches from one unit to another distant unit resulting in the player admiring aircraft happily flying upside down in formation ... tweaks to the simple AI and the application of a few loops worth of complex AI during the switch helped there).
- Only process each unit's AI every few game loops (I actually have a game setting where the AI can be applied for every unit during each and every game loop ... which is fine for higher end machines, or every second, third, fourth, etc loop ... meaning that I can effectively cut the processor overhead by half, etc ... at the cost of an increasing number of poor collision detection decisions, etc as the frequency of the AI being applied for each unit drops). Having something playable, but not as elegant on a lower end machine is in my view better than having the Rolls Royce solution that is unplayable due to the game effectively freezing up.