README.md

December 4, 2022 · View on GitHub

Space Fighter (a complete game & DirectDraw Tutorial)

Description

One day, when you were partoling a far-away sector of the galaxy, when the mission control gave you a special task. You had no idea what it was going to be like.

As ever, offers a COMPLETE game, and a DirectDraw tutorial / explanation of the game, and how to make another one like it.
Game runs at 75fps, even though screenshot shows 50-something. It's just my huge screenshot taker wasting memory and CPU.

More Info

Submitted On2002-06-28 12:45:00
ByXA
LevelIntermediate
User Rating5.0 (25 globes from 5 users)
CompatibilityVB 5.0, VB 6.0
CategoryDirectX
WorldVisual Basic
Archive FileSpace_Figh998106282002.zip

Source Code

A complete DirectDraw Game & Tutorial

        To skip to the tutorial, click here.
        To skip to the bonus content, click here.
        If you are interested in another tutorial in DirectDraw, made by me, you can check out the PingBall Challenge, the same type of tutorial: you get a game, rules, and an instruction on how to make it.

    Space Fighter Challenge.
        Well... here goes the second one. Finish at least 20 levels of this game. You control a ship which has got 100 health points. When you are hit with a laser, you lose 1 health point. If you hit another ship (!!!), you lose 10 health points.
        Your health points are restored every time you enter a new level. You will enter level 2 on 100 points, level 3 on 200 points, level 4 on 400 points. To calculate the  amount of points needed to enter a level you can use this formula: amount=100*2^LevelToEnter .
        You are apposed by a small (you will see just how small it is, when you reach higher levels) fleet of ships. As you progress in levels, the AI on those ships will improve. So will the health points.
        You can use any kind of strategy you like, it all is quite difficult. Post your scores here, and may the best one win!

    DirectDraw Tutorial
        Unlike the PingBall Challenge, this one doesn't contain any resolution code. So, if the game runs slow, decrease the resolution. Please do not decrease the color depth to anything lower than 16-bit - it makes it look bad.

        The program starts with the Form_Load event, in which the mouse is immediately hidden (thanks, Mick!), and then it does to the Init sub.

        The Init sub is the core of the whole program: it initializes, and runs the game (or maybe calls the subs that run the game). First (after setting the error handler), we create DirectDraw, and bind it to our form (Call dd.SetCooperativeLevel(Me.hWnd, DDSCL_FULLSCREEN Or DDSCL_ALLOWMODEX Or DDSCL_EXCLUSIVE)). Then we SetDisplayMode to 800x600 with 16-bit depth - 65025 colors. After creating the description of the primary surface, we create the primary surface from it. The back buffer is then created for the primary buffer.

        Those who know the basic concepts of DirectDraw, are recommended to click here (skips a few paragraphs). However, you might just read on.

        The primary surface represents the screen. Everything that appears on the primary surface, appears on screen. Now, if I was to paint the whole thing directly on the primary surface, the one playing the game would see me painting, and (probably) the screen will flicker. To counter this, people use backbuffers. When you paint onto the backbuffer, user doesn't see anything. Then, in one action (Flip), you paint the entire scene onto the primary surface - the user doesn't see you painting.

        Imagine a surface as an image. You can print the text on (only it's not called printing), or put additional pictures. DirectDraw makes it fast and quick, and adds some features. For example, very easy transparency. Matt Carpenter's A Cool Space Invaders Game uses masks to achieve this. It's painful, and you have to store the masks somewhere as well. To see how I solve this problem, read on.

        Then, to load an image, you need to describe it first. You will need to set it's height & width, before you can load it.

        Then comes the first real code: you have to load the images. COPY CODE: you might want to use UniversalLoad in your programs. Since DirectDraw understands only bitmap images, we will have to re-save the file as bitmap if it isn't already. The sub is quite self-explanatory. The flags I use are standard, and you know them from their name. What I do in the end is that I define that the black color shouldn't be blitted, when a special flag is used. That is the first half of the transparency

        All the small things done (such as creating the starry background, initializing the arrays, fonts), we get onto our 5 line program :

Do
SplashEngine
StoryEngine
GameEngine
Loop

        You can see that the whole program is done in Engine subs. Each Engine sub does it's own things, and is accompanied by a Blt sub with the same first part of the name.

        SplashEngine just scrolls the star field, and displays your ship in the center. Blt sub does this: empties the screen (BltColorFill), and prints the text. Notice the DDBLTFAST_SRCCOLORKEY flag in the blt sub - it makes sure that we use the color key that we defined in the InitSurfaces sub - second part of my transparency. And, this is minimal trouble, and almost no performance decrease.

        StoryEngine controls the small story that we have along with the game - it calls the SplashBlt sub with the text it wants to display.

        GameEngine is the core of the game (again!). It calls (again!) the different subs that drive the game. Let's take a look at those one by one.

        CheckLevel makes sure that we are on the correct level. It is basic and self-explanatory.

        StarFieldProccess take every star, and moves it by it's SpeedY. It also re-spawns the stars when they meet the bottom. Very basic.

        MoveYourShip is responsive for controlling the movement of your ship (how did you guess?). It takes the SpeedX (and SpeedY if a certain constant is true, about that later), adds it, and then handles the consequences.

        MoveAIUnits is a more complex part. It is a loop to call EnemyAI for every enemy, and to re-spawn the enemies when they are killed or hit the bottom.
            EnemyAI is passed with an enemy ID, and enemy's AI level (1-100). It is responsible for what each ship does. Basically, it's a large Select Case, which then uses enemy(ID).location and yourlocation to compute what it should do. It's easy to figure out what it does, and there is nothing special to DirectDraw here

        HandleBullets is probably the most severe computing sub in the entire game. It checks who wants to shoot, checks whether they can shoot, and shoots (if they can). It handles both AI and Player actions. It uses BadWeaponShots and GoodWeaponShots to store the coordinates of the laser shots.
        Every time it's called, it cleans-up it's old bullets, not to waste memory. Then it uses Collides function to determine the collisions between laser shots and targets. It does that for both sides. It also handles the damage done by this shot. Then, (as a bonus) it checks for collisions between your ship and enemy ships.
        Collides is a sub that You can copy, and use in your own projects. It checks if the figure1 collides with figure2 - a sort of collision detection sub. I think it's correct, at least 90% of this game relies on it..

        Gameblt, finally, is the sub that paints it all. This one is quite complex so let's walk through it.
        CheckScreen (Copy Code: CheckScreen, ExModeActive, and adjust the name of the sub that should be called to restore the surfaces) )is a standard sub in any blt sub I wrote - it checks if the user hadn't switched away from us (ALT-TAB or CTRL-ALT-DEL). If the user didn't, nothing happens. However, if he/she did, the sub would be in the loop until he switches back. It then would restore the surfaces.
        BltColorFill just blanks the entire screen with black color.
        StarFieldToBackBuffer
just paints the stars() array to the back buffer. Simple. It uses the star surface to create them (BltFast) on the screen.
        Then it paints all the standard text onto the top left corner.
        Then, using loops, it paints Enemy ships, your laser shots, and enemy laser shots. If the loss variable is not true, it paints your ship. If it is, it paints the You Lost! message. Then the whole thing is Fliped onto the primary surface. That is it.

        If you want to skip this, click here.

        On Blitting. There is a number of different Blt subs used by DirectDraw.

  • Blt allows you to strech what you are drawing. It is a little slower then (next one)

  • BltFast - supply the x,y coordinates, plus a rectangle - and it paints. It's faster.

  • BltColorFill - doesn't paint an image, just a huge box filled with the color you specify.

  • There are other blts, but they are little or no use in the scope of this tutorial.

On RECT.

        You select which part of the picture you want copied/copied to. In our case, we want the whole picture, so we can just forget about modifying this, and just pass it as it is. If you want to use it, set Left and Top as you would normally, while Right should be Left + Width, Bottom should be Top + Height.

        So, how does this thing work? It is tied together by the Form_Keydown and Form_KeyUp events. Keydown basically provides control of the game - it allows you to pause, start or end the game, as well as checking your Left & Right arrows (Up & Down ones as well...), Space, and other keys. It sets variables that can be used, if the Engine running is right. Otherwise, they are just ignored.

    Bonus Content.

        Bonuses? Quite a few actually. Check the ModTypes for the declarations of various constants are used. Most of the bonuses are achieved by changing these. Let's take them one by one:

  • AllowYMovement - if true, it allows you to use Up & Down arrows to move vertically. Recommended: False.
  • AmountOfStars - specifies how many stars are there in the background. You can increase the setting if you want a more starry background, or would like to slow down (for some reason) the game.
  • MaxStarSpeed - specifies the maximum speed with which a star should move. Larger numbers will be uncomfortable.
  • MaxGoodBullets - the maximum amount of your shots that can be in the air at once. You can lower this value if you want a more challenging game.
  • MaxBadBullets - the maximum amount of bad shots that cen be in the air at once. You can lower the value to make it easier on higher levels, or put it sky-high to  have certain death on lvl 55.

         That's about it. Thanks for reading this far. If you liked it, vote.

The END