Seite 1 von 1

Buttons für Spiele/Fullscreen-Anwendungen

Verfasst: 22.10.2009 16:09
von Josef Sniatecki
Hallo,

nachdem ich ein paar Informationen gesammelt habe und nun an
einem Brettspiel arbeite, habe ich mal ein Button-Include
zusammengebastelt:

Code: Alles auswählen

;******************************************
; Constants
;******************************************

Enumeration
  #Button_Normal
  #Button_MouseOver
  #Button_Push
EndEnumeration



;******************************************
; Structures
;******************************************

Structure Button
  Sprite.i
  State.i
  X.i
  Y.i
  Width.i
  Height.i
EndStructure



;******************************************
; Variables
;******************************************

Global *Button_Array
Global Button_MaxIndex.i
Global *Button_Current.Button
Global Button_Pushed.i

ExamineDesktops()
Global PreviousWidth     = DesktopWidth(0)
Global PreviousHeight    = DesktopHeight(0)
Global PreviousDepth     = DesktopDepth(0)
Global PreviousFrequency = DesktopFrequency(0)


;******************************************
; Functions
;******************************************

Procedure.i UseButtons(Array Button.Button(1))
  *Button_Array   = @Button(0)
  Button_MaxIndex = ArraySize(Button())
  *Button_Current = 0
EndProcedure
Procedure.i SetButton(Index.i, Sprite.i, X.i, Y.i)
  Protected *Button.Button = *Button_Array + Index * SizeOf(Button)
 
  *Button\Sprite = Sprite
  If Sprite
    *Button\State  = #Button_Normal
    *Button\X      = X
    *Button\Y      = Y
    *Button\Width  = SpriteWidth(Sprite) / 3
    *Button\Height = SpriteHeight(Sprite)
  EndIf
EndProcedure

Procedure.i ExamineButtons(Event.i, MouseX.i, MouseY.i)
  Protected *Button.Button, Index.i
 
  If *Button_Current
    *Button = *Button_Current
    Select *Button\State
      Case #Button_MouseOver
        If Not (MouseX => *Button\X And MouseX < *Button\X + *Button\Width And MouseY => *Button\Y And MouseY < *Button\Y + *Button\Height)
          *Button_Current = #Null
          *Button\State = #Button_Normal
        ElseIf Event = #WM_LBUTTONDOWN Or Event = #WM_LBUTTONDBLCLK
          *Button\State = #Button_Push
        EndIf
      Case #Button_Push
        If Event = #WM_LBUTTONUP
          If MouseX => *Button\X And MouseX < *Button\X + *Button\Width And MouseY => *Button\Y And MouseY < *Button\Y + *Button\Height
            *Button\State   = #Button_MouseOver
            Button_Pushed   = (*Button - *Button_Array) / SizeOf(Button)
            ProcedureReturn #True
          Else
            *Button_Current = #Null
            *Button\State   = #Button_Normal
          EndIf
        EndIf
    EndSelect
  Else
    *Button = *Button_Array
    For Index = 0 To Button_MaxIndex
      If *Button\Sprite
        If MouseX => *Button\X And MouseX < *Button\X + *Button\Width And MouseY => *Button\Y And MouseY < *Button\Y + *Button\Height
          *Button\State = #Button_MouseOver
          *Button_Current = *Button
          Break
        EndIf
        *Button + SizeOf(Button)
      EndIf
    Next
  EndIf
 
  ProcedureReturn #False
EndProcedure
Procedure.i DisplayButtons()
  Protected *Button.Button = *Button_Array, Index.i
 
  For Index = 0 To Button_MaxIndex
    If *Button\Sprite
      ClipSprite(*Button\Sprite, *Button\State * *Button\Width, 0, *Button\Width, *Button\Height)
      DisplaySprite(*Button\Sprite, *Button\X, *Button\Y)
    EndIf
    *Button + SizeOf(Button)
  Next
EndProcedure
Procedure.i DisplayTransparentButtons()
  Protected *Button.Button = *Button_Array, Index.i
 
  For Index = 0 To Button_MaxIndex
    If *Button\Sprite
      ClipSprite(*Button\Sprite, *Button\State * *Button\Width, 0, *Button\Width, *Button\Height)
      DisplayTransparentSprite(*Button\Sprite, *Button\X, *Button\Y)
    EndIf
    *Button + SizeOf(Button)
  Next
EndProcedure
Procedure.i PushedButton()
  ProcedureReturn Button_Pushed
EndProcedure





;******************************************
; Example
;******************************************

Procedure.i SetScreenSettings(Width.i ,Height.i, BitsPerPel.i ,Frequency.i ,TestMode.i = 0)
   ; Danke an "fluid byte"!
   Protected DevMode.DEVMODE
   
   DevMode\dmSize             = SizeOf(DEVMODE)
   DevMode\dmFields           = #DM_BITSPERPEL | #DM_PELSWIDTH | #DM_PELSHEIGHT | #DM_DISPLAYFREQUENCY
   DevMode\dmBitsPerPel       = BitsPerPel
   DevMode\dmPelsWidth        = Width
   DevMode\dmPelsHeight       = Height
   DevMode\dmDisplayFrequency = Frequency
   
   ProcedureReturn ChangeDisplaySettings_(@DevMode, TestMode)
EndProcedure



Global Sprite.i
Global Dim Button.Button(5)



InitSprite()

SetScreenSettings(1024, 768, 32, 60) ;Wenn nötig anpassen!
OpenWindow(0, 0, 0, 0, 0, "Test", #PB_Window_Maximize|#PB_Window_BorderLess)
OpenWindowedScreen(WindowID(0), 0, 0, 1024, 768, 0, 0, 0) ;Hier ebenso anpassen, wenn nötig!



Sprite = CreateSprite(#PB_Any, 80 * 3, 30)
StartDrawing(SpriteOutput(Sprite))
  Box(0  , 0, 80, 30, $C0C0C0) ;Normal
  Box(80 , 0, 80, 30, $FF0000) ;Mouse over
  Box(160, 0, 80, 30, $800000) ;Push
StopDrawing()



UseButtons(Button())
For I = 0 To 5
  SetButton(I, Sprite, 200, 200 + I*40)
Next

Repeat
  Event = WindowEvent()
 
  ClearScreen(#Black)
    ; Buttons anzeigen:
    DisplayButtons()
  FlipBuffers()
 
  ; Events für Buttons abfragen:
  If ExamineButtons(Event, WindowMouseX(0), WindowMouseY(0))
    ; Button wurde gedrückt:
    Debug "Button nr. " + Str(PushedButton() + 1) + " pushed"
  Else
    ; Sonstige Abfragen:
    Select Event
      Case #WM_KEYDOWN
        If EventwParam() = #VK_ESCAPE
          Break
        EndIf
    EndSelect
  EndIf
 
  Delay(1)
ForEver



CloseWindow(0)
SetScreenSettings(PreviousWidth, PreviousHeight, PreviousDepth, PreviousFrequency)
End
Die Benutzung ist anschaulich im Code vorgeführt. Trotzdem ein paar Hinweise:
- Das Include verwendet das Eventhandling von normalen Fenstern
- Anstatt OpenScreen verwende ich ein Borderless WindowedScreen
- Die Sprites für Buttons bestehen aus drei seitlich aneinandergereihten Teilen: "Unaktiv", "Fokus" und "Eingedürckt"
- Die Größe eines Button-Sprites ist egal, solange die Breite durch 3 Teilbar ist

Ansonsten denke ich mal, dass alles Weitere klar ist.

Wenn es Fragen, Kommentare und irgendwelche Anregungen gibt, dann bitte posten.

Viel Spaß damit!
Gruß Josef

Re: Buttons für Spiele/Fullscreen-Anwendungen

Verfasst: 16.11.2009 23:42
von iostream
Sieht gut aus...allerdings bekomme ich einen BlueScreen nach dem Beenden.
(PB 4.40 Beta 5 x64, Windows 7 Professional)

Re: Buttons für Spiele/Fullscreen-Anwendungen

Verfasst: 16.11.2009 23:50
von ts-soft
böhze Falle :mrgreen:
Problemsignatur:
Problemereignisname: BlueScreen
Betriebsystemversion: 6.1.7600.2.0.0.256.1
Gebietsschema-ID: 1031

Zusatzinformationen zum Problem:
BCCode: 1000007e
BCP1: FFFFFFFFC0000094
BCP2: FFFFF96000795577
BCP3: FFFFF88005DF0778
BCP4: FFFFF88005DEFFD0
OS Version: 6_1_7600
Service Pack: 0_0
Product: 256_1

Dateien, die bei der Beschreibung des Problems hilfreich sind:
C:\Windows\Minidump\111609-30156-01.dmp
C:\Users\Thomas\AppData\Local\Temp\WER-79156-0.sysdata.xml

Re: Buttons für Spiele/Fullscreen-Anwendungen

Verfasst: 17.11.2009 21:12
von Josef Sniatecki
OMG was habe ich nur gemacht :shock:

Versucht mal die beiden Aufrufe von "SetScreenSettings" zu entfernen. Ich denke, dann müsste Win7 nicht mehr mit einem " :bluescreen:" abspringen.

EDIT: Und falls ihr gerne Testen wollt, könnt ihr nochmal den obigen Code ausprobieren. Hab nähmlich am Ende die vorherigen Dimensionen angegeben, anstatt 0 für jeden Parameter.