Seite 1 von 1

2D Kollisionsproblem

Verfasst: 22.02.2011 15:35
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

Re: 2D Kollisionsproblem

Verfasst: 22.02.2011 15:56
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:

Re: 2D Kollisionsproblem

Verfasst: 22.02.2011 16:17
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

Re: 2D Kollisionsproblem

Verfasst: 22.02.2011 16:21
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

Re: 2D Kollisionsproblem

Verfasst: 22.02.2011 16:30
von deify
cool danke (: das wird mir sicher bei einigen Problemen weiterhelfen (: