Here is a quick summary of some of the techniques I used when building this game.
The first thing I had to figure out was how to manage all of the models and assets for the game. I knew there would be a lot of 3D going on – which is not exactly flash’s strong point.
Initially I started out by setting up a basic camera controller and loading in as many models as I thought I would need. This gave me an indication of what level of detail I could get away with without sacrificing too much detail. This formed the basis for pretty much the rest of the game development.
The next thing I played with was the frame rate. Originally I ran the entire program at 60fps, which was awesome, but as I added in more and more features I discovered that it was pushing the CPU pretty hard.
I dropped the frame rate back down to 30fps which made little difference to the visual display of the game elements, but unfortunately made the UI elements seem a bit sluggish.
To get around it this problem, I split the game up into a variety of different renderers, each running at the minimum speed possible.
The render layer used for the for the GUI elements were set up to run at 60fps, whilst the ‘boats / islands’ and ‘water’ layer ran at a much slower 25fps. There was also an under water layer for a while when I had transparent water, but that had to be removed due to performance issues.
A unexpected positive side effect of this approach was that it prevented a lot of the clipping problems that were occurring between the boats and the water.
The ripples around the boats and islands were created by putting a simple 3D plane under the loaded in MD2 models. The benefits of this approach was that it allowed me to keep the complexity of the MD2 model down a bit, as well as making it easy to edit and animate the texture.
Having a plane for the ripples under the boat came in handy for the collision detection as well. It game me a simple shape to check projectile collisions against (there is another invisible vertical one as well).
The explosions were a key part to the game. We wanted them to be big and look awesome, but at the same time we were limited by the rendering powers of flash.
We decided to take a billboard approach, which is basically some planes that would always face the camera. Usually this technique looks pretty flat, so I experimented with some different styles and finally came up with a way that I think looked pretty good.
The 3D / After Effects guys created and rendered out some explosion animations that were split into two parts – the main explosion and the flat ripple effect on the water. I created an object that had two similar planes – one for the ripple and one for the explosion. The ripple laid flat on the ocean and never moved, whilst the main explosion rotated around a point at the base, an was angled to face the camera.
Depending on the explosion animation, the pivot point would sometimes be moved to compensate for alignment issues.
To make it look better, I got the 3D guys to render out explosion animation from an angle that was similar to that used by the games camera. This helped give the explosions the look of volume and depth.
Path finding was a big part of Warfare Officer – and a part I put off for too long because of fear… I had never done any kind of path finding before so it was all a learning experience.
I did some reading and found a really good post explaining the A* path finding technique – A* Pathfinding for Beginnners. It explained the technique very well and I was able to knock up my own basic system one Sunday afternoon.
I soon had the boats moving around the world following the A* grid, but it didn’t look quite natural. This was mainly because the ships would move to the centre of each grid cell, moving in an almost robotic manner. I set about figuring out a way to smooth out the path to make it a bit smoother and more boat like.
The technique I came up with was to start by generating the A* path. Then I would draw a line from the first node to each subsequent node until I hit an obstacle. If an obstacle was hit, I would store the last point I reached, before starting the process again from this new point.
What I ended up with was a path that smoothed out a lot of the diagonal movements, making the boats move in a much more direct manner.
AI is another one of those things I had never attempted. For a first attempt, I think that the computer puts up a pretty good fight.
My approach was to break the AI into two separate parts that worked together – a boat AI and a master AI.
The master AI would run over everything about every 10-15 seconds looking at everything the boats and base could see and figure out a basic game plan. In most cases this would be to have one ship patrol the defensive third of the map, whilst the other two wander out towards the enemy base. The AI would sometimes call for a full on charge at the enemy base when it recognised that the defenses were weak.
The boats would take the master AI’s objective for them and then decide what exactly they would do. If there was an enemy ship near by they may choose to ignore them or engage depending on what their weapon status. The would also occasionally focus all their attention on the enemy base which helped make them a bit less predictable.
When a boat AI engaged the player it would loop through all of its available weapons and would test to see what had a chance of actually hitting them. Once a collection of possibly successful weapons was collated, it would choose one at random, then attempt to fire it.
The position that the AI would aim for was based on the position of the players boat, with a random X and Y value applied to make it slightly less accurate.
To try and make the battle a bit more even, the enemy ships use a slightly shorter range on all weapons. I found that this was necessary to give the user time to engage computer, otherwise they would usually die before they even had a chance to fire.
To stop the game from ‘cheating’ the AI tracks the player’s boats itself rather than using data from the actual game. It stores the last known position of each boat based on what it can see, so if the player destroys a ship, the AI will store that position as the last known position of the enemy and may consider sending a ship there to seek revenge.
In the end, the whole thing runs of a complex set of if/then statements and is governed by a bunch of random number calls to make decisions. I basically just kept plugging in values until I got a result I was happy with.
That sums up most of the main parts of the game. I hope it has given some insight into how some of the systems work. If you have any questions about a particular part, please feel free to post a comment and I will get back to you!