Seitengenaue Kollisionsabfrage

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

hier mal ein beispiel, wie es besser aussieht:

Code: Alles auswählen

Global Ball_X.f       = 10
Global Ball_Y.f       = 10
Global Ball_MoveX.f   = 5
Global Ball_MoveY.f   = 5
Global Ball_Radius.i  = 8

Global Brick_X.i      = 300
Global Brick_Y.i      = 300
Global Brick_Width.i  = 100
Global Brick_Height.i = 50

Enumeration 1
  #Collision_Top
  #Collision_Left
  #Collision_Bottom
  #Collision_Right
EndEnumeration

Procedure.l SectorCollision( x1.l, y1.l, a1.l, b1.l, x2.l, y2.l, a2.l, b2.l )
  Protected dx.l, dy.l
  Protected sx.l, sy.l
  Protected Coll.l = 0
 
  dx = (x1 + a1/2) - (x2 + a2/2)
  If dx < 0
    dx = -dx
    sx = -1
  ElseIf dx > 0
    sx = 1
  EndIf

  dy = (y1 + b1/2) - (y2 + b2/2)
  If dy < 0
    dy = - dy
    sy = -1
  ElseIf dy > 0
    sy = 1
  EndIf
 
  If dx < (a1+a2)/2 And dy < (b1+b2)/2
    If dx < dy
      Coll = 2 + sy
    Else
      Coll = 3 + sx
    EndIf
  EndIf
 
  ProcedureReturn Coll

EndProcedure



InitSprite()
InitKeyboard()
InitMouse()
OpenScreen(1024, 768, 32, "Test")

Repeat
  ExamineKeyboard()
  ExamineMouse()

  Brick_X = MouseX() - Brick_Width / 2
  Brick_Y = MouseY() - Brick_Height / 2

  Ball_X + Ball_MoveX
  Ball_Y + Ball_MoveY
 
  If Ball_X < 0
    Ball_X = 0
    Ball_MoveX = -Ball_MoveX
  ElseIf Ball_X > 1024 - Ball_Radius*2
    Ball_X = 1024 - Ball_Radius*2
    Ball_MoveX = -Ball_MoveX
  EndIf
  If Ball_Y < 0
    Ball_Y = 0
    Ball_MoveY = -Ball_MoveY
  ElseIf Ball_Y > 768 - Ball_Radius*2
    Ball_Y = 768 - Ball_Radius*2
    Ball_MoveY = -Ball_MoveY
  EndIf
 
    Select SectorCollision(Ball_X, Ball_Y, Ball_Radius*2, Ball_Radius*2, Brick_X, Brick_Y, Brick_Width, Brick_Height)
      Case #Collision_Left
        Ball_X = Brick_X - Ball_Radius*2
        Ball_MoveX = -Ball_MoveX
      Case #Collision_Top
        Ball_Y = Brick_Y - Ball_Radius*2
        Ball_MoveY = -Ball_MoveY
      Case #Collision_Right
        Ball_X = Brick_X + Brick_Width
        Ball_MoveX = -Ball_MoveX
      Case #Collision_Bottom
        Ball_Y = Brick_Y + Brick_Height
        Ball_MoveY = -Ball_MoveY
    EndSelect

  ClearScreen( $201008 )
    StartDrawing(ScreenOutput())
      Box(Brick_X, Brick_Y, Brick_Width, Brick_Height, #Red)
      Circle(Ball_X + Ball_Radius, Ball_Y + Ball_Radius, Ball_Radius, #White)
    StopDrawing()
  FlipBuffers()

Until KeyboardPushed(#PB_Key_Escape)
was noch passieren kann, ist dass die Kugel um den Block gleitet,
wenn man provoziert, dass mehrere Frames Hintereinander Kollisionen auftreten.
das ist aber im Grunde korrekt so.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Josef Sniatecki
Beiträge: 657
Registriert: 02.06.2008 21:29
Kontaktdaten:

Beitrag von Josef Sniatecki »

Danke :)

Nun ist es Zeit für mich, an einem Projekt weiter zu arbeiten...
PB 4.61 | Windows Vista - 32Bit
Homepage

"Wahrlich es ist nicht das Wissen, sondern das Lernen, nicht das Besitzen sondern das Erwerben, nicht das Dasein, sondern das Hinkommen, was den grössten Genuss gewährt." - Carl Friedrich Gauß
Antworten