Reaction Timer

Just starting out? Need help? Post your questions and find answers here.
georgej
User
User
Posts: 11
Joined: Wed Aug 17, 2005 5:21 pm

Reaction Timer

Post by georgej »

For my first post as a beginner to PureBasic, I would firstly like to thank the PB community for the helpful comments and lines of code on the forums. I have learnt so much from reading and trying to understand the code.

Rather than ask lots of questions, I have studied first and below is my rather simple effort at a reaction timer. It was done as a learning exercise in gadget interaction and how to get a thread to work, rather than a precision timer. It may look very simple to most, but it took me a long while to figure out the thread part. I have commented the code as I understand it. It does work but now I am left with a question, am I on the right track with PureBasic coding?

Code: Select all

; -------------------------------------------
; Title:    Reaction Timer
; Version:  1.1
; PB Ver:   4.00
;
; Author:   George Jopling
;
; About:
; A simple reaction timer for novelty use.
; 
; Use this code in any way you see fit.
; -------------------------------------------

;- Window Constants

Enumeration
  #Window_0
EndEnumeration

;- Gadget Constants

Enumeration
  #Spin_Random
  #Button_Start
  #Text_Seconds
  #Text_Label_Spin
  #Text_Label_Seconds
  #Text_Status
EndEnumeration

Procedure timer() 
  SetGadgetText(#Text_Status, "[ Random delay started.  Get ready... ]") 
  
  StartDelay.b=(GetGadgetState(#Spin_Random)) ;Obtain value of Spin Gadget. 
  RandomStart.w = Random(StartDelay) ;Use Spin Gadget number as maximum for randomising start delay. 
  If RandomStart = 0 ;0 is a valid output of Random().  Add 1 if random result is 0. 
    RandomStart = RandomStart + 1
  EndIf 
  Delay(RandomStart*1000) ;Convert random delay number into milliseconds, as required by Delay().
  
  key.w = GetKeyState_( #VK_SPACE) ;API keyboard call. 
  If key & $8000 ;Check to see if the Space bar is being pressed when Delay() expires;
     DisableGadget(#Button_Start, 0)
     DisableGadget(#Spin_Random, 0) 
     SetGadgetText(#Text_Status, "[ Cheat! ]") ;Display a cheat message if it is.
    
  Else ;Space bar was not being pressed, continue with main reaction timer. 
    SetGadgetText(#Text_Status, "[ Go!  Press the Space bar Now! ]") 
    Beep_(500,50) ;API function to make sound from the computer speaker. 
    StartTime.d = ElapsedMilliseconds() ;Obtain a time reference point when the reaction timer started.
  
  Repeat ;Generate loop checking to see if the Space bar has been pressed.  Update displays accordingly. 
    key.w = GetKeyState_( #VK_SPACE) ;API keyboard call. 
    If key & $8000 ;Check to see if the Space bar has been pressed.
      DisableGadget(#Button_Start, 0)
      DisableGadget(#Spin_Random, 0) 
      SetGadgetText(#Text_Status, "[ Another go? ]")
      Break ;Break out of loop straight away if the Space bar has been pressed.
      
    Else ;If Space bar has not been pressed, update timer display etc.
      Delay(1) ;1 millisecond delay.  Essential to prevent 100 per cent processor usage.
      DisplayTime.f = ElapsedMilliseconds()-StartTime ;Obtain further time reference point and compare against start. 
      DisplayTimeSeconds.s = StrF(DisplayTime/1000, 3) ;Format display to 3 decimal places.
      SetGadgetText(#Text_Seconds,DisplayTimeSeconds) ;Display it.
    EndIf
    
  Until DisplayTime =  10000 ;Loop until maximum wait time for Space bar press (10 seconds). End loop if reached. 
    If DisplayTime = 10000 ;If it is the maximimum wait time, update accordingly.
    SetGadgetText(#Text_Status, "[ Slowcoach!  Another go? ]")
    DisableGadget(#Button_Start, 0)
    DisableGadget(#Spin_Random, 0)  
    EndIf
  EndIf
  
EndProcedure

Procedure Open_Window_0() ;Open the main window and display gadgets. 
  If OpenWindow(#Window_0, 410, 283, 264, 192, "Reaction Timer",  #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_WindowCentered )
    
    If CreateGadgetList(WindowID(#Window_0))
      SpinGadget(#Spin_Random, 170, 25, 55, 25, 1, 60) ;Set the spin gadget minimum value at 1 and maximum at 60.
      SetGadgetState (#Spin_Random,10) : SetGadgetText(#Spin_Random,"10") ;Set the spin gadget default at 10.
      ButtonGadget(#Button_Start, 85, 150, 80, 25, "Start Timer")
      TextGadget(#Text_Seconds, 120, 105, 105, 20, "0.000", #PB_Text_Center | #PB_Text_Border)
      TextGadget(#Text_Label_Spin, 30, 30, 125, 25, "Random Delay Maximum", #PB_Text_Center)
      TextGadget(#Text_Label_Seconds, 35, 105, 60, 25, "Seconds")
      TextGadget(#Text_Status, 35, 70, 190, 20, "[ Click Start Timer button. ]") 
    EndIf
    
  EndIf
EndProcedure

Procedure Event_Loop() ;Loop for events. Check to see what they are and process accordingly. 
  Repeat 
    Event = WaitWindowEvent()
    Select Event 
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #Spin_Random ;Process gadget event.
            If GetGadgetState(#Spin_Random)<>Val(GetGadgetText(#Spin_Random)) ;Have gadget contents changed.
              If EventType()=#PB_EventType_Change ;Has a value been typed into gadget.
                SetGadgetState(#Spin_Random,Val(GetGadgetText(#Spin_Random))) ;Set gadget to current value.
              Else 
                SetGadgetText(#Spin_Random,Str(GetGadgetState(#Spin_Random))) ;Put value of button change into gadget.
              EndIf 
            EndIf 
            
          Case #Button_Start ;Start button pressed
            SetGadgetText(#Text_Seconds, "0.000")           
            DisableGadget(#Button_Start, 1) 
            DisableGadget(#Spin_Random, 1) 
            ThreadTimer=CreateThread(@timer(),"") ;Create a thread for the timing processes and display updates.  
        EndSelect  
    EndSelect 
  Until Event = #PB_Event_CloseWindow ;Exit the program if the close window button is clicked.
EndProcedure

Open_Window_0() ;Call the Open Window procedure to initialise the program and display on screen.
Event_Loop() ;Call the Event Loop to check for events and process them.
Last edited by georgej on Mon Oct 09, 2006 10:20 pm, edited 4 times in total.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

You should post the code enclosed in code tags so the indentation is preserved.

Apart from that it seems to be well done. Your variables and gadget constants are sanely named.

Code: Select all

StartDelay.b=Val(Str(GetGadgetState(#Spin_Random)))
...
SetGadgetText(#Text_Status,"[ Slowcoach!  Another go? ]")
Personally I would have used a few more spaces like this:

Code: Select all

StartDelay.b = Val(Str(GetGadgetState(#Spin_Random)))
...
SetGadgetText(#Text_Status, "[ Slowcoach!  Another go? ]")
And have a look at this:

Code: Select all

StartDelay.b = Val(Str(GetGadgetState(#Spin_Random)))
Str() converts an integer to a string. Val() converts a string to an integer. So basically you're converting unnecessarily. You could have written it like this:

Code: Select all

StartDelay.b = GetGadgetState(#Spin_Random)
But overall, very well done for one of your first programs. I particularly like that you disable the button when it shouldn't be clicked. (I'm obsessive with these sort of details.)
georgej
User
User
Posts: 11
Joined: Wed Aug 17, 2005 5:21 pm

Post by georgej »

Thank you Trond.

I have edited my post to enclose the code in tags as you suggested.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

(I'm obsessive with these sort of details.)
No... really? You hide it so well... :lol:
BERESHEIT
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

One huge mistake: If you press (and hold) spacebar before the beep you get a nice score ;)

Suggestion:
Make it check if the spacebar is pressed before and stop the game writing "Cheater!"
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

I would recommend in general for coding, even inside of procedures you should add extra lines and comments to 'section off' the code a bit more and make it more readable
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

dracflamloc wrote:I would recommend in general for coding, even inside of procedures you should add extra lines and comments to 'section off' the code a bit more and make it more readable
Yeah. its way too compact.
georgej
User
User
Posts: 11
Joined: Wed Aug 17, 2005 5:21 pm

Post by georgej »

Thank you for taking the time to give your comments and feedback. It is appreciated. I have amended the code.
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

georgej wrote:Thank you for taking the time to give your comments and feedback. It is appreciated. I have amended the code.
works great!
Post Reply