;------------------------------------------------------------------------------- ; ; ;-------------------------------; ; ; Game On ; ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,; ; ;,,,, ;----------------------------------------------- ; Introduction ; ;---- ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ; ; You wanted to build games, right? ; Well you've come to the right place :) ; ; Here's an overview of ; what you will find here: ; ; Graphics: Graphics modes. ; Buffering: Flicker free graphics. ; Media: Images, sound and music. ; Input: Keyboard, mouse and joystick control. ; Timing: Timing is the key. ; Concepts: How games can be built. ; ; This part contains lots of sections. ; In fact, this program, as a whole, ; and even some sections ; can't be run at all. ; ; You will have to copy and paste ; each or some sections or parts ; of some sections to try it out. ; ; Although if you followed all ; previous parts you'll be able ; to understand a lot of it ; without even having to run it :) ; ;,,,, ;----------------------------------------------- ; Graphics ; ;---- ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ; ; So you know about programming basics ; as well as some graphical commands ; like Color and Text. ; ; It's time for some real graphics. ; ; Most, if not all visual elements in Blitz ; rely on the current graphics mode. ; ; When you run a program in Blitz ; the graphics mode will be set ; for you, automatically, ; to a resolution of, ; for example, 400x300, ; depending on the videocard. ; ; Actually that's exactly ; what happened so far. ; ; When you run a program without ; setting the graphics mode ; a lot of strange things can happen ; such as colors not working ; or text not printing. ; ; Even though you can do a lot ; without setting the graphics mode, ; it's best to always set it ; before doing anything visual. ; ; You can set a graphics mode ; with the Graphics command. Graphics 640 , 480 ; A resolution of 640x480 (width x height) ; A graphics mode is a bit like a graphics session. ; Although there can be only one session at a time. ; Each time you close or open a new graphics mode, ; all visual elements will get wiped. ; Much like redimensioning an array. ; Here's how to close a graphics session. EndGraphics ; Actually, you don't even have to close ; the graphics mode because at the end ; of your program Blitz will do it for you. End ; You can also easily change between ; graphics modes without using ; the EndGraphics command. Graphics 800 , 600 Graphics 640 , 480 ; Only specific graphics modes are available. ; This, again, depends on the videocard. ; Some cards have 10 different modes, ; and others have dozens. ; ; You can figure out which graphics modes ; are available to you by checking out, ; for example, the CountGfxModes command. ; ; I'll leave that part up to you ; to find out more about ;) ; ; Still, a very compatible graphics mode ; is 640x480 so I'll stick to that, ; as you can be very sure it will run ; on any videocard. ; ; The Graphics command has 2 more ; parameters which are optional. ; ; Graphics Width , Height , Depth , Mode ; ; Width and Height you are already know. ; ; Depth is the color depth, usually 16 ; or 32 (bit), sometimes even 24. ; It is however recommended to let ; Blitz handle the color depth. ; So specifying a value of 0 ; (or not using the parameter) ; will automatically detect ; a color depth. ; ; Mode specifies what state ; the game window should be in. ; Here are the available states: ; ; 0 - Automatic ; ; When running in debug mode ; (you know debug mode, right?) ; the game will be run windowed, ; e.g. in a window :) ; ; When not running in debug mode ; the game will run fullscreen. ; ; 1 - Fullscreen ; ; This will force the game ; to run in fullscreen mode. ; ; 2 - Windowed ; ; And this will force the game ; to run in a window. ; ; 3 - Scaled Window ; ; You can also force the game ; to run in a resizable window. ; So you can stretch the ; contents of the window. Graphics 1000 , 100 , 0 , 3 ; This will set a 1000x100 scalable window ; with autodetected colordepth. ; ; You can find out what the current ; graphics mode settings are using ; the GraphicsWidth, GraphicsHeight ; and GraphicsDepth functions. ; ; But you could also use constants ; or global variables for that :) ; ;,,,, ;----------------------------------------------- ; Buffering ; ;---- ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ; ; Imagine a program with a rectangle ; scrolling from left to right. ; ;,,,, ,, , , Graphics 640 , 480 For PosX = 1 To 640 Rect PosX , 240 , 10 , 10 , False ; Draw a 10x10 rectangle. Delay 5 ; Wait 5 milliseconds. Cls Next End ;---- -- - - ; ; Two new commands, Rect and Delay. ; You can check them out (F1) ; to see how they work. ; ; Let's try a larger rectangle ; only this time, filled, ; with some text on it. ; ;,,,, ,, , , Graphics 640 , 480 For PosX = 1 To 640 Color 64 , 128 , 64 Rect PosX , 240 , 100 , 100 , True Color 128 , 255 , 128 Text PosX , 240 , "FILLED" Delay 5 Cls Next End ;---- -- - - ; ; Still looking okay, ; though it jerks a lot. ; ; Let's add the Text outline function ; from the previous part. ; ; And draw an outlined message ; 9 times inside the box. ; ;,,,, ,, , , Function TextOutLine ( Pos_X% , Pos_Y% , Message$ ) Local X% Local Y% Color 128 , 255 , 128 ; Altered. For X = -1 To 1 For Y = -1 To 1 Text Pos_X + X , Pos_Y + Y , Message Next Next Color 0 , 0 , 0 Text Pos_X , Pos_Y , Message End Function Graphics 640 , 480 For PosX = 1 To 640 Color 64 , 128 , 64 Rect PosX , 240 , 100 , 100 , True For Y = 0 To 2 For X = 0 To 2 TextOutline PosX + X * 30 , 240 + Y * 40 , "OUT" Next Next Delay 5 Cls Next End ;---- -- - - ; ; Maybe you can see that ; it's starting to flicker a bit. ; ; If not, we'll just increase ; the number of times we ; draw the outlined text. ; ;,,,, ,, , , Function TextOutLine ( Pos_X% , Pos_Y% , Message$ ) Local X% Local Y% Color 255 , 255 , 255 For X = -1 To 1 For Y = -1 To 1 Text Pos_X + X , Pos_Y + Y , Message Next Next Color 0 , 0 , 0 Text Pos_X , Pos_Y , Message End Function Graphics 640 , 480 For PosX = 1 To 640 Color 128 , 128 , 128 Rect PosX , 240 , 100 , 100 , True For Y = 0 To 9 TextOutline PosX , 240 + Y * 10 , String ( "@" , 13 ) Next Delay 5 Cls Next End ;---- -- - - ; ; If you still can't see a flicker, ; I'm sorry, but your computer is too fast! :P ; ; So how do we get rid of this flickering? ; (And how do we make it more smooth?) ; ; There's a technique called double buffering ; where you draw to an invisible screen ; and swap it with the visible screen ; when you're done drawing. ; ; You can picture it like a piece of paper. ; ; Rear ; , ; ,' ; |`-, |,' ; | `-, '-- ; | `-, ; | | ; | | ; '-, | ; `-, | ; __, `-,| ; ,'| ; ,' ; ' ; Front ; ; The idea is to always draw ; to the rear side of the paper. ; ; When you're done drawing you turn it around ; so the front becomes the back and vise versa. ; ; Then you clear the rear side ; and everything starts from the beginning again. ; ; The rear side of the paper is called ; the BackBuffer (). ; ; So no matter how you twist or turn the paper, ; the BackBuffer () will always be the rear. BackBuffer () ; The visible (front) side is called, ; you guessed it, the FrontBuffer (). FrontBuffer () ; You can swap the contents of the front ; and back buffer with the Flip command. Flip ; After setting the graphics mode, ; the default drawing buffer is ; the front buffer. ; ; So everything you draw, ; and the things that we drew, ; will end up on the front buffer, ; e.g. instantly on screen. ; ; To change the current drawing buffer ; you can use the SetBuffer command. SetBuffer BackBuffer () ; As you can see BackBuffer () is actually ; a function returning a value. ; You could call this a buffer handle. ; And SetBuffer takes such handles ; as a parameter. ; ; The command above changes the ; drawing cursor to the back buffer, ; e.g. the rear side of the paper. ; ; So all things we draw now ; will not be visible at all ; until we turn the paper. ; ; Let's try this in a program. ; ;,,,, ,, , , ; Set graphics mode. Graphics 640 , 480 ; Now drawing to the rear side of the paper. SetBuffer BackBuffer () ; Starting at top of screen. PosY = 0 Repeat ; Orange color. Color 255 , 128 , 0 ; Draw a centered circle. Oval 320 - 50 , PosY - 50 , 100 , 100 , False ; Turn the paper, swap front with rear. Flip ; Clear rear side. Cls ; Move circle downwards. PosY = PosY + 2 ; Until we reach the bottom. Until PosY > 480 End ;---- -- - - ; ; It should be very smooth now. ; (and flickerfree :P) ; ; You may have noticed that ; the Delay command is gone. ; Actually the Flip command ; is now delaying the program ; for us, automatically. ; ; After flipping the screen, ; so after swapping the front with the rear, ; e.g. after turning the paper, ; the Flip command will wait ; for the monitor to refresh. ; ; This will produce very smooth results. ; E.g. smoother than, for example, using Delay ; without doing all kinds of tricky stuff. ; ; If your monitor refresh rate is very high, ; say, 85Hz, the circle will move down faster ; than when using a refresh rate of 60Hz. ; ; This can be fixed in various ways. ; But because this is actually a timing issue ; we'll stop by that topic first. ; ;,,,, ;----------------------------------------------- ; Media ; ;---- ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ; ; No, not the press. ; Multimedia more like. ; Images, sounds and music! ; ; Do you have any image handy? ; I've included a crosshair image ; for you to try out. ; It should be in the same ; directory you're running ; the program from. ; ; Let's try it out. ; ;,,,, ,, , , Graphics 640 , 480 ; Load the image. Image = LoadImage ( "Crosshair.bmp" ) ; Make sure it was loaded. If Image <> 0 ; Draw the image. DrawImage Image , 0 , 0 Else Print "Image not loaded." End If WaitKey End ;---- -- - - ; ; You can use LoadImage to ; load an image into memory ; and store its handle in ; a variable of your choice ; to keep track of it. ; ; If an image was not loaded ; or something went wrong ; a value of 0 is returned. ; ; DrawImage can be used to ; draw the image to the screen ; at a location of your desire. ; ; If in any case you'd want to ; wipe an image from memory ; you can use the FreeImage command. FreeImage Image ; These image handles are indeed ; very similar to pointers. ; Only pointers can't end up ; missing in action because ; you can use Blitz' native ; keywords to hunt them down. ; ; If you were to load an image ; and store its handle, ImageHandle = LoadImage ( "MyImage.BMP" ) ; and then forget its handle, ImageHandle = 0 ; you will never be able to ; retrieve the image. ; So it's gone forever, ; missing in action, ; still existing ; but hanging around ; somewhere in memory. ; ; The only way you'd be ; able to free it again ; is by using either the ; Graphics or EndGraphics command :P ; ; You can also create images manually, ; draw to them on the fly, ; and use them in your game. ; ; For this you can use ; the CreateImage command. ImageHandle = CreateImage ( Width , Height ) ; Maybe you'll remember ; that you can set the ; drawing buffer using ; the SetBuffer command. ; ; Well, an image can also ; be used as a buffer ; using the ImageBuffer command. ; ; Just like the front and back buffers. ; ; SetBuffer -> FrontBuffer () ; -> BackBuffer () ; -> ImageBuffer ( ImageHandle ) SetBuffer ImageBuffer ( ImageHandle ) ; Now you can draw to the image ; as if it were the screen. ; Usually a little bit smaller ; than the screen though :P ; ;,,,, ,, , , Graphics 640 , 480 ; Create an image. ImageHandle = CreateImage ( 100 , 100 ) ; Now drawing on the image. SetBuffer ImageBuffer ( ImageHandle ) ; Dark pink. Color 224 , 32 , 104 ; Drawing a filled circle. Oval 0 , 0 , 100 , 100 , True ; Draw to screen. SetBuffer FrontBuffer () DrawImage ImageHandle , 320 - 50 , 240 - 50 WaitKey End ;---- -- - - ; ; There's a lot you can do ; with images but I'll leave ; most of it up to you to find out. ; ; For now, let's add some sound. ; ;,,,, ,, , , ; Load the sound. Sound = LoadSound ( "Where.wav" ) ; If it was loaded succesfully. If Sound <> 0 ; Play the sound. PlaySound Sound Else Print "Sound not loaded." End If WaitKey End ;---- -- - - ; ; As with images, ; the LoadSound command ; returns a sound handle ; which you can then use to, ; for example, play the sound. ; ; You can even alter the default ; volume, pitch and panning. ; ; You can play sounds and music ; with various formats; ; WAV, MP3, OGG, MOD, S3M, ; IT and XM just to name a few. ; ; To free a sound again, ; as with images, ; you can call FreeSound. FreeSound Sound ; There's a way to have ; more control over ; the sounds being played. ; ; Modern soundcards have ; 32 channels so you have ; 32 slots to play your sounds. ; ; When playing a sound, PlaySound Sound ; it is actually returning a value. Channel = PlaySound ( Sound ) ; The value is the channel handle ; which you can use to fool around ; with the sound currently playing. ; ; You can actually change ; pitch, volume and panning ; while it is playing! ; ; When you want to stop playing ; the sound prematurely, ; you can use StopChannel. StopChannel Channel ; Again, very similar to ; pointers and image handles. ; ; We'll put this into action. ; ;,,,, ,, , , ; Load the sound. Sound = LoadSound ( "Starglider.mp3" ) ; If it was loaded succesfully. If Sound <> 0 ; Play the sound. Channel = PlaySound ( Sound ) ; Wait until done playing. Repeat Until Not ChannelPlaying ( Channel ) Else Print "Sound not loaded." WaitKey End If End ;---- -- - - ; ; Now you can no longer ; abort the program prematurely :P ; ; The program plays the sound ; until reaching the end ; of the sound. ; ; Now, I really hope you're ; not playing any large files :) ; ; There are a lot of commands ; I will not explain here ; so check them out ; and play around with them =) ; ; If you do not have ; a command reference ; in your copy of Blitz, ; there's an online version ; which you can find here: http://www.blitzbasic.com/b3ddocs/command_list_2d_cat.php ; For example you can ; check out the commands for: ; ; Basic, Maths, String, ; Graphics, Text, Image and Sound. ; ; E.g. the things we just 'handled' :P ; ; There are more things ; that use handles as well, ; like banks, to store ; information in any way you want, ; or fonts, to change ; the way your text looks, ; or networking, to communicate ; with another computer ; on your local network, ; through a modem or ; via the internet. ; ;,,,, ;----------------------------------------------- ; Input ; ;---- ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ; ; We displayed a crosshair on screen before ; but we weren't able to control it yet. ; ; Let's control it with the mouse. ; So wherever the mouse moves to, ; our crosshair will move to as well. ; ; We can use the MouseX () and MouseY () ; functions to know the current pixel ; location of the mouse on screen. MouseX () MouseY () ; So we'll just do what we did the other time ; when drawing the crosshair. ; Only we'll add the location of the mouse. ; ; Oh, before you run it I have to tell you ; that you can exit the program ; by pressing the left mouse button. ; ;,,,, ,, , , Graphics 640 , 480 SetBuffer BackBuffer () Crosshair = LoadImage ( "Crosshair.bmp" ) Repeat DrawImage Crosshair , MouseX () , MouseY () Flip Cls Until MouseHit ( 1 ) End ;---- -- - - ; ; If you're running this in Debug mode, ; and hopefully you are, ; you'll find that the Windows mouse cursor ; is actually overlapping our crosshair. ; ; Now if you ran the program in fullscreen ; you wouldn't see a mousecursor. ; A way to hide the mousecursor ; when it is over our game window ; is to call the HidePointer command. HidePointer ; Logically there's ShowPointer ; to make it visible again. ; ; You saw we used MouseHit ( 1 ) ; to detect a mouse button press. ; ; It returns True if you pressed it ; and False if you didn't. ; ; Now, the parameter doesn't ; indicate the number of times ; you can press it. ; ; Rather it means which button ; you have to press. ; ; 1 - Left mouse button ; 2 - Right mouse button ; 3 - Middle mouse button MouseHit ( 2 ) ; This would tell you ; if you pressed the ; right mouse button. ; (or the wrong :) ; ; There's also the MouseDown ; command to know if you're ; holding down the button. ; ; Similar to the MouseHit ; and MouseDown functions, ; there are the KeyHit ; and KeyDown functions ; which are, you guessed it, ; for the keyboard. ; ; The parameter you specify ; is the scancode a key has. ; There is a list of scancodes ; in your copy of Blitz ; in the command reference. ; ; If not.. Const Key1 = 2 Const Key2 = 3 Const Key3 = 4 Const Key4 = 5 Const Key5 = 6 Const Key6 = 7 Const Key7 = 8 Const Key8 = 9 Const Key9 = 10 Const Key0 = 11 Const KeyQ = 16 Const KeyW = 17 Const KeyE = 18 Const KeyR = 19 Const KeyT = 20 Const KeyY = 21 Const KeyU = 22 Const KeyI = 23 Const KeyO = 24 Const KeyP = 25 Const KeyA = 30 Const KeyS = 31 Const KeyD = 32 Const KeyF = 33 Const KeyG = 34 Const KeyH = 35 Const KeyJ = 36 Const KeyK = 37 Const KeyL = 38 Const KeyZ = 44 Const KeyX = 45 Const KeyC = 46 Const KeyV = 47 Const KeyB = 48 Const KeyN = 49 Const KeyM = 50 Const KeyPad7 = 71 Const KeyPad8 = 72 Const KeyPad9 = 73 Const KeyPad4 = 75 Const KeyPad5 = 76 Const KeyPad6 = 77 Const KeyPad1 = 79 Const KeyPad2 = 80 Const KeyPad3 = 81 Const KeyPad0 = 82 Const KeyF1 = 59 Const KeyF2 = 60 Const KeyF3 = 61 Const KeyF4 = 62 Const KeyF5 = 63 Const KeyF6 = 64 Const KeyF7 = 65 Const KeyF8 = 66 Const KeyF9 = 67 Const KeyF10 = 68 Const KeyF11 = 87 Const KeyF12 = 88 Const KeyLeftShift = 42 Const KeyRightShift = 54 Const KeyLeftAlt = 56 Const KeyRightAlt = 184 Const KeyLeftCtrl = 29 Const KeyRightCtrl = 157 Const KeyCapsLock = 58 Const KeyNumLock = 69 Const KeyScrollLock = 70 Const KeySpace = 57 Const KeyEnter = 28 Const KeyTab = 15 Const KeyBackSpace = 14 Const KeyInsert = 210 Const KeyDelete = 211 Const KeyHome = 199 Const KeyEnd = 207 Const KeyPageUp = 201 Const KeyPageDown = 209 Const KeyEscape = 1 Const KeyPause = 197 Const KeyLeftWin = 219 Const KeyRightWin = 220 Const KeyApps = 221 Const KeyBackQuote = 41 Const KeyMinus = 12 Const KeyEquals = 13 Const KeyLeftBracket = 26 Const KeyRightBracket = 27 Const KeyBackSlash = 43 Const KeySemiColon = 39 Const KeyQuote = 40 Const KeyComma = 51 Const KeyPeriod = 52 Const KeySlash = 53 Const KeyPadSlash = 181 Const KeyPadAsterisk = 55 Const KeyPadMinus = 74 Const KeyPadPlus = 78 Const KeyPadEnter = 156 Const KeyPadPeriod = 83 Const KeyArrowUp = 200 Const KeyArrowDown = 208 Const KeyArrowLeft = 203 Const KeyArrowRight = 205 ; In fact, you could ; copy and paste this list ; in your program. ; (above or below) ; ; Then you won't have to ; remember which scancode ; belongs to which key. ; ; You could also paste this ; in a separate BB file. ; And use the Include command ; in your program to glue it ; to your current program ; when you hit Run. Include "ScanCodes.BB" ; This is also how you can ; separate your program ; into multiple files. ; ; When you use the Include command, ; Blitz will actually think that all ; little BB files are one big program. ; ; Let's try out some keys in a program. ; I'll use the numbers for them ; instead of the name. ; ;,,,, ,, , , SetBuffer BackBuffer () Repeat If KeyDown ( 200 ) Then Text 0 , 0 , "Up" Else If KeyDown ( 208 ) Then Text 0 , 0 , "Down" Else Text 0 , 0 , "Nowhere" End If Flip Cls Until KeyHit ( 1 ) ; Esc End ;---- -- - - ; ; We'll continue with a block ; that moves from left to right ; when you press the spacebar. ; ;,,,, ,, , , Graphics 640 , 480 SetBuffer BackBuffer () Block_PosX = 100 ; Position Block_Dir = 10 ; Direction (and speed) Repeat If KeyDown ( 57 ) ; Space ; Move the block. Block_PosX = Block_PosX + Block_Dir ; If crossing left or right boundary. If Block_PosX < 100 Or Block_PosX > 540 ; Reverse direction. Block_Dir = -Block_Dir End If End If ; Display the block, but centered. Rect Block_PosX - 50 , 240 - 50 , 100 , 100 , False Flip Cls Until KeyHit ( 1 ) End ;---- -- - - ; ; Let's add some more control. ; For example being able to ; move it left and right manually. ; ;,,,, ,, , , Const KeyArrowLeft = 203 Const KeyArrowRight = 205 Const KeyEscape = 1 Graphics 640 , 480 SetBuffer BackBuffer () Block_PosX = 320 ; Position Repeat ; If pressing left arrow. If KeyDown ( KeyArrowLeft ) ; Move block left. Block_PosX = Block_PosX - 10 End If ; If pressing right arrow. If KeyDown ( KeyArrowRight ) ; Move block right. Block_PosX = Block_PosX + 10 End If ; Display the block, but centered. Rect Block_PosX - 50 , 240 - 50 , 100 , 100 , False Flip Cls Until KeyHit ( KeyEscape ) End ;---- -- - - ; ; What if we wanted to stop the block ; at the screen boundaries? ; ; Let's put these boundaries ; in constants as well ; since the boundaries ; are indeed constant :) ; ;,,,, ,, , , Const KeyArrowLeft = 203 Const KeyArrowRight = 205 Const KeyEscape = 1 Const LeftBoundary = 50 Const RightBoundary = 590 Graphics 640 , 480 SetBuffer BackBuffer () Block_PosX = 320 ; Position Repeat ; If pressing left arrow. If KeyDown ( KeyArrowLeft ) ; Move block left. Block_PosX = Block_PosX - 10 End If ; If pressing right arrow. If KeyDown ( KeyArrowRight ) ; Move block right. Block_PosX = Block_PosX + 10 End If ; If crossing left boundary. If Block_PosX < LeftBoundary ; Make it stick to the boundary. Block_PosX = LeftBoundary End If ; If crossing right boundary. If Block_PosX > RightBoundary ; Make it stick to the boundary. Block_PosX = RightBoundary End If ; Display the block, but centered. Rect Block_PosX - 50 , 240 - 50 , 100 , 100 , False Flip Cls Until KeyHit ( KeyEscape ) End ;---- -- - - ; ; You can see there's a lot in there ; we can put in constants as well ; as a lot of things actually do not change. ; ; But, why put them in constants anyway? ; Well, imagine a program where everything ; is based on a resolution of 640x480. ; Such as those boundaries we used before. ; ; If you're not using constants for this, ; you'd have to change each and every ; value in the program by hand. ; ; You can imagine how easy it is ; to alter some values if you ; have to change only one! :) ; ; So let's stick everything we can in constants ; without messing with the program too much. ; ;,,,, ,, , , Const ScreenWidth = 640 Const ScreenHeight = 480 Const KeyArrowLeft = 203 Const KeyArrowRight = 205 Const KeyEscape = 1 Const BlockSize = 100 Const BlockSpeed = 10 Const LeftBoundary = 0 + BlockSize/2 Const RightBoundary = ScreenWidth - BlockSize/2 Graphics ScreenWidth , ScreenHeight SetBuffer BackBuffer () Block_PosX = ScreenWidth/2 Repeat ; Move block. If KeyDown ( KeyArrowLeft ) Then Block_PosX = Block_PosX - BlockSpeed If KeyDown ( KeyArrowRight ) Then Block_PosX = Block_PosX + BlockSpeed ; Limit block position. If Block_PosX < LeftBoundary Then Block_PosX = LeftBoundary If Block_PosX > RightBoundary Then Block_PosX = RightBoundary ; Display block. PosX = Block_PosX - BlockSize/2 PosY = ScreenHeight/2 - BlockSize/2 Rect PosX , PosY , BlockSize , BlockSize , False Flip Cls Until KeyHit ( KeyEscape ) End ;---- -- - - ; ; Yes, it has become more math intensive. ; But I think you'll agree that it's pretty easy ; to simply change the size of the block ; without having to change anything else ; and the program still doing what we want. ; E.g. blocking the block at the screen edges. ; ; Let's go back to our crosshair image ; and move it around using the arrow keys. ; ;,,,, ,, , , Const ScreenWidth = 640 Const ScreenHeight = 480 Const KeyArrowUp = 200 Const KeyArrowDown = 208 Const KeyArrowLeft = 203 Const KeyArrowRight = 205 Const KeyEscape = 1 Const Speed = 10 Graphics ScreenWidth , ScreenHeight SetBuffer BackBuffer () Crosshair = LoadImage ( "Crosshair.bmp" ) PosX = ScreenWidth / 2 PosY = ScreenHeight / 2 Repeat If KeyDown ( KeyArrowUp ) Then PosY = PosY - Speed If KeyDown ( KeyArrowDown ) Then PosY = PosY + Speed If KeyDown ( KeyArrowLeft ) Then PosX = PosX - Speed If KeyDown ( KeyArrowRight ) Then PosX = PosX + Speed DrawImage Crosshair , PosX , PosY Flip Cls Until KeyHit ( KeyEscape ) End ;---- -- - - ; ; There are also joystick commands ; such as JoyXDir, JoyYDir and JoyDown. ; ; Make sure to check out the Input ; section of the command reference ; to see which other commands ; are available. ; ;,,,, ;----------------------------------------------- ; Timing ; ;---- ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ; ; You remember the Delay command, right? ; Where you can halt the program ; for any number of milliseconds. ; ; You'll also remember the MilliSecs () function ; which will give you the number of ; milliseconds since Windows started. ; ; You can use the MilliSecs command ; in the same way as the Delay command. Delay 1000 ; This will halt the program for 1 second. ; ; MilliSecs () will count up ; to a value of 2,147,483,647 ; (which takes 24.9 days). ; ; So you can look at the time like a stopwatch ; to see how long something takes. Start = MilliSecs () ; Do something. Finish = MilliSecs () HowLong = Finish - Start ; Which can be interpreted as: ; ; Start Finish ; | -----> | ; v v ; , _,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,_ , ; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ; | | ; |<----------------->| ; HowLong ; ; Where MilliSecs () is a constantly ; increasing value, hence the arrow. ; ; You can use this same principle for ; any or all of your timing routines. ; ; But why would we want to ; make it so complicated? ; ; Well, for example, to wait 1 second, ; and not halt the program totally, ; while we can do something else ; in the meantime. ; ;,,,, ,, , , HowLong = 1000 Start = MilliSecs () Finish = Start + HowLong Repeat ; Do something else. Until MilliSecs () >= Finish End ;---- -- - - ; ; Ofcourse you can write this in various ways, ; but it's basically always the same; ; to see how long something takes. ; ; Below is another way of doing it. ; We'll put something on the screen ; to make it more interesting. ; ;,,,, ,, , , SetBuffer BackBuffer () HowLong = 1000 Start = MilliSecs () Finish = Start + HowLong While MilliSecs () < Finish Counter = Counter + 1 Text 0 , 0 , Finish - MilliSecs () Flip Cls Wend End ;---- -- - - ; ; As you can see it's a counter ; counting down to zero. ; You know, like a bomb :P ; ; Okay now let's try moving something ; at exactly 1 pixel per millisecond. ; E.g. 1000 pixels per second. ; ; Some more code below ; to make a thing move around ; in 4 directions. ; ;,,,, ,, , , Graphics 640 , 480 Const MoveSize = 100 Const OvalSize = 50 Const Dir_Right = 0 Const Dir_Down = 1 Const Dir_Left = 2 Const Dir_Up = 3 SetBuffer BackBuffer () Repeat ; Check the current time. Now = MilliSecs () ; Number of pixels to move is ; number of milliseconds passed ; since last time. Speed = Now - LastTime ; Remember what time it was. LastTime = Now ; See if the thing ; crosses a boundary ; and change its direction ; and position if so. Select Direction Case Dir_Right If Where >= MoveSize Direction = Dir_Down Where = 0 End If Case Dir_Down If Where >= MoveSize Direction = Dir_Left Where = MoveSize End If Case Dir_Left If Where <= 0 Direction = Dir_Up Where = MoveSize End If Case Dir_Up If Where <= 0 Direction = Dir_Right Where = 0 End If End Select ; Update position of thing ; and decide on position on screen ; all depending on direction. Select Direction Case Dir_Right Where = Where + Speed PosX = Where PosY = 0 Case Dir_Down Where = Where + Speed PosX = MoveSize PosY = Where Case Dir_Left Where = Where - Speed PosX = Where PosY = MoveSize Case Dir_Up Where = Where - Speed PosX = 0 PosY = Where End Select ; Draw the thing (centered). CenterX = PosX + OvalSize / 2 CenterY = PosY + OvalSize / 2 Color 128 , 32 , 0 Size = OvalSize * 4 / 4 Oval CenterX - Size/2 , CenterY - Size/2 , Size , Size Color 255 , 0 , 0 Size = OvalSize * 3 / 4 Oval CenterX - Size/2 , CenterY - Size/2 , Size , Size Color 255 , 128 , 0 Size = OvalSize * 2 / 4 Oval CenterX - Size/2 , CenterY - Size/2 , Size , Size Color 255 , 255 , 0 Size = OvalSize * 1 / 4 Oval CenterX - Size/2 , CenterY - Size/2 , Size , Size Flip Cls Until KeyHit ( 1 ) End ;---- -- - - ; ; Maybe a bit too much code ; for the moment :P ; ; We'll get back to our ; controllable crosshair program. ; The one with keyboard control. ; ; We want it to move slower ; by making it dependent ; on how long a second takes. ; ; Let's move it 1 pixel per 10 ms. ; ;,,,, ,, , , Const ScreenWidth = 640 Const ScreenHeight = 480 Const KeyArrowUp = 200 Const KeyArrowDown = 208 Const KeyArrowLeft = 203 Const KeyArrowRight = 205 Const KeyEscape = 1 Graphics ScreenWidth , ScreenHeight SetBuffer BackBuffer () Crosshair = LoadImage ( "Crosshair.bmp" ) ; Increase the precision ; to make it smoother ; and more accurate. PosX# = ScreenWidth / 2 PosY# = ScreenHeight / 2 Repeat Now = MilliSecs () Speed# = Now - LastTime ; Increased precision. LastTime = Now ; Decrease speed tenfold. Speed = Speed / 10 If KeyDown ( KeyArrowUp ) Then PosY = PosY - Speed If KeyDown ( KeyArrowDown ) Then PosY = PosY + Speed If KeyDown ( KeyArrowLeft ) Then PosX = PosX - Speed If KeyDown ( KeyArrowRight ) Then PosX = PosX + Speed DrawImage Crosshair , PosX , PosY Flip Cls Until KeyHit ( KeyEscape ) End ;---- -- - - ; ; What about animation? ; ; We'll use the animated running guy ; which should be included with this tutorial. ; ; The image contains 4 unique frames of 32x32 ; and we can use LoadAnimImage to load it. Image = LoadAnimImage ( "Running.bmp" , 32 , 32 , 0 , 4 ) ; We can animate the image ; by using a variable to keep track ; of the current frame. ; ; How fast the animation runs ; we can let depend on MilliSecs (). ; Let's begin with a delay of ; 100 milliseconds per frame. ; ; Remember how to do that? Now = MilliSecs () If Now > LastTime + 100 LastTime = Now ; Do your thing. End If ; Here's another way: Now = MilliSecs () If Now - LastTime >= 100 LastTime = Now ; Do your thing. End If ; You think you know a little bit ; what the program could look like? ; ;,,,, ,, , , Const ScreenSizeX = 640 Const ScreenSizeY = 480 Const AnimFile$ = "Running.bmp" Const AnimSize = 32 Const AnimFrames = 4 Const AnimDelay = 100 ; Ms Local Image Local Frame Local Now Local LastTime Graphics ScreenSizeX , ScreenSizeY Image = LoadAnimImage ( AnimFile , AnimSize , AnimSize , 0 , AnimFrames ) LastTime = MilliSecs () SetBuffer BackBuffer () Repeat ; What's the time? Now = MilliSecs () ; Has enough time passed? If Now - LastTime >= AnimDelay ; Remember the time. LastTime = Now ; Increase the frame number. Frame = Frame + 1 ; Keep frame in range of [0..3]. ; Yes, it starts from zero! If Frame = 4 Then Frame = 0 End If ; Draw animated image from center of screen. DrawImage Image , ScreenSizeX/2 , ScreenSizeY/2 , Frame Flip Cls Until KeyHit ( 1 ) End ;---- -- - - ; ; Now we'll expand the program a bit ; by letting the character move ; from left to right in a loop ; at the bottom of the screen. ; ; We're gonna have to fiddle a bit ; with the movement speed ; e.g. to find the best ; running speed (in pixels) ; to match with the animation speed. ; ; Like, it doesn't look good ; if the character is doing warp 9 ; while animating in slow-motion :P ; ;,,,, ,, , , Const ScreenSizeX = 640 Const ScreenSizeY = 480 Const AnimFile$ = "Running.bmp" Const AnimSize = 32 Const AnimFrames = 4 Const AnimDelay = 100 ; Ms Const MoveSpeed = 7 ; Pixels per AnimDelay (7 pixels every 100ms). Local Image Local Frame Local Now Local LastTime Local PosX Local PosY Graphics ScreenSizeX , ScreenSizeY Image = LoadAnimImage ( AnimFile , AnimSize , AnimSize , 0 , AnimFrames ) LastTime = MilliSecs () PosX = -AnimSize ; Just off-screen to the left. PosY = ScreenSizeY - AnimSize ; Just above screen bottom. SetBuffer BackBuffer () Repeat ; What's the time? Now = MilliSecs () ; Has enough time passed? If Now > LastTime + AnimDelay ; Remember the time. LastTime = Now ; Increase the frame number. Frame = Frame + 1 ; Keep frame in range of [0..3]. ; Yes, it starts from zero! If Frame = 4 Then Frame = 0 ; Move the character. PosX = PosX + MoveSpeed ; Place character back off-screen on the left ; when running off-screen on the right. If PosX > ScreenSizeX PosX = -AnimSize End If End If ; Draw animated image. DrawImage Image , PosX , PosY , Frame Flip Cls Until KeyHit ( 1 ) End ;---- -- - - ; ; Interesting? :) ; ; For some more related commands ; check out the Time section ; in the command reference. ; ; How to keep your gamespeed constant ; you will find further on in the tutorial. ; ;,,,, ;----------------------------------------------- ; Concepts ; ;---- ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ; ; You can create your game ; in zillions of different ways. ; ; But sometimes you'll want ; to make the code look more understandable ; so you won't read back sometimes ; and wonder what sx-51 means :) ; ; Ofcourse adding comments ; like you have seen so far ; will help a lot too :) ; ; Now, the basic game structure ; usually consists of 4 main parts; ; ; - Def ; - Init ; - Play ; - Exit ; ; A definition section (Def) ; where you define everything ; from variables to objects. ; ; An initialization section ; where you setup the game. ; ; A play-the-game section ; where you.. play the game :) ; ; And a cleaning-up section ; to clean up everything. ; ; The definition section ; usually includes things like; ; ; - Const ; - Type ; - Global ; - Dim ; ; But you could also add ; functions in this section as well. ; ; The initialization section ; can contain commands like; ; ; - Graphics ; - LoadImage ; - LoadSound ; ; As well as preparing variables, ; objects and arrays for the game. ; ; In larger games you usually ; see a loading screen ; while media is being loaded. ; ; The play-the-game section ; can also be called ; the Main routine of your game. ; ; It can contain anything that ; you can fool around with. ; Ranging from operating menus ; to a complete 2D shooter. ; You can ofcourse divide these ; in their own separate sections as well. ; ; So, the Main routine would be the part ; where the player interacts with the game. ; ; In Blitz you can make the ; Exit section very tiny ; because Blitz will remove ; all traces of media, objects etc ; from memory for you. ; ; So you don't really have to ; clean-up everything yourself. ; That is why a lot of games ; usually only have 1 word ; in its Exit game routine: End :P ; ; However there are cases where ; Blitz will not clean up for you ; and cases where you will want ; to do it yourself anyway. ; ; To summarize, ; here's a possible ; basic game structure ; you can hold on to.. ; ; Game ; |_ Definition ; | |_ Const ; | |_ Data ; | |_ Type ; | |_ Global ; | \_ Dim ; |_ Initialization ; | |_ Logic ; | | |_ Objects ; | | |_ Variables ; | | \_ Arrays ; | |_ Graphics ; | \_ Sound/Music ; |_ Play ; | |_ Local ; | \_ Loop ; \_ Exit ; \_ Delete ; \_ End ; ; There can also be a separate section ; for sub-routines (functions, gosubs), ; and a special section for Data, ; usually located at the bottom. ; ; In any way, remember that you ; basically can do anything you want. ; Below you will find some suggestions ; to keep things together, to make the code ; look more understandable in general ; but above all; for yourself. ; ; First, an example of a very small game. ; ;,,,, ,, , , ;-------------------------------; ; Mini Game ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,; ; ; Layout: ; Def ; Init ; Main ; ( Sub ) ; ( Data ) ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ;--> Def Const Screen (visual) Const Game (logic) Type Struct Global Vars Dim Arrays ;--> Init Graphics Screen SeedRnd MilliSecs () InitPlayer InitEnemies (Global) Vars = LoadTileMap ;--> Main Local Repeat UpdateInput ; Keyboard UpdateStruct ; Objects UpdateScreen ; Visual Until GameExit End ;--> Sub ( Can also be moved to after Def ) Function ;--> Data ( Can be moved to anywhere ) .Label Data ;---- -- - - ; ; No real Exit section as the only ; clean-up command used it is: End :P ; ; So basically 5 sections. ; ; The definition section where all ; constants, objects, variables ; and arrays are defined. ; ; For example you could have ; screen dimensions (visual), ; animation speed (logic), ; what's inside a player object ; and an enemy object, ; global image handles, ; a global pointer to a player ; and an array with a tilemap. ; ; In the initialization section ; you'd setup the graphics mode, ; select a fresh random pattern, ; initialize the player object ; and the enemy objects, ; load the graphics ; and the tilemap. ; ; Then the Main routine ; where the game is played. ; But first setting some local ; variables like a counter ; to be used in the Main loop. ; Inside the Main loop ; looking for pressed keys, ; updating the objects ; like moving enemies ; and updating the screen ; with tiles, player ; and enemies. ; ; The sub-routines section ; could for example contain ; functions to manage the player. ; Like, initializing the player, ; checking for player input, ; moving the player, ; making the player die, ; and respawning the player. ; ; Let's continue with a game of ; similar size but using different code. ; ;,,,, ,, , , ;-------------------------------; ; Small Game ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,; ; ; Layout: ; Def ; Init ; Main ; Sub ; Data ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ;--> Def Const Screen (visual) Const Game (logic) Type Struct Global Vars Dim Arrays ;-- Init InitVisual InitLogic InitStruct InitVars InitArrays ;-- Main Repeat Logic Visual Until GameExit End ;-- Sub Function Logic UpdateInput UpdateStruct Function Visual UpdateScreen Function InitVisual Graphics Screen Function InitLogic SeedRnd MilliSecs () Function InitStruct InitPlayer InitEnemies Function InitVars (Global) Vars = Function InitArrays LoadTileMap ;-- Data .Label Data ;---- -- - - ; ; The definition part is ; still completely the same. ; ; However the initialization ; part changed a bit. ; Each bit has been separated ; into clear categories ; and has been put into ; separate functions. ; ; Actually, the same thing ; happened in the Main routine. ; Any local variables would ; now have to be global, ; otherwise they won't be ; visible from inside ; those new functions. ; ; The Logic function controls ; all game logic, being input ; and objects in this case. ; ; And the Visual function simply ; draws the game on the ; background buffer. ; ; The sub-routines part is now ; the part that contains most code. ; In fact, all code where anything ; happens with anything at all :P ; ; You can order the functions ; in any way you like. ; ; Now, watch what happens ; when you further separate ; everything in functions. ; ;,,,, ,, , , ;-------------------------------; ; Medium Game ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,; ; ; - Method 1 ; ; Layout: ; Def ; |_ Const ; |_ Data ; |_ Type ; |_ Global ; \_ Dim ; Sub ; \_ Function ; Init ; Main ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ;== (Global) Def ;-- Constant Def Const Screen (visual) Const Game (logic) ;-- Data ( Can be considered part of Constant Def ) Data ;-- Type Def Type Struct ;-- (Global) Var Def Global Vars Dim Arrays ;== Sub Function Init InitVisual InitLogic InitStruct InitVars InitArrays Function InitVisual Graphics Screen Function InitLogic SeedRnd MilliSecs () Function InitStruct InitPlayer InitEnemies Function InitVars (Global) Vars = Function InitArrays LoadTileMap Function Main Repeat Logic Visual Until GameExit Function Logic UpdateInput UpdateStruct Function Visual UpdateScreen ;== Init Init ;== Main Main End ;---- -- - - ; ; As you can see, the code is now ; completely separated, code-wise. ; ; You could also separate all parts ; that are not directly related. ; ;,,,, ,, , , ;-------------------------------; ; Medium Game ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,; ; ; - Method 2 ; ; Layout: ; Visual ; Logic ; Tilemap ; Player ; Enemies ; Main ; \_ Sub ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ;== Visual Const Screen (visual) Global Vars Function InitVisual Graphics Screen InitVisual ;== Logic Const Game (logic) Global Vars Function InitLogic SeedRnd MilliSecs () InitLogic ;== Tilemap Const Data Global Vars Dim Arrays Function InitArrays LoadTileMap InitArrays ;== Player Const Type Struct Global Vars Function InitPlayer InitPlayer ;== Enemies Const Type Struct Global Vars Function InitEnemies InitEnemies ;== Main Repeat Logic Visual Until GameExit End ;-- Sub Function Logic UpdateInput UpdateStruct Function Visual UpdateScreen ;---- -- - - ; ; Pretty much the same as before, ; just separated differently. ; ; What if you wanted to spread your code ; over a number of different files? ; ; Maybe you'll remember the Include command ; which you can use to glue BB files together. ; ;,,,, ,, , , ;-------------------------------; ; Medium-Large Game ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,; ; ; - Method 1 ; ; Layout: ; Includes ; |_ Visual ; |_ Logic ; |_ Tilemap ; |_ Player ; \_ Enemies ; Game ; \_ Subs ; |_ Level 1 ; |_ Level 2 ; \_ ... ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ;== Includes Include "Visual.BB" ;-> Visual.BB Const Screen (visual) Global Vars Function InitVisual Graphics Screen Include "Logic.BB" ;-> Logic.BB Const Game (logic) Global Vars Function InitLogic SeedRnd MilliSecs () Include "Tiles.BB" ;-> Tiles.BB Const Data Global Vars Dim Arrays Function InitArrays LoadTileMap Include "Player.BB" ;-> Player.BB Const Type Struct Global Vars Function InitPlayer Include "Enemy.BB" ;-> Enemy.BB Const Type Struct Global Vars Function InitEnemies ;== Game InitGame RunGame EndGame ;-- Sub level 1 Function InitGame InitVisual InitLogic InitArrays InitPlayer InitEnemies Function RunGame Repeat Logic Visual Until GameExit Function EndGame End ;-- Sub level 2 Function Logic UpdateInput UpdateStruct Function Visual UpdateScreen ;---- -- - - ; ; The Game section could be a file ; called Main.BB containing all ; parts that are first executed ; as well as calls to functions ; in the Include files. ; ; So all 'external' parts are now ; neatly separated from the code ; for the Main routine. ; ; You could also put all definition ; code in a single section/file. ; ;,,,, ,, , , ;-------------------------------; ; Medium-Large Game ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,; ; ; - Method 2 ; ; Layout: ; Construct ; |_ Definition ; |_ Visual ; |_ Logic ; |_ Tilemap ; |_ Player ; |_ Enemies ; \_ Game ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ;== Construct Include "Definition.BB" ;-> Definition.BB ;-- Screen Const Screen (visual) Global Vars ;-- Logic Const Game (logic) Global Vars ;-- Tilemap Const Data Global Vars Dim Arrays ;-- Player Const Type Struct Global Vars ;-- Enemies Const Type Struct Global Vars Include "Visual.BB" ;-> Visual.BB Function InitVisual Graphics Screen Function Visual UpdateScreen Include "Logic.BB" ;-> Logic.BB Function InitLogic SeedRnd MilliSecs () Function Logic UpdateInput UpdateStruct Include "Tiles.BB" ;-> Tiles.BB Function InitArrays LoadTileMap Include "Player.BB" ;-> Player.BB Function InitPlayer Include "Enemy.BB" ;-> Enemy.BB Function InitEnemies ;-> Game.BB Function ExecGame InitGame RunGame EndGame Function InitGame InitVisual InitLogic InitArrays InitPlayer InitEnemies Function RunGame Repeat Logic Visual Until GameExit Function EndGame End ExecGame ;---- -- - - ; ; You can also see that the code ; from the Main routine has been ; moved around a bit. ; ; Now in the Game.BB file only ; one function is called, ; followed by a chain-reaction. ; ; You'll also find the Logic ; and Visual parts to be moved ; to separate files. ; ; Following is an example of ; a rather large game ; where all, each and every part ; is completely separated. ; ; Where the basic construction ; contains only Logic and Visual. ; ; Ofcourse for programs this size ; you can make it anything at all ; ranging from a single program of GOTOs ; to programs running completely independently. ; ; I have not included the entire structure ; as it would be extremely large so ; I just went upto the point ; where I think you'll get the idea :P ; ;,,,, ,, , , ;-------------------------------; ; Large Game ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,; ; ; Layout: ; Construct ; |_ Logic ; | |_ Player ; | | \_ ; | |_ Enemies ; | | \_ ; | \_ Tilemap ; | \_ ; \_ Visual ; |_ Player ; | \_ ; |_ Enemies ; | \_ ; \_ Tilemap ; \_ ; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ;-> GameName.BB Include "Code\Construct.BB" ;-> Code\Construct.BB Include "Code\Logic.BB" Include "Code\Visual.BB" Const Application .. Function Application_Init .. Application_Run Application_Init () Application_Exit First Application_Structure End ;-> Code\Logic.BB Include "Code\Logic\Player.BB" Include "Code\Logic\Enemies.BB" Include "Code\Logic\Tilemap.BB" Const Logic .. Function Logic_Init .. Logic_Init ;-> Code\Visual.BB Include "Code\Visual\Player.BB" Include "Code\Visual\Enemies.BB" Include "Code\Visual\Tilemap.BB" Const Visual .. Function Visual_Init .. Visual_Init ;-> Code\Logic\Player.BB Include "Code\Logic\Player\Const.BB" Function Player_InitLogic .. .. .. .. .. ;---- -- - - ; ; And you can go all the way. ; Almost as far as chopping it up ; into thousands of little sections. ; ; It just depends on what you want to create ; and how difficult you want to make it for yourself :o) ; ; So for a game like this I would personally ; definitely go for the Mini game structure :) ; ; Always try to shape the code as you see fit. ; You don't have to use the same technique every time. ; ; Also in the code above you'll see that ; there's a whole directory structure ; where both code and media ; are specifically organized. ; ; Here's another example of a more simple ; directory structure: ; ; [Game] ; |_ [Images] ; | |_ Player.BMP ; | \_ Enemy.BMP ; |_ [Sounds] ; | \_ Explosion.WAV ; \_ Main.BB ; ; There are also 2 more interesting ; sections in the commands reference ; being System and Debug. ; ; The Debug section contains the ; commands DebugLog and Stop to aid you ; in debugging your programs. ; ; Now, we talked about the timing issue ; when you run your program on other computers ; with different monitor refresh rates. ; ; There are various solutions to make your program ; run with exactly the same speed on every computer. ; ; One of the easiest solutions is using a Blitz timer. ; You may have noticed the CreateTimer command ; in the command reference under the Time section. ; ; If not, you can check it out in the Blitz help, ; as well as the related commands, such as WaitTimer. ; ;,,,, ,, , , Const GameSpeed = 30 ; Frames per second. Timer = CreateTimer ( GameSpeed ) ;---- -- - - ; ; Timer contains the timer handle ; which you can then use in your Main loop ; to synchronize the number of times ; your game is updated with GameSpeed, ; while the number of times the ; game is displayed on the screen ; actually stays the same. ; ;,,,, ,, , , ; Main loop. Repeat ; Calculate number of times ; we should update the game ; to stay synchronized with ; 30 frames per second. UpdateCount = WaitTimer ( Timer ) ; Update the game ; that number of times. For UpdateNumber = 1 To UpdateCount ; Update the game logic ; e.g. objects, input etc. Logic Next ; Draw the game on screen. Visual ; Display the game screen ; and synchronize with the ; monitor refresh rate. Flip ; End game using Esc. Until KeyHit ( 1 ) ;---- -- - - ; ; So if you run this on a fast enough computer, ; the game logic will not be updated ; more than one time per screen update. ; E.g. only one logic update per run ; through the main loop, e.g. one frame. ; So the program runs as fast as possible. ; ; If you run it on a slower computer, ; the game logic will be executed ; more than one time per frame ; to keep up with the GameSpeed. ; ; This will however cause jerks in the movement ; of objects in the game, but the speed ; will still be the same on any computer. ; ; You can find a tutorial on a smoother solution ; of frame limiting (keeping the speed constant) ; on the BlitzCoder website, as well as numerous ; other enlighting articles and code snippets. ; http://www.blitzcoder.com/articles.shtml http://www.blitzcoder.com/code.shtml ; ;-------------------------------------------------------------------------------