Let's start with the basics. Open the Starfighter project. You have your standard Initialize and OnEnterFrame procedure templates. In Initailize, add Randomize to reset the random number generator and call InitFlareBackground. The rest is left as an exercise:
Excercise 5-7.
  1. We need to load in the images of the main ship and enemy ship and store them as memory references. It's best to create a separate unit for this so that we can make the memory references global variables that will be visible to any other source file that uses that unit. Call the unit ImageManager and create it in the Images folder. This means you will need to add Images to the Unit Search Path in Project -> Compiler Options (However, some IDEs will prompt you to add the folder to the path automatically. If this happens, select yes so you do not have to manually edit the search path.) Once you create the unit, declare two variables: MainShipImage and EnemyShipImage of type Pointer (simply a memory reference just like an object). Then make a procedure called LoadImages which you should then call from Initialize in the main source file. In the implementation of LoadImages, you can use the LoadImage(Filename) function from FTGraphics where Filename is 'Images/Ship.bmp' and 'Images/Enemy.bmp' for the two ships.
  2. Now that we have the images loaded, we need to create classes to manage the ships. We have two types of ships: a main ship and an enemy ship. How many classes should we create?
  3. Let's start by creating the abstract base class TAbstractShip. Think about what fields it should have (e.g., ships can move). Also think about what methods we need (e.g., drawing methods).
  4. Create the TMainShip class. When you implement StepAndDraw, you can use the FTGraphics procedure DrawTransparentImage(X,Y,ImageRef,TransparentColor) where X and Y are the coordinates of the top left corner of the image, ImageRef is the Pointer to the image and TransparentColor is the background color of the image which should be made transparent when drawn (in the case of the ship images it is clWhite). It's best to center the image on the X and Y coordinates. To do this you will need the Width and Height of the image. GetBitmapExtent(ImageRef,Width,Height) will return the Width and Height of the image in the last two arguments which are passed by reference.
  5. Back in the main project source file, create a variable called MainShip of type TMainShip. Create an instance of TMainShip in Initialize and then call StepAndDraw during OnEnterFrame. Set the ship's initial position to (0,-8).
  6. Create a procedure called HandleUserInput and call it at the top of OnEnterFrame. We do this in order to better organize our code because OnEnterFrame will become quite complex otherwise. Inside of HandleUserInput, make the ship respond to the left and right arrow keys (the key codes are VK_LEFT and VK_RIGHT). The best way to do this is by setting a constant velocity for the ship (let's give it a magnitude of 15). This means that you will also need to modify the StepAndDraw code in TMainShip in order to make the position change when the velocity is non-zero.
  7. The code from the previous problem allows the main ship to move. The only problem is that the ship can disappear off the screen. Modify the code in StepAndDraw so that the X position will not change if such a change moves it out of the range of -12 to 12.
  8. Now let's focus on the enemy ships. This will be a bit more interesting because we will have many enemy ships on the screen at the same time. First, create the class TEnemyShip in a very similar way to how we created TMainShip except with the EnemyShipImage. Then add a constructor in which we initialize the Position to something random for X between -10 and 10 and for Y between 10 and 20 (the latter starts the enemies off the screen to the top). Set the velocity to 0 in X and -10 in Y. Also add a global variable Enemies of type TList to keep track of all of them.
  9. Create a TList instance for the Enemies list in Initialize. Then create a procedure called DrawEnemies. In this procedure, loop through the Enemies list and call StepAndDraw for each enemy. When an enemy drops off the bottom of the screen, remove it from the list. (Y = -10 is the bottom but we should probably use Y = -12 as a cutoff to make sure the enemy is completely off the screen) DrawEnemies itself should be called before MainShip.StepAndDraw inside of OnEnterFrame. And, importantly, at the top of OnEnterFrame, write a statement that creates enemies such that only 1 exists for the first 5 seconds, then 2 after 5 more seconds, then 3, etc. Hint: Use FrameCount which is defined in FTGraphics for this last part.