Keyboard - directinput

Just starting out? Need help? Post your questions and find answers here.
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Keyboard - directinput

Post by djes »

Hi Fred!

It seems we (me and polux) have problems in our games on some configs with keyboard, when a lot of sprites are rendered. It is terribly slow. It happens on one of bgames members (cederavic), so we can test.

Maybe it's our way to use keyboard that's not good. Maybe we should use hooks, events, do a delay somewhere, organise our code in some order, put our keys routine in a thread?

I've also read in this article http://www.falloutsoftware.com/tutorials/di/di2.htm that maybe setcooperativelevel could be the problem, but I'm not sure...

If you have a tip (the best method for a game), it would be greatly appreciated! Thank you...
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

I've tried to use SetWindowCallback, but I haven't the window number to use it with openscreen. I've tried with ScreenID, but it doesn't work.

Code: Select all

Procedure WindowCB(WindowID.l, Message.l, wParam.l, lParam.l)
    ; This is where the processing of your callback procedure would be performed
  Result = #PB_ProcessPureBasicEvents
   
  Select Message
    Case #WM_CLOSE  ; #WM_CLOSE = #PB_Event_CloseWindow
      MessageRequester("","Closing")
      End
   
;    Case #WM_CHAR
;      MessageRequester("#WM_CHAR","Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam)) 


    Case #WM_KEYDOWN
         MessageRequester("#WM_KEYDOWN","Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam)) 


    Case #WM_KEYUP
         MessageRequester("#WM_KEYUP","Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam)) 

      If wParam=27
        End
      EndIf


    Default
      ProcedureReturn Result
  
  EndSelect

EndProcedure

InitSprite()
InitKeyboard()
ExamineDesktops()
;OpenScreen(DesktopWidth(0),DesktopHeight(0),DesktopDepth(0),"")
OpenWindow(0, 0, 0, 220, 160, "A screen in a window...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 160, 160, 0, 0, 0)

; A special callback for the Windows OS allowing you to process window events
SetWindowCallback( @WindowCB())
;SetWindowCallback( @WindowCB(), ScreenID()) ;doesn't work

CreateSprite(1,100,100)
StartDrawing(SpriteOutput(1))
Box( 0, 0,100,100,RGB(250,20,20))
Box(10,10, 80, 80,RGB(50,20,220))
Circle(50,50,30,RGB(200,200,50))
StopDrawing()

; Create a copy of the 1st sprite
CopySprite(1,2)

Repeat
  Repeat
    Event = WindowEvent()
    
    If Event = #PB_Event_CloseWindow
      End 
    EndIf
  Until Event = 0

  ExamineKeyboard()
  DisplaySprite(1,20,20)
  DisplaySprite(2,150,150)
  FlipBuffers()
Until KeyboardPushed(#PB_Key_F1)
End

User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

I've tried that, but it doesn't work in fullscreen mode with debugger activated... I imagine this is not strange, as this is a hack. However, could you valid this code?

Code: Select all

Global *pb_callback

Procedure WindowCB(WindowID.l, Message.l, wParam.l, lParam.l)
    ; This is where the processing of your callback procedure would be performed
  Result = #PB_ProcessPureBasicEvents
   
  Select Message
    Case #WM_CLOSE  ; #WM_CLOSE = #PB_Event_CloseWindow
      ;MessageRequester("","Closing")
      End
   
;    Case #WM_CHAR
;      MessageRequester("#WM_CHAR","Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam)) 


    Case #WM_KEYDOWN
 
      ;MessageRequester("#WM_KEYDOWN","Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam)) 

    Case #WM_KEYUP

      ;MessageRequester("#WM_KEYUP","Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam)) 

      If wParam=27
        End
      EndIf

    Default
  
  EndSelect

  CallWindowProc_(*pb_callback, WindowID.l, Message.l, wParam.l, lParam.l)
;  ProcedureReturn Result

EndProcedure

InitSprite()
InitKeyboard()
ExamineDesktops()
OpenScreen(DesktopWidth(0),DesktopHeight(0),DesktopDepth(0),"")
;OpenWindow(0, 0, 0, 220, 160, "A screen in a window...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
;OpenWindowedScreen(WindowID(0), 0, 0, 160, 160, 0, 0, 0)


; A special callback for the Windows OS allowing you to process window events
;SetWindowCallback_( @WindowCB())
*pb_callback=GetWindowLong_(ScreenID(), #GWL_WNDPROC)
SetWindowLong_(ScreenID(), #GWL_WNDPROC, @WindowCB())


CreateSprite(1,100,100)
StartDrawing(SpriteOutput(1))
Box( 0, 0,100,100,RGB(250,20,20))
Box(10,10, 80, 80,RGB(50,20,220))
Circle(50,50,30,RGB(200,200,50))
StopDrawing()

; Create a copy of the 1st sprite
CopySprite(1,2)

Repeat
  Repeat
    Event = WindowEvent()
    
    If Event = #PB_Event_CloseWindow
      End 
    EndIf
  Until Event = 0

  ExamineKeyboard()
  DisplaySprite(1,20,20)
  DisplaySprite(2,150,150)
  FlipBuffers()
Until KeyboardPushed(#PB_Key_F1)
End

User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8425
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

See if this is doing more or less what you want:

Code: Select all

Global oldproc, msgout$

Procedure WindowCB(WindowID.l, Message.l, wParam.l, lParam.l) 
 
  If wParam=27 
    End 
  EndIf 
      
  Select Message 
    
    Case #WM_CHAR 
      msgout$ = "#WM_CHAR, Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam) 

    Case #WM_KEYDOWN 
      msgout$ = "#WM_KEYDOWN, Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam) 

    Case #WM_KEYUP 
      msgout$ = "#WM_KEYUP, Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam)

    Default 
      ProcedureReturn CallWindowProc_(oldproc, WindowID, message, wparam, lparam)
  
  EndSelect 
       
EndProcedure 

InitSprite() 
InitKeyboard() 
ExamineDesktops() 
OpenScreen(DesktopWidth(0),DesktopHeight(0),DesktopDepth(0),"") 
oldproc = SetWindowLong_(ScreenID(), #GWL_WNDPROC, @WindowCB())

CreateSprite(1,100,100) 
StartDrawing(SpriteOutput(1)) 
Box( 0, 0,100,100,RGB(250,20,20)) 
Box(10,10, 80, 80,RGB(50,20,220)) 
Circle(50,50,30,RGB(200,200,50)) 
StopDrawing() 

; Create a copy of the 1st sprite 
CopySprite(1,2) 

Repeat 
  ExamineKeyboard() 
  ClearScreen(0)
  DisplaySprite(1,20,20) 
  DisplaySprite(2,150,150) 
  StartDrawing(ScreenOutput())
    DrawText(0,DesktopHeight(0)-20,Space(DesktopWidth(0)),0,0)
    DrawText(0,DesktopHeight(0)-20,msgout$, #Yellow,#Black)
  StopDrawing()
  FlipBuffers() 
  Delay(1)
Until KeyboardPushed(#PB_Key_F1) 
End 
BERESHEIT
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

Thank you :) In windows, fred told us that we can use a callback. Of course, messagerequester doesn't work. Here a little code that I've just done for us.

Code: Select all

;*****************************************************************************************
;*
;* myKeyboardKeys
;*
;* Windows callback routine to get keyboard state with openscreen when
;* standard pb KeyboardReleased and KeyboardPressed don't work
;*
;* djes (djes@free.fr)
;* http://www.bgames.org
;*
;* 09/30/2007 : first version
;*
;*****************************************************************************************

Global Dim myKeyboardKeys.l(255)
Global *myKeyboard_pb_callback

;*****************************************************************************************

Procedure myKeyboardCB(WindowID.l, Message.l, wParam.l, lParam.l)
   
  Select Message
   
;    Case #WM_CHAR
;      MessageRequester("#WM_CHAR","Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam)) 


    Case #WM_KEYDOWN
    ;    wParam
    ;        Specifies the virtual-key code of the nonsystem key. 
    ;    lParam
    ;        Specifies the Repeat count, scan code, extended-key flag, context code, previous key-state flag, And transition-state flag, As shown in the following table.
    
    ;        0-15
    ;            Specifies the Repeat count For the current message. The value is the number of times the keystroke is autorepeated As a result of the user holding down the key. If the keystroke is held long enough, multiple messages are sent. However, the Repeat count is Not cumulative.
    ;        16-23
    ;            Specifies the scan code. The value depends on the OEM.
    ;        24
    ;            Specifies whether the key is an extended key, such As the right-hand ALT And CTRL keys that appear on an enhanced 101- Or 102-key keyboard. The value is 1 If it is an extended key; otherwise, it is 0.
    ;        25-28
    ;            Reserved; do not use.
    ;        29
    ;            Specifies the context code. The value is always 0 For a WM_KEYDOWN message.
    ;        30
    ;            Specifies the previous key state. The value is 1 If the key is down before the message is sent, Or it is zero If the key is up.
    ;        31
    ;            Specifies the transition state. The value is always zero For a WM_KEYDOWN message.

;      MessageRequester("#WM_KEYDOWN","Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam)) 
      myKeyboardKeys(wParam)=1

    Case #WM_KEYUP
    ;    wParam
    ;        Specifies the virtual-key code of the nonsystem key. 
    ;    lParam
    ;        Specifies the Repeat count, scan code, extended-key flag, context code, previous key-state flag, And transition-state flag, As shown in the following table.
    
    ;        0-15
    ;            Specifies the Repeat count For the current message. The value is the number of times the keystroke is autorepeated As a result of the user holding down the key. The Repeat count is always one For a WM_KEYUP message.
    ;        16-23
    ;            Specifies the scan code. The value depends on the OEM.
    ;        24
    ;            Specifies whether the key is an extended key, such As the right-hand ALT And CTRL keys that appear on an enhanced 101- Or 102-key keyboard. The value is 1 If it is an extended key; otherwise, it is 0.
    ;        25-28
    ;            Reserved; do not use.
    ;        29
    ;            Specifies the context code. The value is always 0 For a WM_KEYUP message.
    ;        30
    ;            Specifies the previous key state. The value is always 1 For a WM_KEYUP message.
    ;        31
    ;            Specifies the transition state. The value is always 1 For a WM_KEYUP message.

;      MessageRequester("#WM_KEYUP","Character typed : Code "+ Str(wParam)+"="+Chr(wParam)+" ; Code 2 :"+Hex(lParam)) 
      myKeyboardKeys(wParam)=2

    Default
  
  EndSelect

  CallWindowProc_(*myKeyboard_pb_callback, WindowID.l, Message.l, wParam.l, lParam.l)

EndProcedure

;*****************************************************************************************

Procedure myKeyboardReleased(code.l)

  If mykeyboardkeys(code)=2
    mykeyboardkeys(code)=0
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf 

EndProcedure

;*****************************************************************************************

Procedure myKeyboardPressed(code.l)

  If mykeyboardkeys(code)=1
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf 

EndProcedure

;*****************************************************************************************
;* Need to be called after openscreen
Procedure myKeyboardInit()

  If ScreenID()=0
    MessageRequester("myKeyboardInit","Screen not opened") 
    End
  EndIf

  ;Our callback working with openscreen
  *myKeyboard_pb_callback=GetWindowLong_(ScreenID(), #GWL_WNDPROC)
  If SetWindowLong_(ScreenID(), #GWL_WNDPROC, @myKeyboardCB())=0
    MessageRequester("myKeyboardInit","Can't intercept keys") 
    End
  EndIf

EndProcedure

;*****************************************************************************************

InitSprite()

;OpenWindow(0, 0, 0, 220, 160, "A screen in a window...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
;OpenWindowedScreen(WindowID(0), 0, 0, 160, 160, 0, 0, 0)

;Usual PB callback for the Windows OS allowing you to process window events
;SetWindowCallback_( @WindowCB())

ExamineDesktops()
OpenScreen(DesktopWidth(0),DesktopHeight(0),DesktopDepth(0),"")
myKeyboardInit()

CreateSprite(1,100,100)
StartDrawing(SpriteOutput(1))
Box( 0, 0,100,100,RGB(250,20,20))
Box(10,10, 80, 80,RGB(50,20,220))
Circle(50,50,30,RGB(200,200,50))
StopDrawing()

x=DesktopWidth(0)/2-SpriteWidth(1)/2
y=DesktopHeight(0)/2-SpriteHeight(1)/2

;*****************************************************************************************

Repeat

  ;Repeat
  ;  Event = WindowEvent()
    
  ;  If Event = #PB_Event_CloseWindow
  ;    End 
  ;  EndIf
  ;Until Event = 0

  If myKeyboardPressed(#PB_Shortcut_Up)
    y-1
  EndIf
  If myKeyboardReleased(#PB_Shortcut_Down)
    y+1
  EndIf

  ClearScreen(0)

  DisplaySprite(1,x,y)

  StartDrawing(ScreenOutput())
  text.s="myKeyboardKeys test"
  DrawText(DesktopWidth(0)/2-TextWidth(text)/2,50,text,RGB($FF,$FF,$FF),0)
  text.s="Up Arrow to move up, press and release Down Arrow to move down"
  DrawText(DesktopWidth(0)/2-TextWidth(text)/2,DesktopHeight(0)/2-TextHeight(text)/2,text,RGB($FF,$FF,$FF),0)
  StopDrawing()

  FlipBuffers()

Until myKeyboardReleased(#PB_Shortcut_Escape)

End

Post Reply