Ball versinkt im Stein [gelöst]

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

BigSnake

Betreff: Ball versinkt im Stein [gelöst]

BeitragSo, Apr 11, 2004 17:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Das scheint nur mit Winkeln von einem Vielfachen von 45° zu passieren. Allerdings hab ich noch keine Lösung gefunden, um das zu verhindern. Mit den unten stehenden Werten sieht man das Problem sofort. Vieleicht hat ja jemand einen Ansatz für eine Lösung

Code: [AUSKLAPPEN]

; --- Bibliotheken ------------------------------------------------------

;Include "XX.bb"

; --- Konstanten --------------------------------------------------------

Const MaxBlocks = 200

; --- Typen -------------------------------------------------------------

Type T_Ball
   ; Repräsentiert einen Ball
   ; Die Kollisionsabfrage erfolgt in jedem Frame über jeweils 0.1
   ; Pixel Schritte
   Field X#
   Field Y#
   Field W#
   Field H#
   Field Angle#
   Field Speed#      
End Type

Type T_Block
   ; Repräsentiert einen Spielstein
   ; Kann beliebig positioniert werden und beliebige Ausmaße haben
   Field X
   Field Y
   Field W
   Field H
   Field A            ; Attribut bestimmt das Verhalten bei Berührung
   Field P            ; Stabilitätspunkte > 0 wird dargestellt
End Type

; --- Variablen ---------------------------------------------------------

Global SecX,SecY,SecW,SecH      ; Ausmaße des Spielfeldes
Global Timer               ; 86 FPS, alle Bewegungen sind darauf getimet

Global Ball.T_Ball = New T_Ball
Global Lv

Dim Block.T_Block(MaxBlocks)

For lv = 1 To MaxBlocks Step 1
   Block.T_Block(Lv) = New T_Block
Next

; --- Hauptprogramm -----------------------------------------------------

;XGraphics 800,600,32,2
;XXInitEngine
Graphics 800,600,32,2
SetBuffer BackBuffer()
SeedRnd MilliSecs()
AppTitle "Blitz Ball - (C) 2003 by Lars Roth"

Timer = CreateTimer(86)

SecX = 10
SecY = 10
SecW = 780
SecH = 580

Ball\X = 100
Ball\Y = 100
Ball\W = 20
Ball\H = 20
Ball\Angle = 45
Ball\Speed = 3

Block(1)\P = 1
Block(1)\X = 200
Block(1)\Y = 200
Block(1)\W = 100
Block(1)\H = 100

Repeat
   ; Hintergrund
   Cls
   
   ; Rand
   Color 255,255,255
   Rect SecX,SecY,SecW,SecH,0
   
   ; Blöcke zeichnen
   For lv = 1 To MaxBlocks Step 1
      If Block(lv)\P > 0 Then
         Color 0,155,0
         Rect Block(lv)\X,Block(lv)\Y,Block(lv)\W,Block(lv)\H
      EndIf
   Next
   
   ; Ball
   Color 255,0,0
   Oval Ball\X,Ball\Y,Ball\W,Ball\H
   
   ; Bewegung des Balls
   MoveBall(Ball)
   
   ; Bild anzeigen
   WaitTimer Timer
   ;XUpdateScreen3d
   ;XUpdateScreen2d
   Flip
Until KeyHit(1)

End

; --- Funktionen --------------------------------------------------------

Function MoveBall(B.T_Ball)
   Local St#
   Local LeftPx#,RightPx#,TopPx#,BottomPx#
   
   For St = 0 To B\Speed Step 0.1
      ; Bewegt den Ball in 0.1 Pixel Schritten
      B\X = B\X + 0.1 * Cos(B\Angle)
      B\Y = B\Y + 0.1 * Sin(B\Angle)
      
      ; Kollision mit den Wänden
      If (B\Y < SecY) Then
         ; Kollision mit der oberen Wand
         B\Angle = NewAngle(B\Angle)
      ElseIf ((B\Y + B\H) > (SecY + SecH)) Then
         ; Kollision mit der unteren Wand : Verloren !
         B\Angle = NewAngle(B\Angle)
      ElseIf (B\X < SecX) Then
         ; Kollision mit der linken Wand
         B\Angle = NewAngle(B\Angle)
      ElseIf ((B\X + B\W) > (SecX + SecW)) Then
         ; Kollision mit der rechten Wand
         B\Angle = NewAngle(B\Angle)
      EndIf
      
      ; Kollision mit einem Block
      For lv=1 To MaxBlocks Step 1
         If (Block(lv)\P > 0) Then
            If (B\X >= Block(lv)\x) And (B\X <= (Block(lv)\X + Block(lv)\W)) Then
               If (B\Y >= Block(lv)\Y) And (B\Y <= (Block(lv)\Y + Block(lv)\H)) Then
                  ; Kollision mit dem Block
                  B\Angle = NewAngle(B\Angle)
                  ; Setzt den Ball außerhalb des Blocks
                  ; Dafür muß zuerst einmal festgestellt werden zu welcher Seite
                  ; der Abstand am geringsten ist
                  LeftPx = B\X - Block(lv)\X
                  RightPx = (B\X + B\W) - (Block(lv)\X + Block(lv)\W)
                  TopPx = B\Y - Block(lv)\Y
                  BottomPx = (B\X + B\H) - (Block(lv)\X + Block(lv)\H)
                  
                  ;If (LeftPx = TopPx) Then
                  ;   ; Linke obere Ecke
                  ;   B\X = Block(lv)\X - B\W - 0.1
                  ;   B\Y = Block(lv)\Y - B\H - 0.1
                  ;EndIf
                  
                  If (LeftPx < RightPx) And (LeftPx < TopPx) And (LeftPx < BottomPx) Then
                     ; Links neben den Stein setzen
                     B\X = Block(lv)\X - B\W - 0.1
                  EndIf
                  If (RightPx < LeftPx) And (RightPx < TopPx) And (RightPx < BottomPx) Then
                     ; Rechts neben den Stein setzen
                     B\X = Block(lv)\X + Block(lv)\W + 0.1
                  EndIf
                  If (TopPx < RightPx) And (TopPx < LeftPx) And (TopPx < BottomPx) Then
                     ; Über den Stein setzen
                     B\Y = Block(lv)\Y - B\H - 0.1
                  EndIf
                  If (BottomPx < LeftPx) And (BottomPx < RightPx) And (BottomPx < TopPx) Then
                     ; Unter den Stein setzen
                     B\Y = Block(lv)\Y + Block(lv)\H + 0.1
                  EndIf
               EndIf
            EndIf
         EndIf
      Next
   Next
End Function

Function NewAngle#(OldAngle#)
   If ((OldAngle >= 315) Or (OldAngle < 45)) Then
      ; Berührt Hindernis von links
      If (OldAngle >= 315) Then
         ; Kommt von schräg unten
         Return (180 + 360 - OldAngle)
      Else
         ; Kommt von schräg oben
         Return (180 - OldAngle)
      EndIf
   ElseIf ( ( OldAngle >= 135) And ( OldAngle < 225 ) ) Then
      ; Berührt Hindernis von rechts
      If (OldAngle >= 180) Then
         ; Kommt von schräg unten
         Return (360 - (OldAngle - 180))
      Else
         ; Kommt von schräg oben
         Return (180 - OldAngle)
      EndIf
   ElseIf ( ( OldAngle >= 225) And ( OldAngle <= 315 ) ) Then
      ; Berührt Hindernis von oben
      If (OldAngle > 270) Then
         ; Kommt von schräg links
         Return (90 - (OldAngle - 270))
      Else
         ; Kommt von schräg rechts
         Return (90 + (270 - OldAngle))
      EndIf
   ElseIf ( ( OldAngle >= 45 ) And ( OldAngle <= 135 ) ) Then
      ; Berührt Hindernis von unten
      If (OldAngle >= 90) Then
         ; Kommt von schräg rechts
         Return (270 - (OldAngle - 90))
      Else
         ; Kommt von schräg links
         Return (270 + (90 - OldAngle))
      EndIf      
   EndIf
End Function

  • Zuletzt bearbeitet von BigSnake am Mo, Apr 12, 2004 10:33, insgesamt einmal bearbeitet

Garfield

BeitragSo, Apr 11, 2004 17:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Auf den ersten Blick erscheint es, das Du natürlich immer den Mittelpunkt des Kreises berechnest und darum der Ball immer versinkt.
Man muss sich erstmal in Deine Physik eindenken...... vieleicht komm ich später drauf Rolling Eyes

BigSnake

BeitragSo, Apr 11, 2004 17:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Mhh jo das Problem ist nun gelöst. Ändere ich nun aber den Winkel geht gar nichts mehr Sad

Code: [AUSKLAPPEN]

; --- Bibliotheken ------------------------------------------------------

;Include "XX.bb"

; --- Konstanten --------------------------------------------------------

Const MaxBlocks = 200
Const MaxBalls = 10

; --- Typen -------------------------------------------------------------

Type T_Ball
   ; Repräsentiert einen Ball
   ; Die Kollisionsabfrage erfolgt in jedem Frame über jeweils 0.1
   ; Pixel Schritte
   Field X#
   Field Y#
   Field W#
   Field H#
   Field Angle#
   Field Speed#
   Field Active      
End Type

Type T_Block
   ; Repräsentiert einen Spielstein
   ; Kann beliebig positioniert werden und beliebige Ausmaße haben
   Field X
   Field Y
   Field W
   Field H
   Field A            ; Attribut bestimmt das Verhalten bei Berührung
   Field P            ; Stabilitätspunkte > 0 wird dargestellt
End Type

; --- Variablen ---------------------------------------------------------

Global SecX,SecY,SecW,SecH      ; Ausmaße des Spielfeldes
Global Timer               ; 86 FPS, alle Bewegungen sind darauf getimet

Dim Ball.T_Ball(MaxBalls)
Global Lv

Dim Block.T_Block(MaxBlocks)

For lv = 1 To MaxBlocks Step 1
   Block.T_Block(Lv) = New T_Block
Next

For lv = 1 To MaxBalls Step 1
   Ball.T_Ball(lv) = New T_Ball
Next

; --- Hauptprogramm -----------------------------------------------------

;XGraphics 800,600,32,2
;XXInitEngine
Graphics 800,600,32,2
SetBuffer BackBuffer()
SeedRnd MilliSecs()
AppTitle "Blitz Ball - (C) 2003 by Lars Roth"

Timer = CreateTimer(86)

SecX = 10
SecY = 10
SecW = 780
SecH = 580

Ball(1)\X = 100
Ball(1)\Y = 100
Ball(1)\W = 20
Ball(1)\H = 20
Ball(1)\Angle = 50
Ball(1)\Speed = 3
Ball(1)\Active = True

Block(1)\P = 1
Block(1)\X = 200
Block(1)\Y = 200
Block(1)\W = 100
Block(1)\H = 100
;Block(2)\P = 1
Block(2)\X = 450
Block(2)\Y = 250
Block(2)\W = 50
Block(2)\H = 50
;Block(3)\P = 1
Block(3)\X = 300
Block(3)\Y = 300
Block(3)\W = 30
Block(3)\H = 30
;Block(4)\P = 1
Block(4)\X = 600
Block(4)\Y = 100
Block(4)\W = 50
Block(4)\H = 50
;Block(5)\P = 1
Block(5)\X = 600
Block(5)\Y = 400
Block(5)\W = 100
Block(5)\H = 20
;Block(6)\P = 1
Block(6)\X = 30
Block(6)\Y = 500
Block(6)\W = 60
Block(6)\H = 56

Repeat
   ; Hintergrund
   Cls
   
   ; Rand
   Color 255,255,255
   Rect SecX,SecY,SecW,SecH,0
   
   ; Blöcke zeichnen
   For lv = 1 To MaxBlocks Step 1
      If Block(lv)\P > 0 Then
         Color 0,155,0
         Rect Block(lv)\X,Block(lv)\Y,Block(lv)\W,Block(lv)\H
      EndIf
   Next
   
   ; Ball
   ; Bewegung des Balls
   For BallNr = 1 To MaxBalls Step 1
      If Ball(BallNr)\Active Then
         Color 255,0,0
         Oval Ball(BallNr)\X,Ball(BallNr)\Y,Ball(BallNr)\W,Ball(BallNr)\H
         MoveBall(Ball(BallNr))
      EndIf
   Next
   
   ; Bild anzeigen
   WaitTimer Timer
   ;XUpdateScreen3d
   ;XUpdateScreen2d
   Flip
Until KeyHit(1)

End

; --- Funktionen --------------------------------------------------------

Function MoveBall(B.T_Ball)
   Local St#
   Local LeftPx#,RightPx#,TopPx#,BottomPx#
   
   For St = 0 To B\Speed Step 0.1
      ; Bewegt den Ball in 0.1 Pixel Schritten
      B\X = B\X + 0.1 * Cos(B\Angle)
      B\Y = B\Y + 0.1 * Sin(B\Angle)
      
      ; Kollision mit den Wänden
      If (B\Y < SecY) Then
         ; Kollision mit der oberen Wand
         B\Angle = NewAngle(B\Angle)
      ElseIf ((B\Y + B\H) > (SecY + SecH)) Then
         ; Kollision mit der unteren Wand : Verloren !
         B\Angle = NewAngle(B\Angle)
      ElseIf (B\X < SecX) Then
         ; Kollision mit der linken Wand
         B\Angle = NewAngle(B\Angle)
      ElseIf ((B\X + B\W) > (SecX + SecW)) Then
         ; Kollision mit der rechten Wand
         B\Angle = NewAngle(B\Angle)
      EndIf
      
      ; Kollision mit einem Block
      For lv=1 To MaxBlocks Step 1
         If (Block(lv)\P > 0) Then
            If ((B\X + B\W) >= Block(lv)\x) And (B\X <= (Block(lv)\X + Block(lv)\W)) Then
               If ((B\Y + B\H) >= Block(lv)\Y) And (B\Y <= (Block(lv)\Y + Block(lv)\H)) Then
                  ; Kollision mit dem Block
                  B\Angle = NewAngle(B\Angle)
               EndIf
            EndIf
         EndIf
      Next
   Next
End Function

Function NewAngle#(OldAngle#)
   If ((OldAngle >= 315) Or (OldAngle < 45)) Then
      ; Berührt Hindernis von links
      If (OldAngle >= 315) Then
         ; Kommt von schräg unten
         Return (180 + 360 - OldAngle)
      Else
         ; Kommt von schräg oben
         Return (180 - OldAngle)
      EndIf
   ElseIf ( ( OldAngle >= 135) And ( OldAngle < 225 ) ) Then
      ; Berührt Hindernis von rechts
      If (OldAngle >= 180) Then
         ; Kommt von schräg unten
         Return (360 - (OldAngle - 180))
      Else
         ; Kommt von schräg oben
         Return (180 - OldAngle)
      EndIf
   ElseIf ( ( OldAngle >= 225) And ( OldAngle <= 315 ) ) Then
      ; Berührt Hindernis von oben
      If (OldAngle > 270) Then
         ; Kommt von schräg links
         Return (90 - (OldAngle - 270))
      Else
         ; Kommt von schräg rechts
         Return (90 + (270 - OldAngle))
      EndIf
   ElseIf ( ( OldAngle >= 45 ) And ( OldAngle <= 135 ) ) Then
      ; Berührt Hindernis von unten
      If (OldAngle >= 90) Then
         ; Kommt von schräg rechts
         Return (270 - (OldAngle - 90))
      Else
         ; Kommt von schräg links
         Return (270 + (90 - OldAngle))
      EndIf      
   EndIf
End Function

BigSnake

BeitragSo, Apr 11, 2004 18:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Das ist mein bisheriger Ansatz. Kollision von links und oben funktioniert nun, nur von rechts und unten nicht

Code: [AUSKLAPPEN]

; --- Bibliotheken ------------------------------------------------------

;Include "XX.bb"

; --- Konstanten --------------------------------------------------------

Const MaxBlocks = 200
Const MaxBalls = 10

; --- Typen -------------------------------------------------------------

Type T_Ball
   ; Repräsentiert einen Ball
   ; Die Kollisionsabfrage erfolgt in jedem Frame über jeweils 0.1
   ; Pixel Schritte
   Field X#
   Field Y#
   Field W#
   Field H#
   Field Angle#
   Field Speed#
   Field Active      
End Type

Type T_Block
   ; Repräsentiert einen Spielstein
   ; Kann beliebig positioniert werden und beliebige Ausmaße haben
   Field X
   Field Y
   Field W
   Field H
   Field A            ; Attribut bestimmt das Verhalten bei Berührung
   Field P            ; Stabilitätspunkte > 0 wird dargestellt
End Type

; --- Variablen ---------------------------------------------------------

Global SecX,SecY,SecW,SecH      ; Ausmaße des Spielfeldes
Global Timer               ; 86 FPS, alle Bewegungen sind darauf getimet

Dim Ball.T_Ball(MaxBalls)
Global Lv

Dim Block.T_Block(MaxBlocks)

For lv = 1 To MaxBlocks Step 1
   Block.T_Block(Lv) = New T_Block
Next

For lv = 1 To MaxBalls Step 1
   Ball.T_Ball(lv) = New T_Ball
Next

; --- Hauptprogramm -----------------------------------------------------

;XGraphics 800,600,32,2
;XXInitEngine
Graphics 800,600,32,2
SetBuffer BackBuffer()
SeedRnd MilliSecs()
AppTitle "Blitz Ball - (C) 2003 by Lars Roth"

Timer = CreateTimer(86)

SecX = 10
SecY = 10
SecW = 780
SecH = 580

Ball(1)\X = 100
Ball(1)\Y = 100
Ball(1)\W = 20
Ball(1)\H = 20
Ball(1)\Angle = 300
Ball(1)\Speed = 3
Ball(1)\Active = True

Block(1)\P = 1
Block(1)\X = 200
Block(1)\Y = 200
Block(1)\W = 100
Block(1)\H = 100
;Block(2)\P = 1
Block(2)\X = 450
Block(2)\Y = 250
Block(2)\W = 50
Block(2)\H = 50
;Block(3)\P = 1
Block(3)\X = 300
Block(3)\Y = 300
Block(3)\W = 30
Block(3)\H = 30
;Block(4)\P = 1
Block(4)\X = 600
Block(4)\Y = 100
Block(4)\W = 50
Block(4)\H = 50
;Block(5)\P = 1
Block(5)\X = 600
Block(5)\Y = 400
Block(5)\W = 100
Block(5)\H = 20
;Block(6)\P = 1
Block(6)\X = 30
Block(6)\Y = 500
Block(6)\W = 60
Block(6)\H = 56

Repeat
   ; Hintergrund
   Cls
   
   ; Rand
   Color 255,255,255
   Rect SecX,SecY,SecW,SecH,0
   
   ; Blöcke zeichnen
   For lv = 1 To MaxBlocks Step 1
      If Block(lv)\P > 0 Then
         Color 0,155,0
         Rect Block(lv)\X,Block(lv)\Y,Block(lv)\W,Block(lv)\H
      EndIf
   Next
   
   ; Ball
   ; Bewegung des Balls
   For BallNr = 1 To MaxBalls Step 1
      If Ball(BallNr)\Active Then
         Color 255,0,0
         Oval Ball(BallNr)\X,Ball(BallNr)\Y,Ball(BallNr)\W,Ball(BallNr)\H
         MoveBall(Ball(BallNr))
      EndIf
   Next
   
   If KeyDown(34)
      Ball(1)\Angle = Ball(1)\Angle + 1
   EndIf
   
   ; Bild anzeigen
   WaitTimer Timer
   ;XUpdateScreen3d
   ;XUpdateScreen2d
   Flip
Until KeyHit(1)

End

; --- Funktionen --------------------------------------------------------

Function MoveBall(B.T_Ball)
   Local St#
   Local LeftPx#,RightPx#,TopPx#,BottomPx#,AxisY#,AxisX#
   
   For St = 0 To B\Speed Step 0.1
      ; Bewegt den Ball in 0.1 Pixel Schritten
      B\X = B\X + 0.1 * Cos(B\Angle)
      B\Y = B\Y + 0.1 * Sin(B\Angle)
      
      ; Kollision mit den Wänden
      If (B\Y < SecY) Then
         ; Kollision mit der oberen Wand
         B\Angle = NewAngleTop(B\Angle)
      ElseIf ((B\Y + B\H) > (SecY + SecH)) Then
         ; Kollision mit der unteren Wand : Verloren !
         B\Angle = NewAngleBottom(B\Angle)
      ElseIf (B\X < SecX) Then
         ; Kollision mit der linken Wand
         B\Angle = NewAngleLeft(B\Angle)
      ElseIf ((B\X + B\W) > (SecX + SecW)) Then
         ; Kollision mit der rechten Wand
         B\Angle = NewAngleRight(B\Angle)
      EndIf
      
      ; Kollision mit einem Block
      For lv=1 To MaxBlocks Step 1
         If (Block(lv)\P > 0) Then
            If ((B\X + B\W) >= Block(lv)\x) And (B\X <= (Block(lv)\X + Block(lv)\W)) Then
               If ((B\Y + B\H) >= Block(lv)\Y) And (B\Y <= (Block(lv)\Y + Block(lv)\H)) Then
                  ; Kollision mit dem Block
                  ; Es muß bestimmt werden an welcher Seite der Ball ist
                  ; Dementsprechend kann dann ein neuer Winkel bestimmt werden
                  LeftPx = Block(lv)\X - (B\X + B\W)
                  RightPx = (Block(lv)\X + Block(lv)\W) - (B\X + B\W)
                  TopPx  = Block(lv)\Y - (B\Y + B\H)
                  BottomPx = (Block(lv)\Y + Block(lv)\H) - (B\Y + B\H)
                  
                  ; Vertikal oder Horizontal
                  If (TopPx > BottomPx) Then
                     AxisY = TopPx
                  Else
                     AxisY = BottomPx
                  EndIf
                  
                  If (LeftPx > RightPx) Then
                     AxisX = LeftPx
                  Else
                     AxisX = RightPx
                  EndIf
                  
                  If (AxisX > AxisY) Then
                     ; Horizontale Kollision
                     If (LeftPx > RightPx) Then
                        ; Schlägt von rechts auf
                        B\Angle = NewAngleLeft(B\Angle)
                     Else
                        ; Schlägt von links auf
                        B\Angle = NewAngleRight(B\Angle)
                     EndIf
                  Else
                     ; Vertikale Kollision
                     If (BottomPx > TopPx) Then
                        ; Schlägt auf der oberen Seite auf
                        B\Angle = NewAngleBottom(B\Angle)
                     Else
                        ; Schlägt auf der unteren Seite auf
                        B\Angle = NewAngleTop(B\Angle)
                     EndIf
                  EndIf
                  
                  ;B\Angle = NewAngle(B\Angle)
               EndIf
            EndIf
         EndIf
      Next
   Next
End Function

Function NewAngleTop#(OldAngle#)
   ; Berührt Hindernis von unten
   If (OldAngle >= 180) Then
      ; Kommt von schräg rechts
      Return (270 - (OldAngle - 90))
   Else
      ; Kommt von schräg links
      Return (270 + (90 - OldAngle))
   EndIf      
End Function

Function NewAngleBottom#(OldAngle#)
   ; Berührt Hindernis von oben
   If (OldAngle >= 180) Then
      ; Kommt von schräg links
      Return (90 - (OldAngle - 270))
   Else
      ; Kommt von schräg rechts
      Return (90 + (270 - OldAngle))
   EndIf
End Function

Function NewAngleLeft#(OldAngle#)
   ; Berührt Hindernis von rechts
   If (OldAngle >= 90) Then
      ; Kommt von schräg unten
      Return (360 - (OldAngle - 180))
   Else
      ; Kommt von schräg oben
      Return (180 - OldAngle)
   EndIf
End Function

Function NewAngleRight#(OldAngle#)
   ; Berührt Hindernis von links
   If (OldAngle > 270) Then
      ; Kommt von schräg unten
      Return (180 + 360 - OldAngle)
   Else
      ; Kommt von schräg oben
      Return (180 - OldAngle)
   EndIf
End Function

BigSnake

BeitragSo, Apr 11, 2004 18:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Mit den meisten Winkeln und in den meisten Situationen funktioniert es nun abe manchmal verhält der Ball sich einfach komisch und ich hab keine Ahnung warum *haarerauf* Mit g läßt sich der Winkel verändern, so daß man es selbst ausprobieren kann

Code: [AUSKLAPPEN]

; --- Bibliotheken ------------------------------------------------------

;Include "XX.bb"

; --- Konstanten --------------------------------------------------------

Const MaxBlocks = 200
Const MaxBalls = 10

; --- Typen -------------------------------------------------------------

Type T_Ball
   ; Repräsentiert einen Ball
   ; Die Kollisionsabfrage erfolgt in jedem Frame über jeweils 0.1
   ; Pixel Schritte
   Field X#
   Field Y#
   Field W#
   Field H#
   Field Angle#
   Field Speed#
   Field Active      
End Type

Type T_Block
   ; Repräsentiert einen Spielstein
   ; Kann beliebig positioniert werden und beliebige Ausmaße haben
   Field X
   Field Y
   Field W
   Field H
   Field A            ; Attribut bestimmt das Verhalten bei Berührung
   Field P            ; Stabilitätspunkte > 0 wird dargestellt
End Type

; --- Variablen ---------------------------------------------------------

Global SecX,SecY,SecW,SecH      ; Ausmaße des Spielfeldes
Global Timer               ; 86 FPS, alle Bewegungen sind darauf getimet

Dim Ball.T_Ball(MaxBalls)
Global Lv

Dim Block.T_Block(MaxBlocks)

For lv = 1 To MaxBlocks Step 1
   Block.T_Block(Lv) = New T_Block
Next

For lv = 1 To MaxBalls Step 1
   Ball.T_Ball(lv) = New T_Ball
Next

; --- Hauptprogramm -----------------------------------------------------

;XGraphics 800,600,32,2
;XXInitEngine
Graphics 800,600,32,2
SetBuffer BackBuffer()
SeedRnd MilliSecs()
AppTitle "Blitz Ball - (C) 2003 by Lars Roth"

Timer = CreateTimer(86)

SecX = 10
SecY = 10
SecW = 780
SecH = 580

Ball(1)\X = 250
Ball(1)\Y = 350
Ball(1)\W = 20
Ball(1)\H = 20
Ball(1)\Angle = 270
Ball(1)\Speed = 3
Ball(1)\Active = True

Block(1)\P = 1
Block(1)\X = 200
Block(1)\Y = 200
Block(1)\W = 100
Block(1)\H = 100
Block(2)\P = 1
Block(2)\X = 450
Block(2)\Y = 250
Block(2)\W = 50
Block(2)\H = 50
Block(3)\P = 1
Block(3)\X = 300
Block(3)\Y = 300
Block(3)\W = 30
Block(3)\H = 30
Block(4)\P = 1
Block(4)\X = 600
Block(4)\Y = 100
Block(4)\W = 50
Block(4)\H = 50
Block(5)\P = 1
Block(5)\X = 600
Block(5)\Y = 400
Block(5)\W = 100
Block(5)\H = 20
Block(6)\P = 1
Block(6)\X = 30
Block(6)\Y = 500
Block(6)\W = 60
Block(6)\H = 56

Repeat
   ; Hintergrund
   Cls
   
   ; Rand
   Color 255,255,255
   Rect SecX,SecY,SecW,SecH,0
   
   ; Blöcke zeichnen
   For lv = 1 To MaxBlocks Step 1
      If Block(lv)\P > 0 Then
         Color 0,155,0
         Rect Block(lv)\X,Block(lv)\Y,Block(lv)\W,Block(lv)\H
      EndIf
   Next
   
   ; Ball
   ; Bewegung des Balls
   For BallNr = 1 To MaxBalls Step 1
      If Ball(BallNr)\Active Then
         Color 255,0,0
         Oval Ball(BallNr)\X,Ball(BallNr)\Y,Ball(BallNr)\W,Ball(BallNr)\H
         MoveBall(Ball(BallNr))
      EndIf
   Next
   
   If KeyDown(34)
      Ball(1)\Angle = Ball(1)\Angle + 1
   EndIf
   
   ; Bild anzeigen
   WaitTimer Timer
   ;XUpdateScreen3d
   ;XUpdateScreen2d
   Flip
Until KeyHit(1)

End

; --- Funktionen --------------------------------------------------------

Function MoveBall(B.T_Ball)
   Local St#
   Local LeftPx#,RightPx#,TopPx#,BottomPx#,AxisY#,AxisX#
   
   For St = 0 To B\Speed Step 0.1
      ; Bewegt den Ball in 0.1 Pixel Schritten
      B\X = B\X + 0.1 * Cos(B\Angle)
      B\Y = B\Y + 0.1 * Sin(B\Angle)
      
      ; Kollision mit den Wänden
      If (B\Y < SecY) Then
         ; Kollision mit der oberen Wand
         B\Angle = NewAngleTop(B\Angle)
      ElseIf ((B\Y + B\H) > (SecY + SecH)) Then
         ; Kollision mit der unteren Wand : Verloren !
         B\Angle = NewAngleBottom(B\Angle)
      ElseIf (B\X < SecX) Then
         ; Kollision mit der linken Wand
         B\Angle = NewAngleLeft(B\Angle)
      ElseIf ((B\X + B\W) > (SecX + SecW)) Then
         ; Kollision mit der rechten Wand
         B\Angle = NewAngleRight(B\Angle)
      EndIf
      
      ; Kollision mit einem Block
      For lv=1 To MaxBlocks Step 1
         If (Block(lv)\P > 0) Then
            If ((B\X + B\W) >= Block(lv)\x) And (B\X <= (Block(lv)\X + Block(lv)\W)) Then
               If ((B\Y + B\H) >= Block(lv)\Y) And (B\Y <= (Block(lv)\Y + Block(lv)\H)) Then
                  ; Kollision mit dem Block
                  ; Es muß bestimmt werden an welcher Seite der Ball ist
                  ; Dementsprechend kann dann ein neuer Winkel bestimmt werden
                  LeftPx = Abs((Block(lv)\X - (B\X + B\W)))
                  RightPx = Abs((Block(lv)\X + Block(lv)\W) - (B\X + B\W))
                  TopPx  = Abs((Block(lv)\Y - (B\Y + B\H)))
                  BottomPx = Abs((Block(lv)\Y + Block(lv)\H) - (B\Y + B\H))
                  
                  ; Vertikal oder Horizontal
                  If (TopPx >= BottomPx) Then
                     AxisY = TopPx
                  Else
                     AxisY = BottomPx
                  EndIf
                  
                  If (LeftPx >= RightPx) Then
                     AxisX = LeftPx
                  Else
                     AxisX = RightPx
                  EndIf
                  
                  ; Wird es vertauscht funktioniert es von der jeweiligen
                  ; anderen Seite nicht
                  If (AxisX >= AxisY) Then
                     ; Horizontale Kollision
                     If (LeftPx > RightPx) Then
                        ; Schlägt von rechts auf
                        B\Angle = NewAngleLeft(B\Angle)
                     Else
                        ; Schlägt von links auf
                        B\Angle = NewAngleRight(B\Angle)
                     EndIf
                  Else
                     ; Vertikale Kollision.
                     If (BottomPx >= TopPx) Then
                        ; Schlägt auf der oberen Seite auf
                        B\Angle = NewAngleBottom(B\Angle)
                     Else
                        ; Schlägt auf der unteren Seite auf
                        B\Angle = NewAngleTop(B\Angle)
                     EndIf
                  EndIf
               EndIf
            EndIf
         EndIf
      Next
   Next
End Function

Function NewAngleTop#(OldAngle#)
   ; Berührt Hindernis von unten
   If (OldAngle >= 180) Then
      ; Kommt von schräg rechts
      Return (270 - (OldAngle - 90))
   Else
      ; Kommt von schräg links
      Return (270 + (90 - OldAngle))
   EndIf      
End Function

Function NewAngleBottom#(OldAngle#)
   ; Berührt Hindernis von oben
   If (OldAngle >= 180) Then
      ; Kommt von schräg links
      Return (90 - (OldAngle - 270))
   Else
      ; Kommt von schräg rechts
      Return (90 + (270 - OldAngle))
   EndIf
End Function

Function NewAngleLeft#(OldAngle#)
   ; Berührt Hindernis von rechts
   If (OldAngle >= 90) Then
      ; Kommt von schräg unten
      Return (360 - (OldAngle - 180))
   Else
      ; Kommt von schräg oben
      Return (180 - OldAngle)
   EndIf
End Function

Function NewAngleRight#(OldAngle#)
   ; Berührt Hindernis von links
   If (OldAngle > 270) Then
      ; Kommt von schräg unten
      Return (180 + 360 - OldAngle)
   Else
      ; Kommt von schräg oben
      Return (180 - OldAngle)
   EndIf
End Function

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group