;-------------------------------------------------------------------------------
;
;   ;-------------------------------;
;   ;   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
;
;-------------------------------------------------------------------------------