TUTORIAL - Setting Up DirectX Screens (updated for PureBasic 4.20)

If you read through the docs and look at the examples you will see there are a number of different things you can draw to and you will also get a better understanding on how to put the various commands together properly.

If you are using a window then you want to use StartDrawing(WindowOutput()) to draw to this window. If you are using a DirectX screen (either Fullscreen or Windowed mode) then you need to use StartDrawing(ScreenOutput()) etc.

Now StartDrawing() is used when you are using any of the 2D commands (lines, circles, fonts) and you put these drawing routines within a StartDrawing()/StopDrawing() block. Only put what is needed to accomplish the 2D drawing within these blocks.

Now if you are displaying Bitmaps, Jpeg Images, etc to a DirectX screen, you would use LoadSprite() and DisplaySprite(). LoadImage() and DrawImage() would be used to draw to a Window.


The first thing you must decide is what type of screen you want to do your work on so... lets say I want to work with a DirectX screen and have the option of using Full Screen or Windowed Mode.

First I will open a normal Window with some option gadgets so the user can select the screen mode he wants. We'll use some constants to represent the various gadgets we will be using

Code:

#Window_Mode=0
#Gadget_Mode_Option1=1
#Gadget_Mode_Option2=2
#Gadget_Mode_Ok=3

then we will create our Window with Gadgets
Code:

If OpenWindow(#Window_Mode,175,0,201,129,"Select Mode",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  If CreateGadgetList(WindowID(#Window_Mode))
    OptionGadget(#Gadget_Mode_Option1,45,25,95,15,"Window Mode")
    OptionGadget(#Gadget_Mode_Option2,45,45,95,15,"Screen Mode")
    ButtonGadget(#Gadget_Mode_Ok,70,85,60,20,"Ok")
    SetGadgetState(#Gadget_Mode_Option1,1)
  EndIf
EndIf

If we run this as is, it will just flash on the screen then end. We need an event loop to process that various button clicks.
Code:

    quitMode=0
    Repeat
      EventID=WaitWindowEvent()

    Until quitMode

This loop will wait for an event to happen, but we must also decode those events. This will check if the Cancel buton (X in top right corner) has been pressed. If so, the program Ends.
Code:

      Select EventID
        Case #PB_Event_CloseWindow
          If EventWindow()=#Window_Mode
            End
          EndIf

      EndSelect

But what is the user pressed the OK button to make his choice of Screen Mode? We need to catch the button press event (OK button). First we check that a Gadget event has happened. If so, then what gadget has been pressed? We labeled our OK button as #Gadget_Mode_Ok so this is the constant we check for.
If OK has been pressed, then we need to see the state of the option gadgets. We labeled the first option gadget as #Gadget_Mode_Option1. If we check the state of this gadget and it equals 1, then it has been selected and we will set screenmode=1 (which will represent Window Mode). If it does not equal 1, then the user must have selected the second option of Full Screen so we wills set screenmode=0 (which will represent Full Screen Mode). We also want to exit the event loop at this point so we will set quitMode=1
Code:

        Case #PB_Event_Gadget
          Select EventGadgetID()
            Case #Gadget_Mode_Ok
              If GetGadgetState(#Gadget_Mode_Option1)
                screenmode=1
                Else
                screenmode=0
              EndIf
              quitMode=1
          EndSelect


So to recap, our code should look like this so far.
Code:

#Window_Mode=0
#Gadget_Mode_Option1=1
#Gadget_Mode_Option2=2
#Gadget_Mode_Ok=3


If OpenWindow(#Window_Mode,175,0,201,129,"Select Mode",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  If CreateGadgetList(WindowID(#Window_Mode))
    OptionGadget(#Gadget_Mode_Option1,45,25,95,15,"Window Mode")
    OptionGadget(#Gadget_Mode_Option2,45,45,95,15,"Screen Mode")
    ButtonGadget(#Gadget_Mode_Ok,70,85,60,20,"Ok")
    SetGadgetState(#Gadget_Mode_Option1,1)   

    quitMode=0
    Repeat
      EventID=WaitWindowEvent()
      Select EventID
        Case #PB_Event_CloseWindow
          If EventWindow()=#Window_Mode
            End
          EndIf

        Case #PB_Event_Gadget
          Select EventGadget()
            Case #Gadget_Mode_Ok
              If GetGadgetState(#Gadget_Mode_Option1)
                screenmode=1
                Else
                screenmode=0
              EndIf
              quitMode=1
          EndSelect

      EndSelect
    Until quitMode
    CloseWindow(#Window_Mode)
  EndIf
EndIf



Alright, now that we have our Mode selector, lets open the appropriate screens for drawing on. Remember.... screenmode=1 is WindowMode, screenmode=0 is fullscreen.
Code:

    If screenmode
      If OpenWindow(0,0,0,640,480,"MyApp",#PB_Window_TitleBar|#PB_Window_ScreenCentered)
        If OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0)=0
          MessageRequester("Error","Could not open Windowed Screen",0)
        EndIf
        Else
        MessageRequester("Error","Could not create Window",0)
        End
      EndIf
     
      Else
      If OpenScreen(640,480,16,"MyApp")=0
        MessageRequester("Error","Could not create DirectX Screen",0)
      EndIf
    EndIf


Basically Windowed Mode is a regular window with a DirectX screen drawn on it. Full screen is... well, Full Screen.

If the user has selected WIndow Mode, we try and open a Window, then try and open a DirectX screen in it. If either fail, you get a message and the program ends.
If the user has selected Full Screen, we try and open a fullscreen DirectX screen. If it fails, error message and program ends.

Once thing to note, to work with DirectX stuff we need to initialize some directX stuff... so at the start of our program we will add the following. (We will also be loading JPEG images so we better include the JPEG image decoder)

Code:

If InitSprite()=0 Or InitKeyboard()=0
  MessageRequester("Error","Could Not Initialize DirectX",0)
  End
EndIf

UseJPEGImageDecoder()

This will allow us to use the DirectX screens and Sprites. And while we're at it, let's initialize the DirectX keyboard as well so we can check for an ESC key press to quit our program.
Now where were we... yes, we just opened our screen for drawing on.
At this point I always set my frame rate to 75. I do this so my app runs the same speed on all processors and I use 75 because I usually have my videocard refresh rate set to 75, so using a frame rate of 75 to match gives nice smooth drawing.
Code:

SetFrameRate(75)



Now lets load our 2 test images. I used these to test with...


Code:

    LoadSprite(0,"image1.jpg")
    LoadSprite(1,"image2.jpg")


Alright, time for the drawing loop !!
If we are using Windowed Mode, we don't want our app taking up 100% CPU power so we need to share by doing a quick event check. This loop will run until we set quitMain=1
Code:

    quitMain=0
    Repeat
      If screenmode
        WindowEvent()
        Delay(1)
      EndIf
   
    Until quitMain



Since we would like our app to quit when we press ESC (escape) key we need to examine the keyboard and check to the press. In this example we will end the app when the ESC key is released.
Code:

      ExamineKeyboard()
      If KeyboardReleased(#PB_Key_Escape)
        quitMain=1
      EndIf


To display our image (which is loaded as a Sprite) we must use DisplaySprite() command. So we will Clear our screen, display the Sprite, then Flip everything into view once ALL drawing is complete.
Code:

      ClearScreen(0)
      DisplaySprite(0,50,50)     
      FlipBuffers()



Now thiswill only show us the one sprite. What we want is to toggle between the 2 sprites so instead of using a set sprite value (we used 0), we will assign the Sprite value to a variable then change this variable.
Code:

        image+1
        If image>1
          image=0
        EndIf

The first time the computer gets to this part of the program, image will be incremented by 1... so image=1. The second time image is incremented by 1, it becomes 2. 2 is greater than 1 so we set image back to 0.
Basically the results will by: 1,0,1,0,1,0,1,0 etc, so it will toggle between image0 and image1 that we are using.
Code:

        image+1
        If image>1
          image=0
        EndIf
     
      DisplaySprite(image,50,50)


This will probably toggle between images faster than we would like so lets put another "counter block" around the "image toggle" block.
Code:

      counter+1
      If counter>75
        counter=0
        image+1
        If image>1
          image=0
        EndIf
      EndIf

This is the same as the image counter but allows the counter to reach 75 before it is reset back to 0. This will give us about a 1 second delay between image changes.



So to sum it all up, here is our final working code...
Code:

#Window_Mode=0
#Gadget_Mode_Option1=1
#Gadget_Mode_Option2=2
#Gadget_Mode_Ok=3



If InitSprite()=0 Or InitKeyboard()=0
  MessageRequester("Error","Could Not Initialize DirectX",0)
  End
EndIf

UseJPEGImageDecoder()
   
   

If OpenWindow(#Window_Mode,175,0,201,129,"Select Mode",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  If CreateGadgetList(WindowID(#Window_Mode))
    OptionGadget(#Gadget_Mode_Option1,45,25,95,15,"Window Mode")
    OptionGadget(#Gadget_Mode_Option2,45,45,95,15,"Screen Mode")
    ButtonGadget(#Gadget_Mode_Ok,70,85,60,20,"Ok")
    SetGadgetState(#Gadget_Mode_Option1,1)   

    quitMode=0
    Repeat
      EventID=WaitWindowEvent()
      Select EventID
        Case #PB_Event_CloseWindow
          If EventWindow()=#Window_Mode
            End
          EndIf

        Case #PB_Event_Gadget
          Select EventGadget()
            Case #Gadget_Mode_Ok
              If GetGadgetState(#Gadget_Mode_Option1)
                screenmode=1
                Else
                screenmode=0
              EndIf
              quitMode=1
          EndSelect

      EndSelect
    Until quitMode
    CloseWindow(#Window_Mode)
   
   
    If screenmode
      If OpenWindow(0,0,0,640,480,"MyApp",#PB_Window_TitleBar|#PB_Window_ScreenCentered)
        If OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0)=0
          MessageRequester("Error","Could not open Windowed Screen",0)
        EndIf
        Else
        MessageRequester("Error","Could not create Window",0)
        End
      EndIf
     
      Else
      If OpenScreen(640,480,16,"MyApp")=0
        MessageRequester("Error","Could not create DirectX Screen",0)
      EndIf
    EndIf
    SetFrameRate(75)




   
    LoadSprite(0,"image1.jpg")
    LoadSprite(1,"image2.jpg")
   
   
    quitMain=0
    Repeat
      If screenmode
        WindowEvent()
        Delay(1)
      EndIf
     
      ExamineKeyboard()
      If KeyboardReleased(#PB_Key_Escape)
        quitMain=1
      EndIf
     
      ClearScreen(0)
     
      counter+1
      If counter>75
        counter=0
        image+1
        If image>1
          image=0
        EndIf
      EndIf
     
      DisplaySprite(image,50,50)
     
      FlipBuffers()   
    Until quitMain
     
  EndIf
EndIf




Enjoy!

(written by Paul Leischow - Dec.6, 2003)