Zwei Tasten gleichzeitig abfragen, wie geht das?

Anfängerfragen zum Programmieren mit PureBasic.
OlderCoder
Beiträge: 109
Registriert: 18.03.2013 12:30
Wohnort: Bayerland
Kontaktdaten:

Re: Zwei Tasten gleichzeitig abfragen, wie geht das?

Beitrag von OlderCoder »

Drei andere Fragen zwischendurch:

- Warum bin ich heute morgen ausgeloggt, gestern abend noch eingeloggt, der Haken bei angemeldet bleiben war gesetzt, mein Rechner war nur im Ruhezustand gewesen?
- Kann ich an der Seite meiner Posts meine Rechnerdaten ausblenden? Diese waren für mein Profil gedacht, nicht dafür. Sonst lösch ich sie wieder. Das ist unschön.
- das PureBoard ist eine der ganz wenigen Plattformen, an denen ich mich nicht gesichert anmelden kann. Ist das unvermeidbar?
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Zwei Tasten gleichzeitig abfragen, wie geht das?

Beitrag von Mijikai »

Hier mal ein Beispiel, hoffe es hilft :)

Code: Alles auswählen

EnableExplicit

Macro KeyPressed(_code_)
  (GetAsyncKeyState_(_code_) & $8000)
EndMacro

Procedure.i Main()
  Protected exit.i
  Protected x.f
  Protected y.f
  Protected mx.f
  Protected my.f
  If InitSprite()
    If OpenWindow(0,0,0,960,600,#Null$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
      If OpenWindowedScreen(WindowID(0),0,0,960,600)
        SetFrameRate(60)
        x = 480
        y = 320
        Repeat
          Repeat
            Select WindowEvent()
              Case #PB_Event_CloseWindow
                exit = #True
              Case #Null
                Break
            EndSelect
          ForEver
          mx = 0.0
          my = 0.0
          If KeyPressed(#VK_W)
            my - 1.0
          EndIf
          If KeyPressed(#VK_A)
            mx - 1.0
          EndIf
          If KeyPressed(#VK_S)
            my + 1.0
          EndIf
          If KeyPressed(#VK_D)
            mx + 1.0
          EndIf
          ;Die diagonale Bewegung ist immer schneller, daher sollte hier noch ein ein Faktor einfließen!
          If mx And my
            mx * 0.6;<- Faktor (hier frei gewählt)
            my * 0.6
          EndIf
          x + mx
          y + my
          ClearScreen($0)
          If StartDrawing(ScreenOutput())
            Circle(x,y,5)
            StopDrawing()
          EndIf
          FlipBuffers()
        Until exit
      EndIf
      CloseWindow(0)  
    EndIf  
  EndIf
  ProcedureReturn #Null
EndProcedure

Main()

End
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Zwei Tasten gleichzeitig abfragen, wie geht das?

Beitrag von Mijikai »

OlderCoder hat geschrieben: 04.07.2021 09:31 - das PureBoard ist eine der ganz wenigen Plattformen, an denen ich mich nicht gesichert anmelden kann. Ist das unvermeidbar?
Vermutlich ist noch http:// anstelle von https:// in der Addressleiste.
Sonst sollte SSL funktionieren.
ST4242
Beiträge: 42
Registriert: 29.10.2011 16:54

Re: Zwei Tasten gleichzeitig abfragen, wie geht das?

Beitrag von ST4242 »

Hallo,

wenn wir nur unter Windows und in den Fenster bleiben wollen, dann funktioniert das mit GetAsyncKeyState_ folgendermaßen - diesmal ist das Programm voll lauffähig.

Code: Alles auswählen

;

;Tasten
;WASD mit GetAsyncKeyState_ Abfragen

#Tw=1
#Ta=2
#Ts=3
#Td=4
OpenWindow(1,100,100,300,300,"Test")
TextGadget(0,0,0,300,20,"Diese Tasten sind gedrückt - Bitte Tasten drücken")
ButtonGadget(#tw,40,25,20,20,"W",#PB_Button_Toggle)
ButtonGadget(#ta,25,45,20,20,"A",#PB_Button_Toggle)
ButtonGadget(#td,55,45,20,20,"D",#PB_Button_Toggle)
ButtonGadget(#ts,40,60,20,20,"S",#PB_Button_Toggle)

 Repeat  
   event=WindowEvent()
  Taste_W=GetAsyncKeyState_(#VK_W)
  Taste_A=GetAsyncKeyState_(#VK_A)
  Taste_S=GetAsyncKeyState_(#VK_S)
  Taste_D=GetAsyncKeyState_(#VK_D)
  
  
  If taste_a:SetGadgetState(#Ta,1):Else:SetGadgetState(#Ta,0):EndIf
  If taste_w:SetGadgetState(#Tw,1):Else:SetGadgetState(#Tw,0):EndIf
  If taste_s:SetGadgetState(#Ts,1):Else:SetGadgetState(#Ts,0):EndIf
  If taste_d:SetGadgetState(#Td,1):Else:SetGadgetState(#Td,0):EndIf
  
  

Until event=#PB_Event_CloseWindow

Ich hoffe damit kommst du zurecht

Grüsse
OlderCoder
Beiträge: 109
Registriert: 18.03.2013 12:30
Wohnort: Bayerland
Kontaktdaten:

Re: Zwei Tasten gleichzeitig abfragen, wie geht das?

Beitrag von OlderCoder »

In meiner Adressleiste steht, wenn ich es herauskopiere
"http://forums.purebasic.com/german/view ... 9&start=10"
Ergänze ich vorne das s bei http zum https, bekomme ich ein Not Found.
Und Firefox weist mich auch beim Anmelden sofort darauf hin, dass die Verbindung unverschlüsselt ist.
Also keine Verschlüsselung.
Und warum funktioniert Angemeldet sein nicht? Bei vielen anderen Plattformen tut es. Und in den Firefox-Einstellungen steht, dass www.purebasic.com Cookies speichert. Daran kann es nicht liegen.

Also gibt es keine Möglichkeit, die eigenen Hardware-Angaben neben den Posts auszublenden? Dann lösche ich diese Angaben im Profil wieder. (Ich will hier ja nicht mit meiner Hardware protzen, schon gar nicht mit meiner altersschwachen Kiste :D .)

Dein Beispiel werde ich mir mal anschauen, danke Dir.
Auf den allerersten Blick sieht es allerdings so aus, als würdest Du hier Geschwindigkeiten verwenden. Da es aber keine Echtzeitbewegungen im Spiel gibt, sondern alle Spielobjekte sich nur immer synchron feldweise bewegen, wenn der Spieler eine Bewegung macht, die ebenfalls nur nach den Feldern orientiert ist, ist so ein Vorgehen gar nicht nötig. Das gesamte Spiel orientiert sich an einem 2D-Feldraster.
Aber vielleicht hab ich ja Deinen Vorschlag auch schon im Ansatz missverstanden. Ich muss mal genauer hinschauen, sobald ich Zeit habe. Machen tut Dein Programm nach Start ja leider nichts (auch nicht nach Korrigieren des fehlenden EndProcedure unten), beendet sich immer sofort nach Start, sonst würde mir evtl. die Funktion durch Ausführen klarer werden. In fremden Programmen nach Fehlern zu suchen, auch in solchen kleinen, ist schwieriger, besonders wenn man sie erst mal verstehen muss.
Mit Macros und Sprites usw. kenn ich mich sowieso gar nicht aus. Ich programmiere immer mit möglichst einfachen Mitteln, da fühle ich mich wohler - lerne aber auch selten dazu. Aber meine Kraft und Zeit reicht kaum für mehr.
(Der Verlangsamungsfaktor für die Diagonalbewegung wäre vermutlich 1/Wurzel 2 - wo sich das blöde Wurzelzeichen verbirgt, keine Ahnung :) )

Bei meinem eigenen letzten Entwurf gibt es noch das Problem, dass zusätzlich noch eine einzelne Taste erkannt wird, wenn ich zwei Tasten gleichzeitig länger drücke, als die Tastenwiederhol-Verzögerung dauert. Und zwar immer exakt einmal.
Und mein Versuch mit der zusätzlichen Zeile

Code: Alles auswählen

eventID = WaitWindowEvent(20)            ; Ereignis löschen, um zu verhindern, dass auf die 2. Taste erneut reagiert wird
kann das nicht verhindern, hat tatsächlich gar keinen Effekt.
Sonst wär ich ja schon glücklich und zufrieden. Die Version mit 4 Tasten und 8 Richtungen würde ansonsten auch schon funktionieren.
Aber das Problem muss ich noch lösen.
Es fehlt vielleicht nur eine Kleinigkeit. Aber welche?
Zuletzt geändert von OlderCoder am 04.07.2021 12:49, insgesamt 2-mal geändert.
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Zwei Tasten gleichzeitig abfragen, wie geht das?

Beitrag von Mijikai »

OlderCoder hat geschrieben: 04.07.2021 11:24 ...
Und Firefox weist mich auch beim Anmelden sofort darauf hin, dass die Verbindung unverschlüsselt ist.
Also keine Verschlüsselung.
Und warum funktioniert Angemeldet sein nicht? Bei vielen anderen Plattformen tut es. Und in den Firefox-Einstellungen steht, dass www.purebasic.com Cookies speichert. Daran kann es nicht liegen.
...
Also gibt es keine Möglichkeit, die eigenen Hardware-Angaben neben den Posts auszublenden? Dann lösche ich diese Angaben im Profil wieder.
...
Leider kann ich hier nicht weiterhelfen am besten mal einen Moderator oder Admin via persönlicher Nachricht anschreiben.

OlderCoder hat geschrieben: 04.07.2021 11:24 ....
Bei meinem eigenen letzten Entwurf gibt es noch das Problem, dass zusätzlich noch eine einzelne Taste erkannt wird, wenn ich zwei Tasten gleichzeitig länger drücke, als die Tastenwiederhol-Verzögerung dauert. Und zwar immer exakt einmal.
Und mein Versuch mit der zusätzlichen Zeile

Code: Alles auswählen

eventID = WaitWindowEvent(20)            ; Ereignis löschen, um zu verhindern, dass auf die 2. Taste erneut reagiert wird
kann das nicht verhindern, hat tatsächlich gar keinen Effekt.
Sonst wär ich ja schon glücklich und zufrieden. Die Version mit 4 Tasten und 8 Richtungen würde ansonsten auch schon funktionieren.
Aber das Problem muss ich noch lösen.
Es fehlt vielleicht nur eine Kleinigkeit. Aber welche?
Im Code wird zu oft WaitWindowEvent() abgefragt!
WaitWindowEvent() sollte immer nur einmal (in der Haptschleife) abgefragt werden.
WindowEvent() hingegen (in einer eigenen Schleife) solange bis alle Events in der Queue abgearbeitet sind.

Auch hat das nichts in der Hauptschleife verloren:

Code: Alles auswählen

Repeat : Until GetAsyncKeyState_(#VK_E)=0 Or KeyboardPushed(#PB_Key_D)
Das führt nur zu Problemen da nicht klar ist wie lange die Haptschleife aufgehalten wird.
Zudem ist die Api Abfrage inkorrekt, hier sollten die richtigen Flags geprüft werden (siehe einer meiner Codes).

Hier noch ein Beispiel wo anstelle der Bewegung direkt erst die Orientierung/Bewegungsrichtung gesetzt wird. :)

Code: Alles auswählen

EnableExplicit

Structure DIRECTION_STRUCT
  StructureUnion
    wasd.a[4]
    code.l
  EndStructureUnion
EndStructure

Enumeration DIRECTION
  #DIR_UP         = $00000001
  #DIR_LEFT       = $00000100
  #DIR_DOWN       = $00010000
  #DIR_RIGHT      = $01000000
  #DIR_LEFT_UP    = $00000101
  #DIR_RIGHT_UP   = $01000001
  #DIR_LEFT_DOWN  = $00010100
  #DIR_RIGHT_DOWN = $01010000
EndEnumeration

Macro KeyPressed(_code_)
  Bool(GetAsyncKeyState_(_code_) & $8000)
EndMacro

Procedure.i Main()
  Protected exit.i
  Protected x.f
  Protected y.f
  Protected dir.DIRECTION_STRUCT
  If InitSprite()
    If OpenWindow(0,0,0,960,600,#Null$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
      If OpenWindowedScreen(WindowID(0),0,0,960,600)
        SetFrameRate(60)
        x = 480
        y = 320
        Repeat
          Repeat
            Select WindowEvent()
              Case #PB_Event_CloseWindow
                exit = #True
              Case #Null
                Break
            EndSelect
          ForEver
          dir\code = 0
          dir\wasd[0] = KeyPressed(#VK_W)
          dir\wasd[1] = KeyPressed(#VK_A)
          dir\wasd[2] = KeyPressed(#VK_S)
          dir\wasd[3] = KeyPressed(#VK_D)
          Select dir\code
            Case #DIR_LEFT        :x - 1.0            :Debug "LEFT"
            Case #DIR_RIGHT       :x + 1.0            :Debug "RIGHT"
            Case #DIR_UP          :y - 1.0            :Debug "UP"
            Case #DIR_DOWN        :y + 1.0            :Debug "DOWN"
            Case #DIR_LEFT_UP     :x - 0.6  :y - 0.6  :Debug "DIR_LEFT_UP"
            Case #DIR_LEFT_DOWN   :x - 0.6  :y + 0.6  :Debug "DIR_LEFT_DOWN"
            Case #DIR_RIGHT_UP    :x + 0.6  :y - 0.6  :Debug "DIR_RIGHT_UP"
            Case #DIR_RIGHT_DOWN  :x + 0.6  :y + 0.6  :Debug "DIR_RIGHT_DOWN"
          EndSelect
          ClearScreen($0)
          If StartDrawing(ScreenOutput())
            Circle(x,y,5)
            StopDrawing()
          EndIf
          FlipBuffers()
        Until exit
      EndIf
      CloseWindow(0)  
    EndIf  
  EndIf
  ProcedureReturn #Null
EndProcedure

Main()

End
Zuletzt geändert von Mijikai am 04.07.2021 12:55, insgesamt 1-mal geändert.
OlderCoder
Beiträge: 109
Registriert: 18.03.2013 12:30
Wohnort: Bayerland
Kontaktdaten:

Re: Zwei Tasten gleichzeitig abfragen, wie geht das?

Beitrag von OlderCoder »

Vielen lieben Dank, Mijikai, werd ich mir anschauen.


Deinen oberen Code hab ich jetzt soweit verstanden. Würde er auch laufen, dann würde er mir sicher bestätigen, dass hier Echtzeitbewegungen entstehen, nicht felderbasierte schrittweise Abläufe.
Ich kann daraus lernen, nur für mein Spiel kann ich es nicht verwenden.

Tut mir sehr leid, ST4242, ich hatte Deinen Beitrag übesehen. Auch hier schau ich mal rein.
Edit: Hab ich kurz gestartet. Hübsch gestaltet mit den Buttons. Aber hier kann ich nicht erkennen, dass bei der Betätigung der Tasten auch immer nur genau ein Tastendruck für die Bewegung der Spielerfigur entsteht, und genau das brauche ich in meinem Spiel. Wie gesagt, das Spiel funktioniert schrittweise. So hat man das damals vor etlichen Jahren gerne gemacht, und es macht, zumindest mir, immer noch Spaß und erzeugt keinen Stress.
Edit: Das hier https://www.myabandonware.com/game/daleks-284/play-284
Zuletzt geändert von OlderCoder am 04.07.2021 13:23, insgesamt 1-mal geändert.
OlderCoder
Beiträge: 109
Registriert: 18.03.2013 12:30
Wohnort: Bayerland
Kontaktdaten:

Re: Zwei Tasten gleichzeitig abfragen, wie geht das?

Beitrag von OlderCoder »

@Mijikai:
Ich hab jetzt bis auf das erste jedes WaitWindowEvent(20) gegen ein WindowEvent() getauscht.
Das Programm verhält sich dadurch unverändert, weder schlechter noch besser. Aber ich hab auch schon überlegt, ob das sinnvoll war.

Dein zweites Code-Zitat ist in meinem Programm gar nicht mehr enthalten. Die KeyboardPushed-Befehle hatte ich wieder entfernt. Ich verwende nur noch ein normales Fenster. Und damit hatte es dann ja auch im großen und ganzen funktioniert.

Danke für Dein weiteres Beispiel. Für mein Spiel allerdings auch nicht verwertbar. Denn ich brauche keine kontinuierlichen Bewegungen, sondern nur einzelne Tasten für die schrittweise Bewegung. Ich hab drüber noch mal das Uralt-Daleks in einer Browser-Version verlinkt.
Vielleicht mal anschauen, damit klar ist, um welches Spielprinzip es mir überhaupt geht.
Wir haben hier wohl ein Problem, dass ich ein sehr altes Spielprinzip umsetzen möchte, dass gar keiner mehr auf dem Schirm hat.
Zuletzt geändert von OlderCoder am 04.07.2021 13:25, insgesamt 2-mal geändert.
OlderCoder
Beiträge: 109
Registriert: 18.03.2013 12:30
Wohnort: Bayerland
Kontaktdaten:

Re: Zwei Tasten gleichzeitig abfragen, wie geht das?

Beitrag von OlderCoder »

Hier nochmal mein Code, wie er jetzt aussieht.

Code: Alles auswählen

; Abfrage 8 Richtungen

;{ Variablen
EnableExplicit
Global e1.b,e3.b,e5.b,e7.b   ; Ergebnis-Variablen der Abfragen
Global eventID               ; Event-Variable
Global evmen                 ; gedrückte Taste
;}

OpenWindow(1,200,200,200,200,"Test")
AddKeyboardShortcut(1,#PB_Shortcut_W,1)      ; Shortcut nach oben
AddKeyboardShortcut(1,#PB_Shortcut_A,7)      ; Shortcut nach links
AddKeyboardShortcut(1,#PB_Shortcut_S,5)      ; Shortcut nach unten
AddKeyboardShortcut(1,#PB_Shortcut_D,3)      ; Shortcut nach rechts

Repeat 
  eventID = WaitWindowEvent(20)
  Select eventID
    Case #PB_Event_Menu                      
      e1=0 : e3=0 : e5=0 : e7=0              ; erst mal Tastenspeicher löschen
      Select EventMenu()                     ; Taste überprüfen     
        Case 1                               ; W?
          e1=1
        Case 3                               ; D?
          e3=1
        Case 5                               ; S?
          e5=1
        Case 7                               ; A?
          e7=1
      EndSelect    
          
  ;Gedrückte Tasten auf gedrückte Nachbartasten überprüfen
      If e1                                      ; Falls W gedrückt wurd
        Repeat                                   ; Solange  
          eventID = WindowEvent()          ; Events abholen
          evmen = EventMenu()
        Until GetAsyncKeyState_(#VK_W)=0 Or evmen=3 Or evmen=7 ; bis entweder W losgelassen oder D oder A gedrückt worden ist
        If evmen=3                               ; wenn zusätzlich D gedrückt wurde
          Debug "W+D"
        ElseIf evmen=7                           ; wenn zusätzlich A gedrückt wurde
          Debug "W+A"
        Else                                     ; wenn nur W losgelassen wurde  
          Debug "W" 
        EndIf  
      ElseIf e3                                  ; Falls D gedrückt wurd
        Repeat                                   ; Solange  
          eventID = WindowEvent()          ; Events abholen
          evmen = EventMenu()
        Until GetAsyncKeyState_(#VK_D)=0 Or evmen=1 Or evmen=5 ; bis entweder D losgelassen oder W oder S gedrückt worden ist
        If evmen=1                               ; wenn zusätzlich W gedrückt wurde
          Debug "D+W"
        ElseIf evmen=5                           ; wenn zusätzlich S gedrückt wurde
          Debug "D+S"
        Else                                     ; wenn nur D losgelassen wurde  
          Debug "D" 
        EndIf  
      ElseIf e5                                  ; Falls S gedrückt wurd
        Repeat                                   ; Solange  
          eventID = WindowEvent()          ; Events abholen
          evmen = EventMenu()
        Until GetAsyncKeyState_(#VK_S)=0 Or evmen=3 Or evmen=7 ; bis entweder S losgelassen oder D oder A gedrückt worden ist
        If evmen=3                                             ; wenn zusätzlich D gedrückt wurde
          Debug "S+D"
        ElseIf evmen=7                                         ; wenn zusätzlich A gedrückt wurde
          Debug "S+A"
        Else                                                   ; wenn nur S losgelassen wurde  
          Debug "S" 
        EndIf  
     ElseIf e7                                   ; Falls A gedrückt wurde
        Repeat                                   ; Solange  
          eventID = WindowEvent()          ; Events abholen
          evmen = EventMenu()
        Until GetAsyncKeyState_(#VK_A)=0 Or evmen=5 Or evmen=1 ; bis entweder A losgelassen oder S oder W gedrückt worden ist
        If evmen=5                                             ; wenn zusätzlich S gedrückt wurde
          Debug "A+S"
        ElseIf evmen=1                                         ; wenn zusätzlich W gedrückt wurde
          Debug "A+W"
        Else                                                   ; wenn nur A losgelassen wurde  
          Debug "A" 
        EndIf  
        Repeat : Until GetAsyncKeyState_(#VK_S)=0 And GetAsyncKeyState_(#VK_W)=0 ; warten bis auch die 2. Taste losgelassen worden ist
     EndIf  
    
  Case #PB_Event_CloseWindow                            
    End
  EndSelect 
  
ForEver
Er ist angepasst an 4 Tasten und 8 Richtungen und verwendet jetzt teilweise andere Variablen.
Drücke ich länger auf 2 Tasten, als die Tastenwiederholverzögerung dauert und lasse dann los, dann wird immer die Taste, die ich zur ersten noch dazugedrückt habe (gleichzeitig ist das ja nie) danach nochmal extra als Tastendruck angezeigt.
Und das darf nicht sein.
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Zwei Tasten gleichzeitig abfragen, wie geht das?

Beitrag von Mijikai »

OlderCoder hat geschrieben: 04.07.2021 13:17 ...
Danke für Dein weiteres Beispiel. Für mein Spiel allerdings auch nicht verwertbar. Denn ich brauche keine kontinuierlichen Bewegungen, sondern nur einzelne Tasten für die schrittweise Bewegung. Ich hatte oben das Uralt-Daleks in einer Browser-Version verlinkt.
Vielleicht mal anschauen, damit klar ist, um welches Spielprinzip es mir überhaupt geht.
?

...Das ist mir klar daher mein zweites Beispiel ​hier wird die Orientierung/Richtung ausgewertet.
Alles visuelle ist nur zu Anschauungszwecken da, was nach der Richtungsabfrage passiert is dem Programmierer überlassen.

Auszug:

Code: Alles auswählen

          Select dir\code
            Case #DIR_LEFT
            Case #DIR_RIGHT
            Case #DIR_UP
            Case #DIR_DOWN
            Case #DIR_LEFT_UP
            Case #DIR_LEFT_DOWN
            Case #DIR_RIGHT_UP
            Case #DIR_RIGHT_DOWN
          EndSelect
Antworten