Seite 1 von 3

Zwei Keyboardtasten gleichzeitig

Verfasst: 19.08.2009 15:23
von Mok
N'Tag!

Ich mach grad ein Programm, wo ich meine (ziemlich schlechte) GraKa bis an ihre Grenzen treiben kann.
Die Funktionsweise: Mit verschiedenen Tastenn kann man verschiedene Sachen auf den Screen zeichnen oder Effekte auslösen, während oben rechts permanent die FPS angezeigt werden.
Bisher habe ich nur Space (Screen bei jedem Schleifendurchlauf mit ClearScreen(RGB(Random(255),Random(255),Random(255)) neu machen) und TAB (Zufällig ein paar 2D-Figuren zeichnen) implementiret und habe eben festgestellt, dass nicht beides gleichzeitig gemacht werden kann.
Mein Snippet:

Code: Alles auswählen

Procedure SetNew()
    
  rnd = Random(4)
  If StartDrawing(ScreenOutput())
    For Objects = 20 To (Random(100)+20)
      new = #False
      If (Random(200) % 2 = 0)
        DrawingMode(#PB_2DDrawing_Outlined)
      EndIf
      Select rnd
        Case 0:
          Box(Random(1000),Random(800),Random(30),Random(40),RGB(Random(255),Random(255),Random(255)))
        Case 1:
          Line(Random(1000),Random(800),Random(50),Random(60),RGB(Random(255),Random(255),Random(255)))
        Case 2:
          Circle(Random(1000),Random(800),Random(42),RGB(Random(255),Random(255),Random(255)))
        Case 3:
          Plot((Objects + 3),(Objects + 5),RGB(Random(255),Random(255),Random(255)))
        Case 4:
          Ellipse(Random(1000),Random(800),Random(50),Random(60),RGB(Random(255),Random(255),Random(255)))
      EndSelect
    Next
    StopDrawing()
  EndIf

EndProcedure

Procedure MyClearScreen()

  RndColorR = Random(255)
  RndColorG = Random(255)
  RndColorB = Random(255)
  ClearScreen(RGB(RndColorR,RndColorG,RndColorB))

EndProcedure

[...]

  If KeyboardPushed(#PB_Key_Tab)
    SetNew()
  ElseIf KeyboardPushed(#PB_Key_Space)
    MyClearScreen()
  Else
    ClearScreen(RGB(255,255,255))
  EndIf
MfG, Mok

Verfasst: 19.08.2009 15:25
von RSBasic
@Mok
Wo ist die Frage?
Oder soll das ein Beispielcode für alle sein?

Falls das ein Beispielcode sein soll, dann bitte immer ein vollständiges Beispiel posten.

Verfasst: 19.08.2009 15:51
von Mok
Ui, 2 neue Probleme. Und keines davon krieg ich alleine weg :(

Problem 1: Wenn ich beide Tasten gleichzeitig drücke, wird nur die Funktion der 1. Taste ausgeführt, ich will aber, dass alle beiden Tasten-Funktionen ausgeführt werden.

Problem 2 (neu): Wenn ich TAB drücke, verschwimmt die FPS-Zahl (weil ich eben kein ClearScreen habe, weil ich soviele Objekte wie möglich zeichnen will). Ist es möglich eine klare FPS-zahl anzuzeigen, den restlichen Screen aber NICHT zu löschen?

Problem 3 (neu): Warum habe ich permanent 0 FPS? So schlecht ist meine GraKa auch wieder net...

Code: Alles auswählen

;{**********************************************
;**    xFPS                                    *
;**    (C)2009 by Wolfram 'aVoX' Weingartner   *
;}**********************************************


;-Procedures:
;
Procedure MyClearScreen()

  RndColorR = Random(255)
  RndColorG = Random(255)
  RndColorB = Random(255)
  ClearScreen(RGB(RndColorR,RndColorG,RndColorB))

EndProcedure

Procedure SetNew()
    
  rnd = Random(4)
  If StartDrawing(ScreenOutput())
    For Objects = 20 To (Random(100)+20)
      new = #False
      If (Random(200) % 2 = 0)
        DrawingMode(#PB_2DDrawing_Outlined)
      EndIf
      Select rnd
        Case 0:
          Box(Random(1000),Random(800),Random(30),Random(40),RGB(Random(255),Random(255),Random(255)))
        Case 1:
          Line(Random(1000),Random(800),Random(50),Random(60),RGB(Random(255),Random(255),Random(255)))
        Case 2:
          Circle(Random(1000),Random(800),Random(42),RGB(Random(255),Random(255),Random(255)))
        Case 3:
          Plot((Objects + 3),(Objects + 5),RGB(Random(255),Random(255),Random(255)))
        Case 4:
          Ellipse(Random(1000),Random(800),Random(50),Random(60),RGB(Random(255),Random(255),Random(255)))
      EndSelect
    Next
    StopDrawing()
  Else
    CloseScreen()
    MessageBox_(#Null,"Could Not draw To Screen","xFPS Error!",#MB_OK|#MB_ICONERROR)
    End
  EndIf

EndProcedure


;-Initializings:
;
If Not InitSprite() Or Not InitKeyboard()
  MessageBox_(#Null,"Fehler beim Initialisieren","Fehler!",#MB_OK|#MB_ICONERROR)
  End
EndIf

If Not OpenScreen(1440,900,32,"xFPS v1.00")
  MessageBox_(#Null,"Fehler beim Öffnen eines Screens","Fehler!",#MB_OK|#MB_ICONERROR)
  End
EndIf


;-Loads:
;
LoadFont(0,"Arial Black",14)


;-MAIN CODE
;
Define.w
  FPS_Timer   = ElapsedMilliseconds()
  FPS         = 0
  FPS_Counter = 0
  new = #True
  
  #R = 255
  #G = 255
  #B = 255
ClearScreen(RGB(#R,#G,#B))


;-* * * M A I N   L O O P   S T A R T * * *
;

Repeat 
  
  If StartDrawing(ScreenOutput())
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawingFont(FontID(0))
    DrawText(0,0,"Current FPS: "+Str(FPS))
    DrawingFont(#PB_Default)
    DrawText(0,30,"Press ESC to exit, press TAB to set new. Press SPACE to ClearScreen permanently.")
  Else
    CloseScreen()
    MessageBox_(#Null,"Could Not draw To Screen","xFPS Error!",#MB_OK|#MB_ICONERROR)
    End
  EndIf
  StopDrawing()
  
  If ElapsedMilliseconds() > FPS_Timer + 1000
    FPS = FPS_Counter
    FPS_Counter = 0
    FPS_Timer = ElapsedMilliseconds()
  Else
    FPS_Counter = FPS_Counter + 1
  EndIf
  
  ExamineKeyboard()

  FlipBuffers(0)
    
  If KeyboardPushed(#PB_Key_Tab)
    SetNew()
  ElseIf KeyboardPushed(#PB_Key_Space)
    MyClearScreen()
  Else
    ClearScreen(RGB(#R,#G,#B))
  EndIf

Until KeyboardPushed(#PB_Key_Escape)

;-* * * M A I N   L O O P   E N D * * *
;
End

Verfasst: 19.08.2009 16:05
von RSBasic
Mit dieser Procedure kannst du die FPS ermitteln:

Code: Alles auswählen

Procedure FPS()
  Static Frame, OldTime, FPS, NewTime
  NewTime = GetTickCount_()
  If Not Frame
    OldTime = NewTime
  EndIf
  FRAME + 1
  If NewTime-OldTime > 1000
    FPS = Frame*1000/(NewTime-OldTime)
    Frame = 0
  EndIf
  ProcedureReturn FPS
EndProcedure

Verfasst: 19.08.2009 16:07
von Mok
Ich hab das mit den FPS aus einem PureBasic-Buch ("Programming 2D Scrolling Games", von Krylar aus'm englischen Forum) und es hat bisher immer gefunzt... aber ich schau mir deine Procedure mal an :)

EDIT:
Supi!
Bleibende Probleme:
Problem 1: Wenn ich beide Tasten gleichzeitig drücke, wird nur die Funktion der 1. Taste ausgeführt, ich will aber, dass alle beiden Tasten-Funktionen ausgeführt werden.

Problem 2 (neu): Wenn ich TAB drücke, verschwimmt die FPS-Zahl (weil ich eben kein ClearScreen habe, weil ich soviele Objekte wie möglich zeichnen will). Ist es möglich eine klare FPS-zahl anzuzeigen, den restlichen Screen aber NICHT zu löschen?

Verfasst: 19.08.2009 17:45
von jojo1541
Du könntest alle Elemente, die angezeigt werden sollen in eine Linkedlist packen und dann via

Code: Alles auswählen

;dein code (mit Clearscreen)
ForEach Sprite()
  Displaysprite(#deinsprite,x,y)
next
;dein weiterer code
;Fps noch anzeigen lassen
anzeigen lassen.

Verfasst: 20.08.2009 15:18
von kswb73
Zu Problem 1. (ohne mir dem Code lange anzusehen)

Code: Alles auswählen

  If KeyboardPushed(#PB_Key_Tab)
    SetNew()
  ElseIf KeyboardPushed(#PB_Key_Space)
    MyClearScreen()
  Else
    ClearScreen(RGB(#R,#G,#B))
  EndIf
Dieser Codeausschnitt von dir ist der Hauptgrund elseif wird nur dann geprüft wenn if fehlschlug. Drückst du Tab und die Leertaste gleichzeitig so liefert KeyboardPushed(#PB_Key_Tab) immer true zurück, mit dem Resultat das elseif KeyboardPushed(#PB_Key_Space) übersprungen wird.
Bei mehreren gleichzeitigen Tastendrücken kann es auch vorkommen, das die Tastatur damit überlastet ist. Windows gibt im normalfall Beep-Töne von sich ab wenn dies der Fall ist

Zu Problem 2. Streich #PB_2ddrawing_Transparent streichst wird der Hintergrund der FPS-Zahl automatisch gefüllt. Besser wäre vielleicht sogar eine Box im Hintergrund zu zeichnen, weil du dann nicht das Problem hast Reste der alten FPS Zahl zu sehen. (Die Box muss nur den Bereich der FPS-Zahl abdecken).

Verfasst: 20.08.2009 20:29
von Mok
kswb73 hat geschrieben:Zu Problem 1. (ohne mir dem Code lange anzusehen)

Code: Alles auswählen

  If KeyboardPushed(#PB_Key_Tab)
    SetNew()
  ElseIf KeyboardPushed(#PB_Key_Space)
    MyClearScreen()
  Else
    ClearScreen(RGB(#R,#G,#B))
  EndIf
Dieser Codeausschnitt von dir ist der Hauptgrund elseif wird nur dann geprüft wenn if fehlschlug. Drückst du Tab und die Leertaste gleichzeitig so liefert KeyboardPushed(#PB_Key_Tab) immer true zurück, mit dem Resultat das elseif KeyboardPushed(#PB_Key_Space) übersprungen wird.
Das versteh ich. Bei folgendem (aktualisiertem) Code würde es mit vielen IFs gehen, aber es wird dadurch immer schwerer den Screen löschen zu lassen, wenn NICHTS gedrückt wird.

Code: Alles auswählen

  If KeyboardPushed(#PB_Key_Tab)
    SetNew()
  ElseIf KeyboardPushed(#PB_Key_Space)
    MyClearScreen()
  ElseIf KeyboardPushed(#PB_Key_LeftShift)
    ExploitCPUPower()
    ClearScreen(RGB(#R,#G,#B))
  Else
    ClearScreen(RGB(#R,#G,#B))
  EndIf

Verfasst: 20.08.2009 21:55
von Rebon
Mok hat geschrieben:

Code: Alles auswählen

  If KeyboardPushed(#PB_Key_Tab)
    SetNew()
  ElseIf KeyboardPushed(#PB_Key_Space)
    MyClearScreen()
  ElseIf KeyboardPushed(#PB_Key_LeftShift)
    ExploitCPUPower()
    ClearScreen(RGB(#R,#G,#B))
  Else
    ClearScreen(RGB(#R,#G,#B))
  EndIf
Bei mir wird es mit diesem Code auch nicht gleichzeitig dargestellt, wobei ich ExploitCPUPower() heraus nahm.
So funktioniert's bei mir:

Code: Alles auswählen

  If KeyboardPushed(#PB_Key_Space) Or KeyboardPushed(#PB_Key_Tab)
    If KeyboardPushed(#PB_Key_Space)
       MyClearScreen()
    EndIf
    If KeyboardPushed(#PB_Key_Tab)
       SetNew()
    EndIf
  Else
    ClearScreen(RGB(#R,#G,#B))
  EndIf

Verfasst: 20.08.2009 22:05
von Mok
@Rebon:
Dran hab ich auch schon gedacht, nur wird das ziemlich aufwändig, wenn ich dann noch ein paar Funktionen hinzufüge... aber ich bin damit zufrieden :D