BPS #13: Drag & Drop - Auswertung

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

Xeres

Moderator

Betreff: BPS #13: Drag & Drop - Auswertung

BeitragSo, Okt 16, 2011 16:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Eine Drag & Drop Funktion macht die Steuerung für viele Nutzer einfacher und/oder bequemer - wer konnte sie umsetzen?

Das war die Aufgabe

Postet hier eure Ergebnisse, Codes, Gedanken. Lernt von den anderen, seht euch deren Quelltext an und versucht euren eigenen zu verbessern.

Diskussion
Postet zu euren Codes stets eine kurze Erklärung mit euren Gedanken in denen ihr simpel gesagt die Frage "Wieso habe ich XY auf diese Art gelöst?" beantwortet. Beiträge, die nur den Code enthalten werden wir aus dem Thread entfernen.

Nächste Aufgabe
In zwei Wochen, wird die Musterlösung nach editiert und die nächste Aufgabe eingestellt.

Viel Spaß & viel Erfolg!

Musterlösung:
BlitzBasic: [AUSKLAPPEN]
; BPS: Holzchopf - Drag & Drop

; Fenster initialisieren
Graphics 800,600,0,2
SetBuffer BackBuffer()
Global timer = CreateTimer(50)
SeedRnd MilliSecs()

; Deklarationen, hier alles vom Objekt
Local posX = Rand(0,19) ; x-Position im Raster
Local posY = Rand(0,14) ; y-Position im Raster
Local offX, offY ; relative Mausposition
Local drag = False ; ob das Objekt gezogen wird

; einfache Hauptschleife
While Not KeyHit(1)
; Eingaben zwischenspeichern
Local mx = MouseX()
Local my = MouseY()
Local mhit = MouseHit(1), mdown = MouseDown(1)

; Raster zeichnen
Color 128,128,128
Local ix, iy
For iy = 0 To 14
For ix = 0 To 19
Rect ix*40,iy*40, 40,40, False
Next
Next

; festes Objekt
If Not drag
Color 240,240,240
Rect posX*40,posY*40, 40,40, True
; Objekt packen
If mhit
If mx=>posX*40 And mx<posX*40+40 And my=>posY*40 And my<posY*40+40
drag = True
; die Mausposition auf dem Objekt wird gespeichert (offset)
; das erlaubt, dass man das Objekt quasi irgendwo packen kann
; und es sich nicht "unter der Maus" bewegt
offX = mx -posX*40
offY = my -posY*40
EndIf
EndIf
; gepacktes Objekt
Else
Color 255,255,255
Rect mx-offX, my-offY, 40,40, True
; Objekt loslassen
If Not mdown
drag = False
; tileposition berechnen (wird gerundet)
posX = (mx-offX)/40.0
posY = (my-offY)/40.0
; ungünstige Rundungsfälle korrigieren
If posX<0 Then posX=0
If posX>19 Then posX=19
If posY<0 Then posY=0
If posY>14 Then posY=14
EndIf
EndIf

; Double-Buffering
Flip 0
Cls
; FPS-Begrenzung
WaitTimer(timer)
Wend

End
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 So, Okt 30, 2011 15:19, insgesamt 2-mal bearbeitet

SpionAtom

BeitragMo, Okt 17, 2011 1:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Um Drag&Drop zu ermöglichen muss man vor allem den Mausstatus kontrollieren: Wo befindet sich der Cursor? Wo befindet er sich beim Dragstart? Ist die Maus zur Zeit gedrückt?
Ebenso muss man das zu draggende Objekt im Auge behalten (was aber recht einfach ist, wenn es nur ein Objekt gibt).

Weiterhin muss man sich merken, ob man gerade zu draggen anfängt, oder ob man im Dragvorgang ist. Dies kontrolliere ich mit der Variable dragStarted

Um das Objekt am Raster einzurasten nutze ich etwas Integerdivision (der Rest wird immer abgeschnitten)
Code: [AUSKLAPPEN]
         objekt_x = (objekt_x + fg / 2) / fg * fg ;Objekt an Raster ausrichten
         objekt_y = (objekt_y + fg / 2) / fg * fg


BlitzBasic: [AUSKLAPPEN]
;Grundeinstellungen mit Auflösung und Rastergröße
Const xr = 800, yr = 600, fg = 40
Graphics xr, yr, 0, 2
AppTitle("BPS #13 - SpionAtom")

;Raster erstellen
rasterBild = CreateImage(xr, yr)
SetBuffer ImageBuffer(rasterBild)
Color 200, 200, 200
For x = fg To xr - fg Step fg
Rect x, 0, 1, yr
Next
For y = fg To yr - fg Step fg
Rect 0, y, xr, 1
Next

;Objektbilder erstellen
objektBild_1 = CreateImage(fg, fg)
SetBuffer ImageBuffer(objektBild_1)
For i = fg / 1.6 To 4 Step - 1
Color 200 - 6 * i, 200 - 6 * i, 0
Oval fg / 2 - i, fg / 2 - i, 2 * i, 2 * i
Next
objektBild_2 = CreateImage(fg, fg)
SetBuffer ImageBuffer(objektBild_2)
For i = fg / 1.6 To 4 Step - 1
Color 255 - 5 * i, 255 - 5 * i, 63
Oval fg / 2 - i, fg / 2 - i, 2 * i, 2 * i
Next

;Variablen für Drag&Drop
Local mouse_x, mouse_y, mousedown_1 ;Mouse-Variablen
Local objekt_x, objekt_y ;Position des Objekts
Local oldObjekt_x, oldObjekt_y ;Position beim Drag-Start
Local oldMouse_x, oldMouse_y
Local dragStarted = False ;Status des Dragvorgangs

;Hauptschleife
SetBuffer BackBuffer()
Repeat
;Mouse-Variablen aktualisieren
mouse_x = MouseX()
mouse_y = MouseY()
mousedown_1 = MouseDown(1)
mousehit_1 = MouseHit(1)

;*** Drag&Drop-Magic ***
If mousedown_1 Then
If dragStarted Then
objekt_x = oldObjekt_x - oldMouse_x + mouse_x
objekt_y = oldObjekt_y - oldMouse_y + mouse_y
Else If mousehit_1 And mouse_x >= objekt_x And mouse_y >= objekt_y And mouse_x < objekt_x + ImageWidth(objektBild_1) And mouse_y < objekt_y + ImageHeight(objektBild_1) Then
dragStarted = True
oldObjekt_x = objekt_x
oldObjekt_y = objekt_y
oldMouse_x = mouse_x
oldMouse_y = mouse_y
End If
Else
dragStarted = False
objekt_x = (objekt_x + fg / 2) / fg * fg ;Objekt an Raster ausrichten
objekt_y = (objekt_y + fg / 2) / fg * fg
End If

;Alles zeichnen
Cls
DrawBlock rasterBild, 0, 0
If dragStarted Then objektBild = objektBild_2 Else objektBild = objektBild_1
DrawImage objektBild, objekt_x, objekt_y
Flip(0)

Until KeyDown(1)
End

Edit: Danke Holzchopf, habs verbessert!


Will man mehrere Objekte draggen, könnte man zb Types verwenden: Beispiel
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080
  • Zuletzt bearbeitet von SpionAtom am Mo, Okt 17, 2011 13:32, insgesamt einmal bearbeitet

Holzchopf

Meisterpacker

BeitragMo, Okt 17, 2011 8:23
Antworten mit Zitat
Benutzer-Profile anzeigen
In der Zeile BlitzBasic: [AUSKLAPPEN]
Else If mouse_x >= objekt_x And mouse_y >= objekt_y And mouse_y < objekt_x + ImageWidth(objektBild_1) And mouse_y < objekt_y + ImageHeight(objektBild_1) Then
ist ein Fehler: du vergleichst Maus-Y-Koordinate mit Objekt-X-Koordinate =/

Ausserdem beginnt der Drag auch schon, wenn man die Maustaste ausserhalb des Objekts drückt und dann mit der Maus übers Objekt fährt. Um das zu verhindern müsste die Abfrage so lauten BlitzBasic: [AUSKLAPPEN]
Else If MouseHit(1) And mouse_x >= objekt_x And mouse_y >= objekt_y And mouse_x < objekt_x + ImageWidth(objektBild_1) And mouse_y < objekt_y + ImageHeight(objektBild_1) Then


Und danke für die (etwas ältere) typisierte Variante!

mfG
Holzchopf
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

hazumu-kun

BeitragMi, Okt 19, 2011 19:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habs wieder mit mehr als einem Objekt und Types gelößt Very Happy

BlitzBasic: [AUSKLAPPEN]
; ###### BPS #13 - Drag'n'Drop
; ### Autor: Viken Emesh aka Hazumu-kun
; ######

; #### Konstanten
Const FPS= 24
; ****

; #### Typen
Type Tile
Field fx ;Feldindex in x-Richtung
Field fy
Field drag ;Flag ob dieses Tile das gedraggte ist
End Type
; ****

; #### Variablen
Global draglock ;Sperrt neuen Dragvorgang wenn noch gedraggt wird
Global ctile.Tile
Global tim_fps

Global mx, my, md ;Mausstatus
; ****

; #### Initialisieren
AppTitle "Drag'n'Drop"
Graphics 800,600,0,2
SetBuffer BackBuffer()

tim_fps= CreateTimer (FPS)

; ## Ein paar Objekte erstellen
ctile= New Tile
ctile\fx= 5
ctile\fy= 5

ctile= New Tile
ctile\fx= 10
ctile\fy= 2

ctile= New Tile
ctile\fx= 1
ctile\fy= 3


ctile= New Tile
ctile\fx= 2
ctile\fy= 2
; ****

; #### Mainloop
Local tmpx,tmpy ;Zwischenspeicher für die Drop-Berechnungen
While Not KeyHit(1)
mx= MouseX():my=MouseY():md=MouseDown(1)

Color 50,175,0
Drawgrid()
Color 150,160,250
DrawTiles()

For ctile= Each Tile

If md Then
If Not draglock Then
;Wenn die Maustaste gedrückt ist und aktuell kein Dragvorgang stattfindet
;Dann Mauskollision mit aktuellem Tile prüfen
If (mx>ctile\fx*40+1) And (mx<ctile\fx*40+40) And (my>ctile\fy*40+1) And (my<ctile\fy*40+40) Then
ctile\drag= 1
draglock= 1
EndIf
EndIf

ElseIf ctile\drag
;Ansonsten Tile loslassen
tmpx= Floor(mx/40.)
tmpy= Floor(my/40.)
If tmpx>19 Then tmpx=19 ElseIf tmpx<0 Then tmpx=0
If tmpy>14 Then tmpy=14 ElseIf tmpy<0 Then tmpy=0

ctile\fx= tmpx
ctile\fy= tmpy
ctile\drag= 0
draglock=0
EndIf
Next

Flip 0
WaitTimer (tim_fps)
Cls
Wend
; ****

; #### Funktionen
Function Drawgrid()
;Gitternetz einzeichnen, 40px Quadrate
Local i
For i= 0 To 760 Step 40
Line i,0,i,600
Next
Line 799,0,799,600

For i= 0 To 560 Step 40
Line 0,i,800,i
Next
Line 0,599,800,599
End Function

Function DrawTiles()
;Alle Tiles einzeichnen
Local xt,yt,t.Tile

For t= Each Tile
If t\drag Then
;Gedraggtes Tile an Mausposition zeichnen
xt=mx
yt=my
Else
xt=t\fx*40+1
yt=t\fy*40+1
EndIf
Rect xt,yt,39,39,1
Next
End Function
; ****


Die Kommentare dürften es ziemlich gut erklären.
Die for each Schleife in der Mainloop könnte man bestimmt noch schwer optimieren!
Warum kann es keine omnipotente Macht geben?
Weil diese omnipotente Macht in der Lage sein müsste, einen so schweren Stein zu schaffen, dass sie ihn nicht heben kann
-> nicht omnipotent

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group