Buttons für Spiele/Fullscreen-Anwendungen

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Josef Sniatecki
Beiträge: 657
Registriert: 02.06.2008 21:29
Kontaktdaten:

Buttons für Spiele/Fullscreen-Anwendungen

Beitrag 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
Zuletzt geändert von Josef Sniatecki am 17.11.2009 21:22, insgesamt 1-mal geändert.
PB 4.61 | Windows Vista - 32Bit
Homepage

"Wahrlich es ist nicht das Wissen, sondern das Lernen, nicht das Besitzen sondern das Erwerben, nicht das Dasein, sondern das Hinkommen, was den grössten Genuss gewährt." - Carl Friedrich Gauß
iostream
Beiträge: 109
Registriert: 15.06.2008 12:59

Re: Buttons für Spiele/Fullscreen-Anwendungen

Beitrag von iostream »

Sieht gut aus...allerdings bekomme ich einen BlueScreen nach dem Beenden.
(PB 4.40 Beta 5 x64, Windows 7 Professional)
OS: Windows 8.1 Pro
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Buttons für Spiele/Fullscreen-Anwendungen

Beitrag 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
Benutzeravatar
Josef Sniatecki
Beiträge: 657
Registriert: 02.06.2008 21:29
Kontaktdaten:

Re: Buttons für Spiele/Fullscreen-Anwendungen

Beitrag 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.
PB 4.61 | Windows Vista - 32Bit
Homepage

"Wahrlich es ist nicht das Wissen, sondern das Lernen, nicht das Besitzen sondern das Erwerben, nicht das Dasein, sondern das Hinkommen, was den grössten Genuss gewährt." - Carl Friedrich Gauß
Antworten