Eigener Button

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Shyiox

Betreff: Eigener Button

BeitragFr, Dez 07, 2012 14:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Heyho,
ich bin vor ein Paar Tagen durch einen Wettbewerb in der Schule mal wieder auf BB aufmerksam geworden und habe auch mein Projekt für diesen Wettbewerb mit BB geschrieben.
Dort ging es jedoch nur darum, das es funktioniert, das "wie" war egal.

Jetzt jedoch beschäftige ich mich mit BB auch wieder in meiner Freizeit und ich bin gerade dabei ein kleines aber feines Spiel zu programmieren, um meine Kenntnisse wieder aufzufrischen.
Dieses mal jedoch geht es mir aber auch um die Effektivität die ich in meiner Programmierung verwende, da man ja stets bestrebt ist diese zu verbessern.

Also, nun zum eigentlichen Problem, zudem ich leider in der Suchfunktion nichts gefunden habe Confused

Ich bin gerade dabei mir meine eigene Button-Funktion zu schreiben, die folgende Eigenschaften hat:
- Button wird erst wirklich geklickt, wenn man die Maus über ihm wieder loslässt
- Button wird nicht geklickt, wenn man die Maus außerhalb des Buttons loslässt
- andere Buttons werden von dem Mausklick der auf dem Button gestartet wurde NICHT geklickt
- Animation (nebensächlich - der Code ist wichtig)

Mein Code sieht bis jetzt so aus:

BlitzBasic: [AUSKLAPPEN]
Function button(id,x,y,sx,sy,t$)

Local mx=MouseX()
Local my=MouseY()

; Mouse-Check
If mx>x Then
If mx<x+sx Then
If my>y Then
If my<y+sy Then
mo=1
EndIf
EndIf
EndIf
EndIf

If mo Then
If mp=0 Then
If mh Then
mp=id
EndIf
Color 192,192,192
ElseIf mp=id Then
If md=1 Then
Color 64,64,64
ElseIf md=0 Then
state=1
mp=0
EndIf
Else
Color 128,128,128
EndIf
Else
If md=0 Then
mp=0
EndIf
Color 128,128,128
EndIf

; Draw
Rect x,y,sx,sy
Color 255,0,0
Text x+sx/2,y+sy/2,t$,1,1

Return state
End Function


Die globalen Variablen im Hauptprogramm sind:

BlitzBasic: [AUSKLAPPEN]
Global mp
Global mh
Global md


wobei

BlitzBasic: [AUSKLAPPEN]
mh=MouseHit(1)
md=MouseDown(1)


Die Button Funktion wird also Beispielsweise so aufgerufen:

BlitzBasic: [AUSKLAPPEN]
button(ID,x-Position,y-Position,x-Größe,y-Größe,"Beschriftung") 


Beispiel:

BlitzBasic: [AUSKLAPPEN]
If button(2,128,208,128,64,"Button") Then
[...]
EndIf


Nun zu mein Problem.
Ich würde gerne bei den Buttons ohne ID arbeiten, jedoch müsste ich dafür intern der Funktion eine Variable speichern können (mp = ob auf dem Button bereits der erste Teil des Klicks stattgefunden hat).
Mir ist jedoch keine Möglichkeit bekannt, bei einer Funktion die bei jedem Schleifen-Aufruf neu initialisiert wird, mit der man eine Variable länger als diesen einen Schleifendurchlauf speichern könnte.

Weiß da vielleicht jemand was?

Ansonsten bin ich offen für Verbesserungsvorschläge meiner Button-Funktion Wink

Mfg - Shyiox

BladeRunner

Moderator

BeitragFr, Dez 07, 2012 15:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Klingt nach einem Fall für Types, Du willst ja quasi Objekte erschaffen. Du machst Dir 'nen Type Button mit allen relevanten Variablen darin und erstellst dann mit einer Create-Funktion alle benötigten Buttons. Im späteren Programm nutzt Du dann eine Update()- und eine Draw()-Function, die alle erstellten Buttons mittels each durchläuft und die nötigen Prüfungen und das Zeichnen vornimmt.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

Shyiox

BeitragFr, Dez 07, 2012 15:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich denke nicht, dass das so funktionieren wird, da ich ja den "state" Wert aus dem Return der Button-Funktion für if-Abfragen benötige.
Wie soll man denn bei einer if-Abfrage herauskriegen, ob irgend ein Objekt (Button) auf dem Bildschirm dessen ID nichtmal bekannt ist, da man ja hier mit Types arbeitet, gedrückt wurde oder nicht?
Das neue "Objekt" wird bei mir auch direkt durch die if-Abfrage erstellt, dass heißt wenn man zwei if-Abfragen hat die nach dem "State" des Buttons verlangen, sind auch 2 Buttons auf dem Bildschirm.
Ich hoffe du kannst mir so weit folgen.

Tut mir leid, aber ich wüsste echt nicht wie ich das realisieren sollte mit Types, vor allem da ich so gut wie überhaupt nicht damit gearbeitet habe bisher (oder wenn dann unter anderem Namen, und anderer Syntax).

Vielleicht kannst du mir das ja nochmal kurz erläutern - wäre nett Smile

Mfg - Shyiox
 

PhillipK

BeitragFr, Dez 07, 2012 16:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich kann deinem problem leider nicht ganz folgen.
Wenn du das problem darin siehst, das du dann einen Button duplizierst / Neu erschaffst, dann umgeh das problem doch einfach.

Bladerunner hat dich bereits auf die lösung hingewiesen Smile So ganz kann ich BB leider nicht, weshalb ich keinerlei Pseudocode dazupacke, lediglich die idee:

Update:

1) Deine Buttons pappst du in ein Type (breite, höhe, wurde zuletzt gedrückt, ist pink gefärbt, hat einen alten großvater) - sprich alle werte, die du für diesen button benötigst.
2) Kommt es nun zum mausdruck, gehst du mit each den Button-Type durch und überprüfst anhand der koordinaten ob der Button gedrückt wurde (mouseDown). Ist dem so, speicherst du in einem globalen isLastPressed den button.
3) Wird die maus nun losgelassen (isLastPressed <> null & MouseDown(1) = 0), überprüfst du erneut die position der Maus und schaust, ob isLastPRessed immernoch "unter der maus" liegt. Wenn ja -> Do whatever you want! PS: isLastPressed wieder auf null / 0 setzen.

Zum zeichnen:
1) Deine buttons sind immernoch im selben type vorliegend, keinerlei kopien oder duplikate sollte vorhanden sein Razz
2) Willst du zeichnen, schreibe dir zb eine DrawButton(x,y,w,h, isPressed) funktion. Gehe nun jeden Type Button durch und rufe "DrawButton" mit den entsprechenden Button-fields auf. isPressed kannst du ermitteln, wenn isLastPressed existiert und isLastPressed = momentaner button des each-durchlaufs ist. In dem fall kannst zb eine sonderform des zeichnens innerhalb der funktion nutzen (aka leicht eingedrückt, ne schrille grüne farbe, nen ausrufezeichen daneben..)
3) Flip nicht vergessen Razz


So hast du:
Keinerleid ungewünschte kopien.
Saubere und aufgeräumte programmierform
Gute performance
Gute übersicht
Ein Buttontype, was du später evtl noch erweitern kannst (zb einen wert speichern, welche funktion bei einem maus-druck ausgeführt werden soll... keine ahnung, wie man das in BB macht, sorry!)
Einen "sichtbaren" button, der immer mit den selben werten wie die update funktion arbeitet.

Gruß, PhillipK Smile

(ps: Fertigen code bitte posten, dann lern ich noch was *grins*)

BladeRunner

Moderator

BeitragFr, Dez 07, 2012 16:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Deine Methode würde unglaublich viel redundanten Code generieren, Shyiox, denn überleg mal wieviele dieser If-Schachteln du bräuchtest wenn Du ein ganzes Programm mit Buttons versorgst. Noch schlimmer: nehmen wir an Du möchtest das ein Benutzer variablen Input je nach Situation geben kann, dann ändert sich die Anzahl der Buttons dynamisch zur Laufzeit des Programms. Das ist bei deiner Methode quasi nicht zu händeln.

Die Types sind btw. keine Unbekannten, denn Du kannst ihnen intern weiter eine ID zuweisen als auch ihr Objecthandle abfragen. Dieses kann deine Funktion auch als return-Wert nutzen, denn es wird ja immer nur ein Button zur gleichen Zeit gedrückt sein bei einer normalen Mausabfrage.
Selbst wenn es mehrere sein sollten wäre der Type noch im Vorteil, Du kannst ihn zB in ein Antwort-array eintragen.

Arbeite mal die Beispiele zu Types in der OnlineHilfe durch und verrsuch sie zu verstehen. Types sind das mächtigste Instrument was BB an Bord hat.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Xeres

Moderator

BeitragFr, Dez 07, 2012 21:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo auch.
Types sind möglich und sicher langfristig die bessere Wahl, wenn man den Funktionsumfang erweitern möchte, aber auch ein, zwei Funktionen hätten ihren Reiz, wenn es klein und simpel bleiben soll.
Einem Anfänger kann man nur raten, sich gleich mit Types auseinander zu setzen - der Mechanismus ist codetechnisch aber grundsätzlich recht leicht um zu schreiben (wenn man schon etwas geübter ist, jedenfalls).

Aber praktische Tipps für alle Fälle:

Das ist suboptimal:
BlitzBasic: [AUSKLAPPEN]
If mx>x Then
If mx<x+sx Then
If my>y Then
If my<y+sy Then
mo=1
EndIf
EndIf
EndIf
EndIf

Man schreibt solche Blöcke höchstens einmal - und zwar in eine Funktion MouseInRect, MouseOutOfRect - welche Variante halt gefragt ist - und ruft diese dann aus Button aus auf.

Ferner: IDs sind Unfug. Entweder man hat eine Funktion und reagiert auf dessen Rückgabewert - dann weiß man, was gedrückt wurde - oder man man fragt das Objekt (die Version mit Types) ab - dann weiß man auch, wo und in welcher Situation man ist.

Für die Information, ob die Maustaste losgelassen wurde, brauchst du wohl eine eigene Funktion und eine Globale Variable. Das Problem hat aber nichts mit Buttons zu tun.
Alles hübsch in Funktionen gliedern: Teile und Herrsche!
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

PacMani

BeitragFr, Dez 07, 2012 22:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Bitte bitte benutze And
 

Shyiox

BeitragSa, Dez 08, 2012 2:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke erstmal an euch Very Happy

Das mit den Types habe ich jetzt verstanden denke ich mal, und werde es dann auch ausprobieren.

Bei der Lösung mit den Types:
Ich muss aber trotzdem irgendwie definieren wo welcher Button liegt?!
Wie löse ich das dann am geschicktesten? Ein Data Feld am Ende des Programms sieht nämlich ziemlich dumm aus... oder gibt es keine andere Lösung? Shocked

Mfg - Shyiox

Xeres

Moderator

BeitragSa, Dez 08, 2012 11:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn du Types benutzt, kannst du ja das Erstellen von der Abfrage trennen.
Pseudo:
BlitzBasic: [AUSKLAPPEN]
Type TButton
Field x,y,w,h, ...
Field image, hoverImage, ...
End Type

Local StartButton.TButton = CreateButton(64, 128, 12, 12, IMG, IMG2)

[...]

UpdateButtons()

If StartButton.Clicked Then
[...]
EndIf


Rückgabewerte von Funktionen richtig definieren nicht vergessen:
BlitzBasic: [AUSKLAPPEN]
Function CreateButton.TButton(_data)
Local B.TButton = New TButton
B\Data = _data
Return B
End Function
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
  • Zuletzt bearbeitet von Xeres am Sa, Dez 08, 2012 15:00, insgesamt einmal bearbeitet
 

Shyiox

BeitragSa, Dez 08, 2012 14:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich nehme mal an dieses "_data" bedeutet so viel wie, dass er alle Daten übernimmt?
Ich hab in letzter Zeit öfter sowas mit "_irgendwas" gesehen, weiß aber bis jetzt nicht genau wofür das gut ist? Surprised

Mfg - Shyiox

BladeRunner

Moderator

BeitragSa, Dez 08, 2012 14:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Das ist nur eine Namenskonvention - viele Programmierer kennzeichnen mit dem _ eine Variable die in einem Type liegt oder die für eine Zuweisung deklariert wird. Das kannst Du handhaben wie du willst, nur konsistent solltest du dann sein Wink
EDIT: Und um es klar zu machen: das _data ist nur ein Beispiel und bedeutet nicht dass automatisch alle Felder eines Types befüllt werden!
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

Shyiox

BeitragSa, Dez 08, 2012 14:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Denn bei mir macht er aus dem "_data" ein "_Data" (blau) und sagt dann "Expecting Identifier" Shocked
Btw: Die "Clicked" Funktion muss ich auch noch erstellen richtig?
Oder ist das auch ein Type? ._.

Mfg - Shyiox

PS: Sorry das ich so viele Fragen stelle xD

Edit: Ahh ok Smile

Xeres

Moderator

BeitragSa, Dez 08, 2012 15:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Verzeihung, es muss natürlich "B\Data = ..." in BB sein... und ja: der Code oben soll nur ein paar Möglichkeiten darstellen und muss ausgeweitet werden, wenn er laufen soll.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

Shyiox

BeitragSa, Dez 08, 2012 15:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok... ich hab erstmal irgendwas geschrieben und das Programm gibt zumindest keine Fehler zurück Confused
Aber ich wette ich habe 1000 Fehler gemacht - leider habe ich keine Ahnung wo Sad

Die ganzen Funktionen:
BlitzBasic: [AUSKLAPPEN]
Type TButton
Field x,y,w,h
Field t$
Field hover,clicked
End Type

Function MouseInRect(x,y,x2,y2)
If mx>x And mx<x+sx And my>y And my<y+sy Then
state=1
Else
state=0
EndIf
Return state
End Function

Function Click()
If mh Then
state=1
ElseIf md Then
state=2
Else
state=0
EndIf
Return state
End Function

Function CreateButton.TButton(x,y,w,h,t$)
Local B.TButton = New TButton
B\x = x
B\y = y
B\w = w
B\h = h
B\t$ = t$
Return B
End Function

Function UpdateButtons()
For B.TButton = Each TButton
If MouseInRect(B\x,B\y,B\x+B\w,B\y+B\h)
B\hover = 1
If Click() Then
B\clicked = 1
Else
B\clicked = 0
EndIf
Else
B\hover = 0
EndIf
Next
End Function

Function DrawButtons()
For B.TButton = Each TButton
Local c = 128+(64*B\hover)-(192*B\clicked)
Color c,c,c
Rect B\x,B\y,B\w,B\h
Next
End Function


Im Hauptprogramm:
BlitzBasic: [AUSKLAPPEN]
Graphics 640,480,32,2
AppTitle "Buttontest"
SetBuffer BackBuffer()

Global mh
Global md
Include "bin\button2.bb"
fps = CreateTimer(60)

While Not KeyHit(1)
Cls

mh=MouseHit(1)
md=MouseDown(1)

; Button-Erstellung
Local StartButton.TButton = CreateButton(12,12,64,128,"Button")

; Button-Abfrage
If StartButton\clicked And muuh=0 Then
muuh=1
ElseIf StartButton\clicked And muuh=1 Then
muuh=0
EndIf

; Debug-Anzeige wenn muuh=1
If muuh Then
Color 255,255,255
Rect 608,448,32,32
EndIf

WaitTimer fps
Flip(1)
Wend
End


Sorry, ist erstmal ne ganze Menge... aber ich werde durch die ganzen kurzen Onlinehilfen zu Types nicht wirklich schlauer hab ich das Gefühl Crying or Very sad

Hoffe ihr könnt mir sagen wo hier mein (vermutlich ständiger) Denkfehler liegt.

Mfg - Shyiox

Xeres

Moderator

BeitragSa, Dez 08, 2012 19:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Als kleine Änderung würde ich anmerken, dass man Return gleich verwenden kann, also:
BlitzBasic: [AUSKLAPPEN]
Function MouseInRect(x,y,x2,y2)
If mx>x And mx<x+sx And my>y And my<y+sy Then
Return True
Else
Return False
EndIf
End Function
Zusätzliche Variablen braucht man nicht, und Konstanten schaffen immer bessere Übersicht.

Was du natürlich gar nie machen darfst ist
BlitzBasic: [AUSKLAPPEN]
Local StartButton.TButton = CreateButton(12,12,64,128,"Button")
in der Hauptschleife aus zu führen! Damit erzeugst du jeden Schleifendruchlauf einen neuen Button bis dir der Speicher ausgeht.

Außerdem: Timer immer in Verbindung mit Flip(0) Arrow Hurra, 100 % Auslastung

Ansonsten sieht's doch aber gut aus. Wink
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group