2D Kollisionsproblem

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
deify
Beiträge: 141
Registriert: 29.03.2010 22:01
Computerausstattung: Win7 64bit
AMD Phenom II X4 940
NVIDIA GeForce GTS 250
4GB RAM
Kontaktdaten:

2D Kollisionsproblem

Beitrag von deify »

Hey Jungs (:
Ich wollte mich in den letzten Tagen mal etwas in die 2D Programmierung einarbeiten. Habe auch schon eine gute Tutorials bzw Codes gesehen und verstanden. Das Problem bei der Komplexität wird letztendlich ja die Mathematik mit massig Vektorrechnung sein, aber ich denke das könnte klappen.

Jetzt habe ich versucht einen simplen Code zu schreiben, der beliebig viele Objekete (Boxen mit verschiedenen Größen und x- /y-Geschwindigkeiten) in einem Raum verteilt und diese von den Wänden reflektieren lässt. Soweit garkein Problem.
Jetzt wollte ich die Kollision mit einbauen, hierzu hatte ich mir überlegt, dass zwei Vierecke die sich treffen eigentlich nur ihre Richtungsvektoren austauschen und weiterfliegen. (hierbei gehe ich natürlich von gleichen Massen etc. aus)
Leider will der Code garnkeine Kollisionen bearbeiten. DasProblem ist aber nicht die Kollisionsabfrage, sondern mein Code danach, wenn man eine Veränderung der Vektoren entfernt klappt die Kollision(leider nur nicht im richtigen Winkel) Wenn sie senkrecht aufeinander treffen wird die Kollision auch richtig bearbeitet.

Geht es einfacher zu lösen? Bin ich auf dem Holzweg oder könnt ihr einen Fehler im Code finden? (:

Code: Alles auswählen

EnableExplicit

Structure object
  x.i
  y.i
  width.i
  height.i
  xSpeed.i
  ySpeed.i
  spriteID.i
EndStructure

Enumeration
  #window
EndEnumeration

Global exit
Global Dim objects.object(0)

Procedure addObject(x,y,width,heigth,xSpeed,ySpeed,color)
  Protected size = ArraySize(objects())
  
  ReDim objects(size+1)
  With objects(size+1)
    \x = x
    \y = y
    \width = width
    \height = heigth
    \xSpeed = xSpeed
    \ySpeed = ySpeed
    \spriteID = CreateSprite(#PB_Any,width,heigth)
  EndWith
  
  StartDrawing(SpriteOutput(objects(size+1)\spriteID))
  Box(0,0,width,heigth,color)
  StopDrawing()
EndProcedure

Procedure drawSprites()
  Protected i
  For i=1 To ArraySize(objects())
    With objects(i)
      DisplaySprite(\spriteID,\x,\y)
      
      If \x < 0 : \xSpeed = -\xSpeed : EndIf
      If \x > 300-\width : \xSpeed = -\xSpeed : EndIf
      If \y < 0 : \ySpeed = -\ySpeed : EndIf
      If \y > 200-\height : \ySpeed = -\ySpeed : EndIf
      
      \x + \xSpeed
      \y + \ySpeed
    EndWith
  Next
EndProcedure

Procedure checkCollision()
  Protected i, k, xSpeed, ySpeed
  
  For i=1 To ArraySize(objects())
    For k=1 To ArraySize(objects())
      If i <> k
        If SpriteCollision(objects(i)\spriteID,objects(i)\x,objects(i)\y,objects(k)\spriteID,objects(k)\x,objects(k)\y)
          Debug 1
          xSpeed = objects(i)\xSpeed
          ySpeed = objects(i)\ySpeed
          objects(i)\xSpeed = objects(k)\xSpeed
          objects(i)\ySpeed = objects(k)\ySpeed
          objects(k)\xSpeed = xSpeed
          objects(k)\ySpeed = ySpeed
        EndIf
      EndIf
    Next
  Next        
EndProcedure


If Not InitSprite()
  MessageRequester("Error","Can't load DirectX")
  End
EndIf

If Not OpenWindow(#window,0,0,300,200,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  MessageRequester("Error","Can't open window")
  End
Else
  If Not OpenWindowedScreen(WindowID(#window),0,0,300,200,0,0,0)
    MessageRequester("Error","Can't open windowed screen")
  Else
    StartDrawing(ScreenOutput())
    FrontColor(#Black)
    StopDrawing()    
    addObject(0,0,20,20,3,4,#Blue)
    addObject(100,100,20,20,4,3,#Red)
  EndIf  
EndIf

Repeat
  Select WindowEvent()
    Case #PB_Event_CloseWindow
      exit = 1
  EndSelect
  
  ClearScreen(#Black)
  drawSprites()
  checkCollision()
  FlipBuffers()
  
  Delay(1)
Until exit  

mfg deify
Windows 7 | 64bit | PureBasic 4.51 (x64/x86)
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: 2D Kollisionsproblem

Beitrag von STARGÅTE »

Das Problem in deinem Code ist, das du einmal bei i kollidiert mit k und k kollidiert mit i die Vektoren tauschst.
Also tauchst du zweil mal, also garnicht ^^

Code: Alles auswählen

  For i=1 To ArraySize(objects())
  	For k=i+1 To ArraySize(objects())
  		If SpriteCollision(objects(i)\spriteID,objects(i)\x,objects(i)\y,objects(k)\spriteID,objects(k)\x,objects(k)\y)
  			Debug 1
  			Swap objects(i)\xSpeed, objects(k)\xSpeed
  			Swap objects(i)\ySpeed, objects(k)\ySpeed
	  	EndIf
	  Next
  Next        
So ist es besser, und spart zudem eine Abfrage.
Er geht nun zB:
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
durch

EDIT: Mit Swap gehts noch einfacher :allright:
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
deify
Beiträge: 141
Registriert: 29.03.2010 22:01
Computerausstattung: Win7 64bit
AMD Phenom II X4 940
NVIDIA GeForce GTS 250
4GB RAM
Kontaktdaten:

Re: 2D Kollisionsproblem

Beitrag von deify »

danke für die schnelle Antwort (: klappt top so.

Ich bin mir nur nicht sicher wie realistisch das alles ist, noch dazu passiert es ab und zu dass Objekte ineinander bzw in der Wand hängen bleiben... muss man das für jeden Fall fixen?

Gibt es ein gutes Tutorial im Forum für Kollisionen in 2D? Kugeln z.B. haben ja ein anderes Kollisionsverhalten. Ansonsten muss ich mal wieder meine Matheskills auspacken und alles selber herleiten :D was ja unter Umständen länger dauern könnte :D (z.b. Rechtecke die mit Drehung aufeinander stoßen)

Habe schon einen Wrapper hierfür gefunden, wollte aber selber eine kleine "Engine" schreiben, bin mir aber nicht sicher ob ich mit meiner Vorgehensweise auf dem richtigen Weg bin (:

mfg deify
Windows 7 | 64bit | PureBasic 4.51 (x64/x86)
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: 2D Kollisionsproblem

Beitrag von STARGÅTE »

Hier gibt es zB ein Comunity-Projekt, welches ebenfalls eine Physik-Engine schreibt.
Code ist zu 100% einsehbar:
Circle Physic Engine Userlib
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
deify
Beiträge: 141
Registriert: 29.03.2010 22:01
Computerausstattung: Win7 64bit
AMD Phenom II X4 940
NVIDIA GeForce GTS 250
4GB RAM
Kontaktdaten:

Re: 2D Kollisionsproblem

Beitrag von deify »

cool danke (: das wird mir sicher bei einigen Problemen weiterhelfen (:
Windows 7 | 64bit | PureBasic 4.51 (x64/x86)
Antworten