GUI Gadget Tutorial

Übersicht BlitzMax, BlitzMax NG FAQs und Tutorials

Neue Antwort erstellen

Midimaster

Betreff: GUI Gadget Tutorial

BeitragDo, Aug 09, 2012 1:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Dieses Tutorial wird darstellen, wie man eine verschachtelte GUI erstellt. Es geht nicht so sehr um den optischen Teil, sondern mehr um die Logik, wie man mit Klassen und Listen an eine solche Frage herangeht. Außerdem wird die GUI auflösungsunabhängig von verschiedene Displaygrößen sein.

Hier mal ein erster Blick drauf. Im Monkey-Forum-Codearchiv gibt es übrigens das gesamte Tutorial nochmal für die Sprache Monkey.

user posted image

Dies ist kein Anfänger Tutorial. Es geht nicht um die Verwendung von GUIs, sondern um die Programmierung einer neuen GUI.

Wie bei allen Midimaster-Tutorials werde ich die Kapitel jeweils in eigene Postings stecken und bitte deshalb die Admins, mir ein Mehrfach-Posting zu erlauben. Ebenso soll die Abfolge der Kapitel nicht durch Fragen und Kommentare gestört werden, daher bitte ich alle Antworten hier zu posten: https://www.blitzforum.de/forum...hp?t=33457 . Fragen von Hilfesuchenden bitte hierhin https://www.blitzforum.de/forum/viewforum.php?f=29 und auf keinen Fall in diesen Thread.

Die Kapitel:

Kapitel 1: Alles Gadget oder was?

Kapitel 2: Mütter und Kinder

Kapitel 3: Touch Down

Kapitel 4: Etwas Styling

Kapitel 5: Scrolling
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

Midimaster

BeitragDo, Aug 09, 2012 2:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Kapitel 1: Alles Gadget, oder was?

Zunächst starten wir wie üblich... Tja, und hier zweifle ich, wie ich's schreiben soll. Seit ich Monkey habe könnte man auch mal unüblich starten. Doch das ist heute nicht das Thema.
BlitzMax: [AUSKLAPPEN]
SuperStrict
Graphics 320,480

Global FPS:TTimer,MausIn%

FPS= CreateTimer(30)

Repeat
OnUpdate
OnRender
WaitTimer FPS
Until KeyHit(Key_Escape)


Function OnUpdate()
MausIn=TGadget.Check()
End Function


Function OnRender()
SetClsColor 0,111,0
Cls
TGadget.Draw
SetColor 225,225,225
SetViewport 0,0,999,999
DebugLog "MausIn=" + MausIn
Flip 0
End Function


Type TGadget
Global Liste: TList = New TList

Function Draw%()
Debug="wird gemalt"
Return 0
End Function

Function Check%()
Return 0
End Function
End Type




...fast wie gewöhnlich... Die Repeat-Schleife ist sehr kurz und soll es auch so bleiben. Durch die zwei Funktionsaufrufe sollen alle grafikrelevanten Aktionen von den Update-Aktionen getrennt werden.

Es gibt schon die Klasse Gadget, die später die GUI darstellt, es gibt dort auch schon Funktionen, die vom Hauptprogramm aufgerufen werden, aber die Funktionen sind kompett inhaltslos. Der Vorteil eines solchen Aufbaus ist, dass das Programm schon läuft! Späteres Hinzufügen von Code kann also immer gleich getestet werden: "Wenn das Programm nicht anläuft muss es an dem neuen Code liegen."

Es gibt eine Stringvariable Debug$, die ich mir jederzeit und überall im Code mit Text füllen kann. Das hat sich so bewährt. Ein Beispiel sieht man bem Gadget.Draw(). Die Variable MausIn% wird später enthalten, welches GUI-Element geklickt wurde.

Die Elemente der GUI selbst werden aus immer dem gleichen Typen bestehen. Wir nennen es TGadget. Es kann Frame und Label sein, Button und Ceckbox, Scrollfenster und Silder und, und und....

Jedes dieser Elemente hat eine eindeutige ID, an der es gefunden werden kann. Außerdem die Üblichen Werte wie X, Y, Breite, Höhe, ... Eine Variable Typ unterscheidet dann die Arbeitweise des Gadget.

Die Elemente kommen in eine Liste. Wer zuerst rein kommt liegt optisch (z-Achse) zu unterst. Ein Element kennt seine Eltern, seine Kinder tragen sich später in die Children-Liste ein. So kennt es letztendlich auch seine Kinder.

Daraus ergeben sich die ersten Fields, die unser Gadget haben muss:
BlitzMax: [AUSKLAPPEN]
Type TGadget
Global Liste: TList = New TList

Field Id%,X%,Y%,B%,H%,Typ%,Text$
Field Parent:TGadget, Visible%, Enable%
Field Children:TList= New TList



nun kann man die ersten Gadgets erstellen:
BlitzMax: [AUSKLAPPEN]
Function  OnCreate()
SetUpdateRate 60
' id, x, y, b, h, Typ, Parent-ID
TGadget.Create 1,0,0,360,480,3,0,"" ' Mutter aller Fenster
TGadget.Create 5,2,2, 356,56,1,1,""
End Function
....
Type TGadget
Global Liste: TList = New TList

Field Id%,X%,Y%,B%,H%,Typ%,Text$
Field Parent:TGadget, Visible%, Enable%
Field Children:TList= New TList

Function Create%(Id%,X%,Y%,B%,H%,Typ%,ElternID%,Text$="")
Local loc:TGadget=New TGadget
loc.Id=Id
loc.X=X
loc.Y=Y
loc.B=B
loc.H=H
loc.Typ=Typ
loc.Text=Text
loc.Visible=True
loc.Enable=True
If ElternID>0
loc.Parent=Gadget(ElternID)
loc.Parent.Children.AddLast loc
Else
loc.Parent=Null
EndIf
Liste.AddLast loc
Return 0
End Function


Function Gadget:TGadget(Id%)
For Local loc:TGadget = EachIn Liste
If Id=loc.Id Then Return loc
Next
Return Null
End Function
.....


Interessant dabei dürfte die Funktion Gadget:Gadget(Id%) sein. Sie findet ein Gadget aufgrund seiner Id-Nummer und gibt das Gadget zurück. In unserem Code wird dies bereits benutzt: Die Gadget.Create() sucht aufgrund einer ID-Zahl seine Mutter und hinterlegt sie in dem Feld Parent

Wie ihr seht bleibt alles noch sehr abstrakt und völlig ohne Malen. Dies werde ich erst in Kapitel 2 zeigen.
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe
  • Zuletzt bearbeitet von Midimaster am Do, Aug 09, 2012 20:49, insgesamt 3-mal bearbeitet

Midimaster

Betreff: Kapitel 2: Mütter und Kinder

BeitragDo, Aug 09, 2012 2:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Kapitel 2: Mütter und Kinder

Eine der zentralen Eigenschaften der GUI ist es, zu wissen wo und ob etwas hingemalt werden muss und was der User gerade auswählt. Hier hilft das Mutter-Kinder-Prinzip, das jedes Gadget genau in einen Container unterbringt. Der Container wiederum kann viele Elemente enthalten. Diese Elemente können selbst wieder Container für weitere Gadgets sein. Dies entspricht dem Vorbild einer "Mutter", die viele Kinder haben kann, die wiederum Kinder haben können. Aber jedes Kind hat immer nur eine Mutter.

So kann man sich z.b. ein Scroll-Fenster als rechteckige Mutter vorstellen, die zwei Kinder nebeneinander hat: den rechteckigen sichtbaren Image-Bereich und ein rechteckiges Scroll-Element.Der sichtbare Image-Bereich ist wiederum Mutter des Bildes, das viel größer als der sichtbare Bereich sein kann. Das Scroll-Element ist wiederum Mutter für den rechteckigen Slider, der sich darin bewegen kann. So lassen sich auch scheinbar komplexe Gadget letzendlich in viele kleine nebeneinander oder ineinanderliegende Rechtecke darstellen.

Sehen wir uns zunächst an, wie man die Gadgets zeichnet:

Es beginnt immer bei der Mutter aller Mütter. Dem einzigen Gadget, dass selbst keine Mutter hat. Oft wird es "Fenster" genannt.

BlitzMax: [AUSKLAPPEN]
Type TGadget
...
Function Draw%()
' Mutter-X, Mutter-Y, Viewport-X1,Viewport-Y1, Viewport-X2, Viewport-Y2
Liste.First.DrawOne (0,0,0,0,999,999)
Return 0
End Function


Method DrawOne%(offX%,offY%,sX%,sY%,sX2%,sY2%)
If Visible=False Then Return 0
SetFarbe Typ
offX=offX+X
offY=offY+Y
If offX>sX Then sX=offX
If offY>sY Then sY=offY
If offX+B<sX2 Then sX2=offX+B
If offY+H<sY2 Then sY2=offY+H
If (sX2<sX) Or (sY2<sY) Then Return 0
SetViewport sX , sY, (sX2-sX) , (sY2-sY)
' hier das eigentliche Malen:
SetFarbe 100+Typ*10
DrawRect offX, offY,B,H
SetFarbe 101+Typ*10 + Sgn(Check()=Id)
DrawRect offX+2, offY+2,B-4,H-4
SetFarbe 103+Typ*10
DrawGadgetText Text, offX+B/2, offY+H/4,1

'
For Local loc:TGadget = EachIn Childrene
loc.DrawOne (offX+2, offY+2, sX+2, sY+2 , sX2-2, sY2-2)
Next
Return 0
End Method
....



Die Funktion Gadget.Draw() startet eigentlich nur das Malen der ÜberMutter, die dann rekursiv auch ihre Töchter malen wird. Die Parameter die dabei übergeben werden sind die Koordinaten und Malgrenzen des Bildschirms. Der Viewport() ist eine Funktion, die den Malbereich auf ein Rechteckauschnitt beschränkt. Zunächst steht er für die Übermutter auf "unendlich". später werden die Gadgets ihre eigenen Grenzen so an die Kinder weiterreichen.

Das Malen erfolgt in der Methode Gadget.DrawOne()

Ist das Gadget nicht visible wird gleich abgebrochen und so auch die Kinder erst gar nicht gemalt. Zu den eigenen Koordinaten X Y werden die Koordinaten der Mutter offX offY addiert

Hier wird der ViewPort auf seine neuen Grenzen eigestellt. Sind die Ausmaße des Gadget enger als der bisherige Viewport, werden diese Aumaße als zukünftige Grenze des Viewport festgesetzt:
BlitzMax: [AUSKLAPPEN]
			If offX>sX Then sX=offX
If offY>sY Then sY=offY
If offX+B<sX2 Then sX2=offX+B
If offY+H<sY2 Then sY2=offY+H
If (sX2<sX) Or (sY2<sY) Then Return 0
SetViewport sX , sY, (sX2-sX) , (sY2-sY)


Die vorletzte Zeile erzwingt einen Abbruch des Malens, wenn der Viewport jetzt eine Breite oder Höhe unter Null haben sollte. Dies wird immer dann der Fall sein, wenn das Gadget außerhalb des sichtbaren Bereichs liegt. Auch die Kinder werden so nicht mehr gemalt.

Schließlich wird gemalt. Während der Erprobungsphase genügt es hier ein farbiges Rechteck zu zeichnen. Wenn des damit funktioniert wird es später auch mit aufwendigen Themes gelingen.

Nun kommt der interessanteste Teil. Das Gadget ruft seine Kinder auf und übergibt als Parameter seine eigenem X Y Koordinaten, sowie den soeben neu ausgerechneten Viewport, der aber um die Rahmenbreite verkleinert wird:
BlitzMax: [AUSKLAPPEN]
			For Local loc:TGadget = EachIn Children
loc.DrawOne (offX+2, offY+2, sX+2, sY+2 , sX2-2, sY2+2)
Next

Nachzutragen bleibt nur noch eine kleine Funktion SetFarbe(), die während der Simulation zur Unterscheidung der Gadgets dient. Sie legt für die Gadgets unterschiedliche Farben fest. Später könnte man hier komplette Themes und Styles festlegen.

Und so sieht nun unsere GUI momentan aus:
BlitzMax: [AUSKLAPPEN]
SuperStrict
Graphics 320,480

Global FPS:TTimer,MausIn%,Debug$
FPS= CreateTimer(30)
OnCreate
Repeat
OnUpdate
OnRender
WaitTimer FPS
Until KeyHit(Key_Escape)

Function OnCreate()
TGadget.Create 1,0,0,360,480,3,0,"" ' Mutter aller Fenster
TGadget.Create 2,0,0,360,120,3,1,"" ' Mutter für Top feld
TGadget.Create 5,2,2, 356,56,1,1,""
TGadget.Create 6,5,65, 90,50,0,2,"A"
TGadget.Create 7,105,65, 90,50,0,2,"B"
TGadget.Create 8,205,65, 70,50,0,2,"C"
TGadget.Create 9,305,65, 70,50,0,2,"D"
End Function


Function OnUpdate()
MausIn=TGadget.Check()
End Function


Function OnRender()
SetClsColor 0,111,0
Cls
TGadget.Draw
SetColor 225,225,225
SetViewport 0,0,999,999
DrawText "MausIn=" + MausIn + " Debug=" + Debug,10,10
Flip 0
End Function


Type TGadget
Global Liste: TList = New TList

Field Id%,X%,Y%,B%,H%,Typ%,Text$
Field Parent:TGadget, Visible%, Enable%
Field Children:TList= New TList

Function Create%(Id%,X%,Y%,B%,H%,Typ%,ElternID%,Text$="")
Local loc:TGadget=New TGadget
loc.Id=Id
loc.X=X
loc.Y=Y
loc.B=B
loc.H=H
loc.Typ=Typ
loc.Text=Text
loc.Visible=True
loc.Enable=True
If ElternID>0
loc.Parent=Gadget(ElternID)
loc.Parent.Children.AddLast loc
Else
loc.Parent=Null
EndIf
Liste.AddLast loc
Return 0
End Function


Function Gadget:TGadget(Id%)
For Local loc:TGadget = EachIn Liste
If Id=loc.Id Then Return loc
Next
Return Null
End Function


Function Draw%()
Liste.First.DrawOne (0,0,0,0,999,999)
Return 0
End Function


Method DrawOne%(offX%,offY%,sX%,sY%,sX2%,sY2%)
If Visible=False Then Return 0
SetFarbe Typ
offX=offX+X
offY=offY+Y
If offX>sX Then sX=offX
If offY>sY Then sY=offY
If offX+B<sX2 Then sX2=offX+B
If offY+H<sY2 Then sY2=offY+H
If (sX2<sX) Or (sY2<sY) Then Return 0
SetViewport sX , sY, (sX2-sX) , (sY2-sY)
' hier das eigentliche Malen:
SetFarbe 100+Typ*10
DrawRect offX, offY,B,H
SetFarbe 101+Typ*10 + Sgn(Check()=Id)
DrawRect offX+2, offY+2,B-4,H-4
SetFarbe 103+Typ*10
DrawGadgetText Text, offX+B/2, offY+H/4,1

'
For Local loc:TGadget = EachIn Children
loc.DrawOne (offX+2, offY+2, sX+2, sY+2, sX2-2, sY2-2)
Next
Return 0
End Method

Method DrawGadgetText(T$,X%,Y%,Style%)
DrawText T,X, Y
End Method

Function Check%()
Return 0
End Function
End Type






Function SetFarbe(FarbTon%)
Select FarbTon
Case 0
SetColor 0,0,0
Case 1
SetColor 255,255,255
Case 100
SetColor 222,222,222
Case 101
SetColor 90,90,90
Case 102
SetColor 90,90,110
Case 103
SetColor 222,222,222
Case 110
SetColor 150,150,150
Case 111
SetColor 244,244,244
Case 112
SetColor 244,244,244
Case 113
SetColor 55,55,55
Case 120
SetColor 150,150,150
Case 121
SetColor 50,50,50
Case 122
SetColor 50,50,70
Case 123
SetColor 255,255,255
Case 130,131,132,133
SetColor 1,1,1
End Select
End Function



In der Praxis

Hier einige Experimente, die Ihr jetzt schon mit diesem Teil ausprobieren könnt. Dazu müsst ihr im Code siehe oben immer die OnCreate() und OnUpdate() durch die Beispiele ersetzen.


Mutter und Tochter

wenn die Mutter bewegt wird geht die Tochter mit:
BlitzMax: [AUSKLAPPEN]
Function OnCreate()
TGadget.Create 1,0,0,360,480,3,0,"" ' Mutter aller Fenster
TGadget.Create 2,40,40,200,100,2,1,"" 'eine Tochter in grau
End Function


Function OnUpdate()
TGadget.Gadget(1).X:+1
End Function




Fenstergrenzen

Als Alternative bewegt Ihr mal Gadget 2. Tatsächlich sorgt die Gadget.Draw() bereits dafür, dass die Tochter nicht über die Mutter hinausgemalt wird:
BlitzMax: [AUSKLAPPEN]
Function OnUpdate()
TGadget.Gadget(2).X:+1
End Function





unterschiedliche Gadgets

Oder ändert mal den "Typ". Sofort ändert sich die Farbe des Gadget:
BlitzMax: [AUSKLAPPEN]
' die "0" ist der Typ:
' Beispiele 0=grau/weißer Rand, 1=weiß wie Textfield, 3=schwarz ohne Rand wie Frame
TGadget.Create 2,40,40,200,100,0,1,"" 'eine Tochter in grau



Z-Order: Wer überdeckt wen?

Zwei Gadgets auf der selben Ebene. Das zuerst erstellt wird zu unterst gemalt:
BlitzMax: [AUSKLAPPEN]
Function OnCreate()
' id, x, y, b, h, Typ, Parent-ID
TGadget.Create 1,0,0,360,480,3,0,"" ' Mutter aller Fenster
TGadget.Create 2,40,40,200,100,2,1,"" 'eine Tochter in grau
TGadget.Create 3,20,200,200,50,1,1,"" 'eine 2.Tochter in in weiß
End Function

Function OnUpdate()
If KeyHit(KEY_ESCAPE) Then Error ""
TGadget.Gadget(2).Y+=1
End Function




Verschachtelung

Mutter, Tochter, Enkel:
BlitzMax: [AUSKLAPPEN]
Function OnCreate()
' id, x, y, b, h, Typ, Parent-ID
TGadget.Create 1,0,0,360,480,3,0,"" ' Mutter aller Fenster
TGadget.Create 2,40,40,200,100,2,1,"" 'eine Tochter in grau
TGadget.Create 3,20,200,200,50,1,1,"" 'eine 2.Tochter in weiß
End Function

Function OnUpdate()
If KeyHit(KEY_ESCAPE) Then Error ""
TGadget.Gadget(2).Y+=1
TGadget.Gadget(3).X-=1
End Function



Ein Slider entsteht aus 4 Grundgadgets:

BlitzMax: [AUSKLAPPEN]
Function OnCreate()
' id, x, y, b, h, Typ, Parent-ID
TGadget.Create 1,0,0,360,480,1,0,"" ' Mutter aller Fenster
TGadget.Create 2,40,40,300,30,2,1,"" 'eine Hülle für einen Slider
TGadget.Create 5,122,2,126,26,1,2,"" 'der Slider
TGadget.Create 3,1,1,28,28,0,2,"" 'linker button
TGadget.Create 4,271,1,28,28,0,2,"" 'rechter button

End Function

Function OnUpdate()
If KeyHit(KEY_ESCAPE) Then Error ""
TGadget.Gadget(5).X-=1
If TGadget.Gadget(5).X<30 Then TGadget.Gadget(5).X=150
End Function

Midimaster

Betreff: Kapitel 3: Maus

BeitragDo, Sep 06, 2012 2:58
Antworten mit Zitat
Benutzer-Profile anzeigen
In diesem Kapitel werten wir die Aktionen aus, die in der GUI geschehen können. Hierfür brauchen wir weitere globale Parameter:

BlitzMax: [AUSKLAPPEN]
Type TGadget
...
Global MausX%,MausY%,MausHit%,StartMausX%,StartMausY%,WarScrolling%
...




Zunächst sehen die Funktionen TGadget.Check() und TGadget.CheckOne() den Draw()-Funktionen sehr ähnlich:
BlitzMax: [AUSKLAPPEN]
	Function Check%()
MausAction
Local T:TGadget=TGadget(Liste.First())
Return T.CheckOne(0,0,0,0,999,999)
End Function

Method CheckOne%(offX%,offY%,sX%,sY%,sX2%,sY2%)
Local In%,LastIn%=0
If Visible=False Then Return 0
offX=offX+X
offY=offY+Y
If offX>sX Then sX=offX
If offY>sY Then sY=offY
If offX+B<sX2 Then sX2=offX+B
If offY+H<sY2 Then sY2=offY+H
If (sX2<sX) Or (sY2<sY) Then Return 0
.....


Die TGadget.Check() beginnt mit Check der Übermutter, die dann rekursiv alle ihre Kinder rufen wird. Vorher wird der Maus-Zustand festgestellt

Die TGadget.CheckOne() erhält beim Aufruf wieder die Koordinaten der Mutter sowie den von ihr gesetzten Viewport. Die Tests und Berechnungen sind die gleichen wie bei Draw.

Danach wird untersucht, ob die Maus sich innerhalb des Gadget befindet und die ID des Gadget gemerkt:
BlitzMax: [AUSKLAPPEN]
....
If MausX>sX And MausX<sX2
If MausY>sY And MausY<sY2
LastIn=Id
Local locChildren:TList=Children.Reversed()
For Local loc:TGadget = EachIn locChildren
In=loc.CheckOne (offX+2, offY+2, sX+2, sY+2, sX2-2, sY2-2)
If Enable=True
If In<>0 Then Return In
EndIf
Next
If Enable=False Then Return -1
Scroll
EndIf
EndIf
Return LastIn
End Method

Nur wenn dies der Fall ist, werden auch die Kindern durchsucht. Wäre die Maus auch dort, würde dies vorgehen. Erst im letzten Moment vor der Rückgabe des Ergebnis wird geprüft, ob dem Gadget überhaupt erlaubt ist, Werte zu liefern. Anders als beim Malen, kann ja ein Disable Gadget Kinder enthalten, die Enabled sind.

Rekursionen sind immer schwer in ihrer Gesamtwirkung zu verstehen. Doch es gilt: "Funktioniert es für ein Element, dann funktioniert es auch für alle anderen, dann funktioniert es auch für das Ganze."

Die Gadget.CheckOne() verweist bereits auf eine Scroll()-Funktion, die ich aber erst im Kapitel 4 vorstellen werde. Deshalb jetzt nur:
BlitzMax: [AUSKLAPPEN]
	Method Scroll()
End Method



Das Maus-Ereignis bekommt eine eigene Funktion, die in der Lage ist, ziehende Gesten von einfachen Punktberührungen zu unterscheiden:

BlitzMax: [AUSKLAPPEN]
	Function MausAction()
MausX=MouseX()
MausY=MouseY()
If MausHit<>MouseDown(1)
Select MausHit
Case 0
MausHit=1
StartMausX=MausX
StartMausY=MausY
WarScrolling=MausX+MausY
Case 1
MausHit=2
StartMausX=0
StartMausY=0
If Abs(WarScrolling-(MausX+MausY))>20
MausHit=0
EndIf
Case 2
MausHit=0
WarScrolling=0
End Select
EndIf
End Function



Die Funktion stellt die Werte MausX% MausY% und MausHit% zur Verfügung. MausHit% kennt dabei drei Zustände:

0=Maus nicht gedrückt
1=Maus ist gedrückt
2=Maus wurde an der selben Stelle losgelassen

Bei Berührung spring MausHit zunächst auf 1 und springt beim Loslassen aber nur dann in den Zustand 2, wenn sich die Maus seitdem nicht allzuweit bewegt hat. Damit lässt sich "Ziehen" von "Klicken" unterscheiden.


Abschließend wieder der gesamte Code. Man kann nun schon sehr schön in der Kondsole sehen, dass "Ziehen" zu keinen Clicks führt:

BlitzMax: [AUSKLAPPEN]
SuperStrict
Graphics 800,600
Main
End

Global Game:MyGame, Debug$, MausIn%

Type MyGame

Field FPS:TTimer

Method OnCreate()
FPS= CreateTimer(10)
TGadget.Create 1,0,0,360,480,3,0,"" ' Mutter aller Fenster
TGadget.Create 2,0,0,360,120,3,1,"" ' Mutter für Top feld
TGadget.Create 5,2,2, 356,56,1,1,""
TGadget.Create 6,5,65, 90,50,0,2,"A"
TGadget.Create 7,105,65, 90,50,0,2,"B"
TGadget.Create 8,205,65, 70,50,0,2,"C"
TGadget.Create 9,305,65, 70,50,0,2,"D"
End Method



Method OnUpdate()
MausIn=TGadget.Check()
End Method



Method OnRender()
SetClsColor 0,111,0
Cls
TGadget.Draw
SetColor 5,5,5
SetViewport 0,0,999,999
DrawText "MausIn=" + MausIn + " Debug=" + Debug,10,10
Flip 0
End Method
End Type




Function Main%()
Game:MyGame =New MyGame
Game.OnCreate
Repeat
Game.OnUpdate
Game.OnRender
WaitTimer Game.FPS
Until KeyHit(Key_Escape)
End Function




Type TGadget
Global Liste: TList = New TList
Global MausX%,MausY%,MausHit%,StartMausX%,StartMausY%,WarScrolling%

Field Id%,X%,Y%,B%,H%,Typ%,Text$
Field Parent:TGadget, Visible%, Enable%
Field Children:TList= New TList

Function Create%(Id%,X%,Y%,B%,H%,Typ%,ElternID%,Text$="")
Local loc:TGadget=New TGadget
loc.Id=Id
loc.X=X
loc.Y=Y
loc.B=B
loc.H=H
loc.Typ=Typ
loc.Text=Text
loc.Visible=True
loc.Enable=True
If ElternID>0
loc.Parent=Gadget(ElternID)
loc.Parent.Children.AddLast loc
Else
loc.Parent=Null
EndIf
Liste.AddLast loc
Return 0
End Function


Function Gadget:TGadget(Id%)
For Local loc:TGadget = EachIn Liste
If Id=loc.Id Then Return loc
Next
Return Null
End Function


Function Draw%()
Gadget(1).DrawOne (0,0,0,0,999,999)
Return 0
End Function


Method DrawOne%(offX%,offY%,sX%,sY%,sX2%,sY2%)
If Visible=False Then Return 0
SetFarbe Typ
offX=offX+X
offY=offY+Y
If offX>sX Then sX=offX
If offY>sY Then sY=offY
If offX+B<sX2 Then sX2=offX+B
If offY+H<sY2 Then sY2=offY+H
If (sX2<sX) Or (sY2<sY) Then Return 0
SetViewport sX , sY, (sX2-sX) , (sY2-sY)

' hier das eigentliche Malen:
SetFarbe 100+Typ*10
DrawRect offX, offY,B,H
SetFarbe 101+Typ*10 + Sgn(Check()=Id)
DrawRect offX+2, offY+2,B-4,H-4
SetFarbe 103+Typ*10
DrawGadgetText Text, offX+B/2, offY+H/4,1

'
For Local loc:TGadget = EachIn Liste
If loc.Parent=Self
loc.DrawOne (offX, offY, sX, sY , sX2, sY2)
EndIf
Next
Return 0
End Method

Method DrawGadgetText(T$,X%,Y%,Style%)
DrawText T,X, Y
End Method



Function Check%()
MausAction
Local T:TGadget=TGadget(Liste.First())
Return T.CheckOne(0,0,0,0,999,999)
End Function

Method CheckOne%(offX%,offY%,sX%,sY%,sX2%,sY2%)
Local In%,LastIn%=0
If Visible=False Then Return 0
offX=offX+X
offY=offY+Y
If offX>sX Then sX=offX
If offY>sY Then sY=offY
If offX+B<sX2 Then sX2=offX+B
If offY+H<sY2 Then sY2=offY+H
If (sX2<sX) Or (sY2<sY) Then Return 0
If MausX>sX And MausX<sX2
If MausY>sY And MausY<sY2
LastIn=Id
Local locChildren:TList=Children.Reversed()
For Local loc:TGadget = EachIn locChildren
In=loc.CheckOne (offX+2, offY+2, sX+2, sY+2, sX2-2, sY2-2)
If Enable=True
If In<>0 Then Return In
EndIf
Next
If Enable=False Then Return -1
Scroll
EndIf
EndIf
Return LastIn
End Method


Function MausAction()
MausX=MouseX()
MausY=MouseY()
If MausHit<>MouseDown(1)
Print MausHit
Select MausHit
Case 0
MausHit=1
StartMausX=MausX
StartMausY=MausY
WarScrolling=MausX+MausY
Case 1
MausHit=2
StartMausX=0
StartMausY=0
If Abs(WarScrolling-(MausX+MausY))>20
MausHit=0
EndIf
Case 2
MausHit=0
WarScrolling=0
End Select
EndIf
End Function


Method Scroll()
End Method



End Type






Function SetFarbe(FarbTon%)
Select FarbTon
Case 0
SetColor 0,0,0
Case 1
SetColor 255,255,255
Case 100
SetColor 222,222,222
Case 101
SetColor 90,90,90
Case 102
SetColor 90,90,110
Case 103
SetColor 222,222,222
Case 110
SetColor 150,150,150
Case 111
SetColor 244,244,244
Case 112
SetColor 244,244,244
Case 113
SetColor 55,55,55
Case 120
SetColor 150,150,150
Case 121
SetColor 50,50,50
Case 122
SetColor 50,50,70
Case 123
SetColor 255,255,255
Case 130,131,132,133
SetColor 1,1,1
End Select
End Function

Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG FAQs und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group