Maus Blockieren, wenn die Blöcke Kollidieren?

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

 

bruce85

Betreff: Maus Blockieren, wenn die Blöcke Kollidieren?

BeitragSa, Mai 07, 2011 18:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo nochmal,
ich habe folgendes problem und zwar, habe ich 1 Type für die einzelne Blöcke erstellt und in diesem Type habe ich noch ein Array erstellt, die die Daten der einzelne Blöcke beinhaltet wie Frames etc.

BlitzMax: [AUSKLAPPEN]
'Zugriff auf die Frames
Block[z].arrBlock[i,j].Wert
'Zugriff auf die Felder in denen die Blöcke sich befinden
Block[z].arrBlock[i,j].FeldX
Block[z].arrBlock[i,j].FeldY
'Zugriff auf die Positionen in denen die Blöcke sich befinden
Block[z].arrBlock[i,j].XPos
Block[z].arrBlock[i,j].YPos


Somit bewege ich die Blöcke:
BlitzMax: [AUSKLAPPEN]
Block[z].XPos = MX-tmpMausX
Block[z].YPos = MY-tmpMausY


Es funktioniert alles ganz gut, aber wie kann ich die Maus so begrenzen, dass wenn ich einen Block
bewege und die Maus in diese richtung automatisch blockiert, wenn ein Kollision mit einem anderen Block besteht die den Wert > wie 1 hat?
Ich möchte einfach nicht, das man ein Block mit andere Blöcke überlappen kann.

Wie mache ich ambesten die berechnung um dann auch die Maus dementsprechend in diese Richtung, wo
die Kollision sich befindet, blockieren kann?

Ich bedanke mich schonmal im Voraus.

MfG
AMD Athlon(tm) II X2 250, 8 GB DDR, MSI MSI 770-C45, GeForce GTS 250

Xeres

Moderator

BeitragSa, Mai 07, 2011 18:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich kann mir darunter nichts vorstellen, aber: wenn du Blöcke nicht überlappen lassen willst, würde ich nicht den Umweg über die Maus gehen.
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)
 

bruce85

BeitragSa, Mai 07, 2011 18:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich bin dabei ein Puzzle Spiel zu schreiben, daher muss ich das über die Maus regeln.

Ich hab jetzt mal Testweise was versucht, also wenn sich ein Block mit andere überlappt, das dieser dann gelöscht wird:
BlitzMax: [AUSKLAPPEN]
If MouseDown(1) Then
Block[z].XPos = MX-tmpMausX
Block[z].YPos = MY-tmpMausY

For Local y:Int=0 To Block[z].YAnz-1
For Local x:Int=0 To Block[z].XAnz-1
If Block[z].arrBlock[x,y].Wert > 1 Then
For Local z2:Int=0 To BlockAnz-1
If z = z2 Then

Else
For Local y2:Int=0 To Block[z2].YAnz-1
For Local x2:Int=0 To Block[z2].XAnz-1
If Block[z2].arrBlock[x2,y2].Wert > 1 Then
If Block[z].arrBlock[x,y].FeldX = Block[z2].arrBlock[x2,y2].FeldX And Block[z].arrBlock[x,y].FeldY = Block[z2].arrBlock[x2,y2].FeldY Then
Block[z].arrBlock[x,y].Wert = 0
EndIf
EndIf
Next
Next
EndIf
Next
EndIf
Next
Next

If MouseHit(2) And MouseDown(2) Then
Block[z] = turnArray(Block[z].Nr)
EndIf
CheckBlock(Block[z].Nr)
EndIf

Das Funktioniert schonmal, jetzt muss ich nur noch die Maus begrenzen, also das man die Maus dann nicht mehr in diese richtung weiter bewegen kann.

Weiss einer von euch Vielleicht wie ich das ambesten hinbekomme?

MfG
AMD Athlon(tm) II X2 250, 8 GB DDR, MSI MSI 770-C45, GeForce GTS 250

M0rgenstern

BeitragSa, Mai 07, 2011 20:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Also, ich gehe mal davon aus, dass deine Blöcke quadratisch sind.

Erstmal musst du berechnen, wo sich die Maus (relativ zum Block) befindet:
BlitzMax: [AUSKLAPPEN]
If MouseX() < Block.X Then 'Links vom Block
If MouseY()<Block.Y Then 'links unter dem block
ElseIf MouseY()>Block.Y Then 'links über dem Block
ElseIf MouseX() > Block.X Then 'Rechts vom Block
If MouseY()<Block.Y Then 'rechtsunter dem block
ElseIf MouseY()>Block.Y Then 'rechtsüber dem Block
EndIf


Dann berechnest du den Abstand von der Maus und dem Block, also:
BlitzMax: [AUSKLAPPEN]
Function Abstand:Float(x1:Float, y1:Float, x2:Float, y2:Float)
Return Sqr((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
End Function


Wenn der Abstand kleiner ist als die Hälfte eines Blockdurchmessers, so liegt die Maus im Block.
Dann musst du die Maus entsprechend "vor" den Block setzen. Da du ja weißt, wo sich die Maus relativ zum Block befindet, dürfte das kein Problem sein. Musst da einfach die Maus um ein paar Werte in die Richtung weiter verschieben.

Am besten speicherst du die Position der Maus immer in einer Variable. Dann kannst du einfach die alte Position "wiederherstellen".

lg, M0rgenstern
 

bruce85

BeitragSo, Mai 08, 2011 0:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielen Dank.
Ich glaube, ich lass des ambesten so wie es ist.
Ich wollte das eigentlich nur machen, weil wenn ich z.B. Block 2 über Block 1 bewege, dann ist der Block 2 plötzlich hinter Block 1, weil es ja der Reihe nach gezeichnet wird.

Gibt es Vielleicht einen einfachen befehl um z.B. Block 2 an erster stelle zu zeichnen?
Ich habe das schon mit 2 Verschachtelte Schleifen versucht, aber dann Flackern die Blöcke kurz wenn die Blöcke dann wieder neu gezeichnet werden.

Ich habe auch versucht die Type einträge neu zu erstellen, wenn 1 Block angeklickt und verschoben wird, dann habe ich den Block wo angeklickt wurde, als erstes erstellt.
So hat das auch nicht richtig funktioniert.

Danke schonmal.

MfG
AMD Athlon(tm) II X2 250, 8 GB DDR, MSI MSI 770-C45, GeForce GTS 250

M0rgenstern

BeitragSo, Mai 08, 2011 0:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, um deinen momentan gewählten Block über allen anderen zu zeichnen, müsstest du ihn an die letzte Stelle des Arrays verschieben, da er dann als letzter bearbeitet und somit auch gezeichnet wird.
Das könntest du machen mit:

BlitzMax: [AUSKLAPPEN]
Function UpdateBlockArray:Int()
Local TmpBlock:TBlock, iSize:Int
iSize = Blockarray.length-1
TmpBlock = Blockarray[iSize] 'Block, der an letzter Stelle steht zwischenspeichern
For Local i:Int = 0 Until Blockarray.length 'Momentan gewählten Block suchen
If Blockarray[i] = MomentanerBlock Then
Blockarray[iSize] = MomentanerBlock 'Diesen an die letzte Stelle im Array setzen
Blockarray[i] = TmpBlock 'Zwischengespeicherten Block an momentane Stelle setzen
Return 0 'Funktion beenden, da er sonst am Ende die Blöcke wieder tauscht
EndIf
Next
End Function


Hoffe, dass dir das weiter hilft.

Lg, M0rgenstern
 

bruce85

BeitragSo, Mai 08, 2011 2:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke Dir.
Ich hab dein Code bei mir angepasst, das funktioniert, aber die Blöcke flackern dann kurz, wenn diese Funktion aufgerufen wird.

BlitzMax: [AUSKLAPPEN]
Function UpdateBlockArray:Int(MomentanerBlock:Int)
Local TmpBlock:TBlock, iSize:Int
iSize = Block.length-1
TmpBlock = Block[iSize] 'Block, der an letzter Stelle steht zwischenspeichern
For Local i:Int = 0 Until Block.length 'Momentan gewählten Block suchen
If Block[i] = Block[MomentanerBlock] Then
Block[iSize] = Block[MomentanerBlock] 'Diesen an die letzte Stelle im Array setzen
Block[i] = TmpBlock 'Zwischengespeicherten Block an momentane Stelle setzen
Return 0 'Funktion beenden, da er sonst am Ende die Blöcke wieder tauscht
EndIf
Next
End Function


Jetzt muss ich nur noch das Flackern der Blöcke beheben, wenn diese Funktion aufgerufen wird.
Wie könnte man das machen?

MfG
AMD Athlon(tm) II X2 250, 8 GB DDR, MSI MSI 770-C45, GeForce GTS 250

Xeres

Moderator

BeitragSo, Mai 08, 2011 2:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn ich das gerade richtig sehe, ist die (zeitraubende) Schleife nicht nötig. Mit den Indizes sind die Blöcke eindeutig definiert.

BlitzMax: [AUSKLAPPEN]
Function UpdateBlockArray:Int(MomentanerBlock:Int)
Local TmpBlock:TBlock, iSize:Int = Block.length - 1
TmpBlock = Block[iSize] 'Block, der an letzter Stelle steht zwischenspeichern
Block[iSize] = Block[MomentanerBlock] 'Diesen an die letzte Stelle im Array setzen
Block[MomentanerBlock] = TmpBlock 'Zwischengespeicherten Block an momentane Stelle setzen
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)
 

bruce85

BeitragSo, Mai 08, 2011 2:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke Dir.
Hab mich vertan, bekomme bei manchen Blöcke eine Fehlermeldung, also Array größe überschreitet das maximum etc.
Wenn ich z.B. ein Block mit der Größe von 2*2 und Vielleicht danach ein Block mit der Größe von 3*3 anklicke, dann bekomme ich diesen Fehler.

Naja, ich werde mal versuchen, ob ich das irgendwie beheben kann.

Vielen Dank.

Edit: Jetzt denke ich wieso ich eine Fehlermeldung bekomme, Grund:
In der Schleife wo die Blöcke gezeichnet werden, rufe ich ja die Funktion auf, wenn die Maus auf einen der Blöcke geklickt wurde, wenn jetzt z.B. ein Block mit 2*2 ans ende verschoben wird und ein Block mit 3*3 am gemerkte stelle verschoben wird, dann denkt die Schleife irgendwie, das es immer noch die vorherige Feldgröße hat oder so und überschreitet dann die Größe vom Array.
Ich habe einfach eine zusätzliche variable genommen und beim Klicken der Blöcke wird dann diese variable auf 1 gesetzt und am ende der Schleife rufe ich dann diese Funktion auf.
Nun Funktioniert das ganze jetzt und ohne Flackern der Blöcke beim Klicken.

Vielen Dank für die Hilfe.

MfG
AMD Athlon(tm) II X2 250, 8 GB DDR, MSI MSI 770-C45, GeForce GTS 250

M0rgenstern

BeitragSo, Mai 08, 2011 9:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey Xeres, hast Recht.
Ich dachte er hätte einen Zeiger auf die INstanz des momentanen Blocks. Habe nicht gesehen, dass er einfach über einen INteger drauf zugreift. Dann stimmt natürlich deine Methode.

@bruce85:
Du wählst ja, so wie ich das verstanden habe nur einen neuen Block aus, wenn du mit der Maus klickst. Das heißt, dass du die FUnktion zum Tauschen nur ein einziges Mal, nämlich wenn du die Maustaste drückst, aufrufen musst und nicht jedes mal wenn die Blöcke gezeichnet werden. Es ist klar, dass es dann kurz flackert.
Deine Hauptschleife müsste also so aussehen:
BlitzMax: [AUSKLAPPEN]
Repeat
Cls
Local mh:Int = MouseHit(1)
If mh Then
'Neuen BLock wählen
'Funktion zum Tauschen aufrufen
EndIf

'Blocke zeichnen
Flip 0
Until KeyHit(key_escape)


So brauchst du keine zusätzliche Variable zu überprüfen etc.

Lg, M0rgenstern
 

bruce85

BeitragSo, Mai 08, 2011 12:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Hier ist mal ein Teil von meinem Code:
BlitzMax: [AUSKLAPPEN]
Local Klick:Int=0
Local MerkBlockNr:Int=0
For Local z:Int=0 To BlockAnz-1
For Local y:Int=0 To Block[z].YAnz-1
For Local x:Int=0 To Block[z].XAnz-1
'Nur Blöcke Zeichnen die den Wert > 1 haben
If Block[z].arrBlock[x,y].Wert > 1 Then
DrawImage tile01_png,x*36+Block[z].XPos-(x*1)/1,y*36+Block[z].YPos-(y*1)/1,Block[z].arrBlock[x,y].Wert
EndIf

'Maus berechnung für die Blöcke
If MouseX() > x*36+Block[z].XPos-(x*1)/1 And MouseX() < x*36+Block[z].XPos-(x*1)/1+36 Then
If MouseY() > y*36+Block[z].YPos-(y*1)/1 And MouseY() < y*36+Block[z].YPos-(y*1)/1+36 Then
If Block[z].arrBlock[x,y].Wert > 1 Then
If MouseHit(1) And MouseDown(1) Then
MerkBlockNr = z
Klick = 1
EndIf
EndIf
EndIf
EndIf
Next
Next
Next

If Klick = 1 Then
UpdateBlockArray(MerkBlockNr)
EndIf


Damit funktioniert es auch, aber trotzdem vielen Dank.

MfG

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group