Abprallen, ich kriegs nicht hin!!!!

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

 

MrJack

Betreff: Abprallen, ich kriegs nicht hin!!!!

BeitragDi, Jul 25, 2006 12:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich versuche schon lange eine Lösung für dieses Problem zu finden,
schaffe es trotz forensuche und google einfach nicht.

Grobe Beschreibung:
Ich habe einen Ball und viele Vektoren die als Wände fungieren.
Die Kollision ist fertig und ich habe den Winkel in der der Vektor zeigt
und den winkel bzw den punkt wo der Ball auf den vektor trifft.

Jetzt möchte ich aber das der Ball ständig von einer kraft nach unten gezogen
wird also auf einer graden fläche hüpft und schließlich liegen bleibt.

Das ganze soll dann als jumpn run gedacht sein.

Ich habe mich bereits mit diversen vektorformeln und beispielen
auseinandergesetzt habe es aber nicht geschaft.

Habe mir das ungefär so vorgestellt:

Code: [AUSKLAPPEN]


While...
 playerx=playerx+hspeed
 playery=playery+vspeed

 collision

Wend

function collision()
 ;prüfe....
 ;vectors\angle ist der winkel des vektors
 ;und hspeed und vspeed die geschwindigkeit des balls in x/y
 ;abprallwinkel berechnen mit der gravity eingeschlossen
 ;hier das problem: wie?
;natürlich muss sich die geschwindigkeit ändern...
;und noch gravity hinzu rechenen... ?
end function


Ich hoffe das ist verständlich gewesen

Rone

BeitragDi, Jul 25, 2006 15:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Moin,

Guck mal Hier...da ist ein code der sowas ähnliches macht. Halt kollision von Kugeln mit Vektoren.... Wink

Hier gibt es ein Tutorial über Linienkollision, von Vertex

jetzt juckt es mich schon wieder in den Fingern...
...werde nachher auch mal sowas probieren, Code poste ich dann hier... Smile

mfg
Rone
 

MrJack

BeitragDi, Jul 25, 2006 20:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Hab ich mir alles schon angekuckt... Das problem ist auch nicht das abprallen an sich also wenn ich nur die vektoren addieren soll,
sondern die einbindung der schwerkraft also ein dritter vektor. dann das
problem das der ball springen soll und irgendwann durch die reibung
auf boden liegt...

trotzdem erstmal thx

Rone

BeitragMi, Jul 26, 2006 0:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,
Hab das jetzt mal ausprobiert.
Gravitation funktioniert Very Happy , hab mir ziemlich einen abgebrochen, obwohl die Loesung eigendlich kinderleicht ist...

Also ich hab feste werte für 'Anziehungskraft' und 'Geschwindigkeitsverlust' bei Kollision.
Code: [AUSKLAPPEN]

Global Gravi:int =981
Global ENERGIEVERLUST:float =0.7
...
Local line:TLine = TLine.AllLinesCollide(x , y, radius)
If Not line Then
   vy:+ (Gravi * time)
Else
   y:- vy * time
   x:- vx * time
      Local dot:Float= vx*line.nx+vy*line.ny   
      vx= (vx-2.0*line.nx*dot)*ENERGIEVERLUST
   vy= (vy - 2.0 * line.ny * dot)*ENERGIEVERLUST
EndIf

Dann einfach den y-Geschw.-vektor immer um delte V verändern. Wobei 'delta V' mit 'v=a*t' berechnet wird. Bin mir nicht sicher ob das Physikalisch richtig/exakt ist( Hatte es erst über die Strecken mit 'S=0.5*a*t^2' probiert,ging aber irgendwie nicht richtig), aber ist auch egal, weil sieht ja 'echt' aus... .
Code: [AUSKLAPPEN]

SuperStrict
Framework brl.basic
Import brl.max2d
Import brl.d3d7max2d
Import brl.retro
Graphics 800,600,16,60
SetBlend ALPHABLEND
Type TLine
   
   Global LineList:TList
   
   Field x1:Float , y1:Float
   Field x2:Float , y2:Float
   Field ux:Float , uy:Float
   Field nx:Float , ny:Float
   
   Method New()
      If Not LineList Then LineList = New TList
      LineList.Addlast Self
   End Method
   
   Method Create:TLine(x1# , y1# , x2# , y2#)
      Self.x1 = x1
      Self.Y1 = y1
      Self.x2 = x2
      Self.y2 = y2
      Local dx#=x2-x1
         Local dy#=y2-y1
       Local d#=Sqr(dx*dx+dy*dy)
       If d#<0.0001
          d#=0.0001
       EndIf
          ux=dx/d
         uy=dy/d 
         nx=uy
         ny=-ux
      Return Self
   End Method
   
   Method Draw()
      DrawLine x1 , y1 , x2 , y2
   EndMethod
   
   Method  LineDistance:Float(x:Float,y:Float)
      Local dx:Float=x2-x1
      Local dy:Float=y2-y1
      Local d:Float=Sqr(dx*dx+dy*dy)
      Local px#=x1-x
      Local py# = y1 - y
      Return Abs((dx*py-px*dy) / d)
   End Method 

   Method LineCollide:Int(x:Float,y:Float,radius:Int)
      Local dx1:Float=x-(x1-ux*radius)
      Local dy1:Float=y-(y1-uy*radius)
      Local d#=Sqr(dx1*dx1+dy1*dy1)
      dx1=dx1/d
      dy1=dy1/d
      Local dx2#=x-(x2+ux*radius)
      Local dy2#=y-(y2+uy*radius)
      d#=Sqr(dx2*dx2+dy2*dy2)
      dx2=dx2/d
      dy2=dy2/d
      Local dot1#=dx1*ux+dy1*uy
      Local  dot2#=dx2*ux+dy2*uy
      Return ((dot1#>=0 And dot2#<=0) Or (dot1#<=0 And dot2#>=0)) And (LineDistance(x,y)<=radius)
   End Method
   
   Function AllLinesCollide:TLine(x:Float,y:Float,radius:Int)
      If LineList Then
         For Local l:TLine = EachIn LineList
            If l.LineCollide:Int(x , y , radius) Then Return l
         Next
      EndIf
      Return Null
   End Function
   
   Function DrawAll()
      If LineList Then
         For Local l:TLine = EachIn LineList
            
            DrawLine l.x1 , l.y1 , l.x2 , l.y2
         Next
      EndIf
   End Function

End Type

Type Ball
   
   Global Gravi:Float = 981
   Global ENERGIEVERLUST:Float = 0.8
   Global ballList:TList
   Global BallAnz:Int
   Global oldtime:Float
   
   Field r:Int,g:Int,b:Int
   Field x:Float
   Field y:Float
   Field radius:Float
   Field vx# , vy#
   Field alter:Float
   
   Method New()
      If Not ballList Then ballList = New Tlist
      ballList.AddLast Self
      BallAnz:+1
   End Method
   
   Method Create:Ball(x:Float , y:Float , radius:Float , r:Int = 255 , g:Int = 255 , b:Int = 255)
      self.r = r
      self.g = g
      Self.b=b
      Self.x = x
      Self.Y = y
      Self.radius = radius
      Return Self
   End Method
   
   Method Berechne(time:Float)
      alter:+ time
      If alter > 10 Then
         Balllist.Remove Self   
         BallAnz:- 1
      EndIf
      Local line:TLine = TLine.AllLinesCollide(x , y, radius)
      If Not line Then
         vy:+ (Gravi * time)
      Else
         y:- vy * oldtime
         x:- vx * oldtime
            Local dot:Float= vx*line.nx+vy*line.ny   
            vx= (vx-2.0*line.nx*dot)*ENERGIEVERLUST
          vy= (vy - 2.0 * line.ny * dot)*ENERGIEVERLUST
      EndIf
      y:+ vy * time
      x:+ vx * time
   End Method
   
   Method Draw()
       Local rh#=radius*2
        DrawOval x-radius,y-radius,rh,rh
   End Method
   
   Function BerechneAll(time:Float)
      If BallList Then
         For Local b:Ball = EachIn BallList
            b.Berechne(time)
         Next
      EndIf
      oldtime=time
   End Function
   
   Function DrawAll()
      If BallList Then
         For Local b:Ball = EachIn BallList
            SetColor b.r,b.g,b.b
            b.Draw()
         Next
      EndIf
   End Function

End Type

Local b:Ball
Local l:TLine = New TLine.Create(100, 100 , 700 , 100)
l:TLine = New TLine.Create(700 , 100 , 700 , 500)
l:TLine = New TLine.Create(100,500,100,100)
l:TLine = New TLine.Create(100 , 500,200,550)
l:TLine = New TLine.Create(200,550,300,500)
l:TLine = New TLine.Create(300 , 500,400,400)
l:TLine = New TLine.Create(400 , 400 , 450 , 400)
l:TLine = New TLine.Create(450,400,600,500)
l:TLine = New TLine.Create(600,500,700,500)

Local timer:Int=MilliSecs()
Local time:Float = 0

While Not KeyHit(KEY_ESCAPE)
   timer = MilliSecs()
   Cls
   If Not Rand(0,10) Then
      If MouseDown(1) Then
         b:Ball = New Ball.Create(MouseX() , MouseY() , Rand(3,10),Rand(0,255),Rand(0,255),Rand(0,255))
         b.vx = Rand(0,100)*2-100
         b.vY=Rand(0,300)*2-400
   
      EndIf
   EndIf 
   Ball.BerechneAll(time)
   Ball.DrawAll()
   SetColor 255,255,255
   TLine.DrawAll()
   Flip 0
   time = ( MilliSecs() - timer ) / 1000.0
Wend
End


Edit: Hab den nochmal editiert, Linienkollision funktioniert jetzt auch ziemlich gut Very Happy
Hier nochmal die exe...

mfg
Rone
  • Zuletzt bearbeitet von Rone am Mi, Jul 26, 2006 21:54, insgesamt 3-mal bearbeitet
 

MrJack

BeitragMi, Jul 26, 2006 8:54
Antworten mit Zitat
Benutzer-Profile anzeigen
ansich nicht schlecht aber in deiner beispiel exe funktioniert nur jeder ca. 10 ball richtig! die anderen kleben sofort an der linie...

dein code hilft mir nicht viel weiter weil dort kein kommentar
etc ist.... wäre nett wenn du das system mal global beschreiben würdest.
dann würde man auch den sinn jeder variable verstehen.

bin auch nicht mit der bmax syntax vertraut...

aber danke das du dir die mühe machst. Very Happy

Aso noch zur linien kollision. ich hab das garnicht ausgerechnet.
ich habe ein monochromes bild jedes vektors erzeugt und das per
imagerectoverlap geprüft wo der ball collidiert.
ist nicht die schnellste variante aber ich brauch nur ein ball
und sie funktioniert perfekt..
Wink

Rone

BeitragMi, Jul 26, 2006 11:39
Antworten mit Zitat
Benutzer-Profile anzeigen
moin,

das ist aber komisch, bei mir ist es genau andersrum, nur jeder 10. klebt sofort an der Linie.. Shocked

Hier ist mal ne etwas bessere Version.


Edit:
Hier nochmal in B2D und nur auf die Gravitation beschränkt: Smile
Code: [AUSKLAPPEN]
Graphics 800,600, 16, 2
SetBuffer BackBuffer()

;Konstante für FallBeschleunigung
Const Gravi=981
;Konstante für Energieverslus bei Kollision in Prozent
Const Energieverlust#=0.8

;Variablen für Ball
Local x#,y#,r#=15,vx#,vy#

;Variablen für Zeitmessung
Local  timer=MilliSecs(),time#,oldtime#

Repeat

   timer = MilliSecs()
   Cls
   If MouseHit(1) Then  x = MouseX() : y = MouseY() :   vy = 0 : vx = 0
   
   ;##############################################################
   If  y + r < 500 Then ;Wenn keine Kollision
      vy = vy + ( Gravi * time );Gravitation anwenden
   Else;Wenn Kollision
      ;Position die Ball vor Kolli hatte wieder herstellen
      y = y + ( vy * oldtime )
      x = x + ( vx * oldtime )
      ;Neue Geschwindigkeitsvektoren erstellen
      speed# = Sqr(vx*vx + vy*vy )
      vx = (  speed * Energieverlust# ) * Sin(0)
      vy = ( -speed * Energieverlust# ) * Cos(0)
   EndIf
   ;Kugel bewegen
   x  = x + ( vx * time )
   y  = y + ( vy * time )

   ;##############################################################
   
   Oval x,y,15,15
   Line 0,500,800,500
   Flip 0
   oldtime = time
   time = (MilliSecs() - timer ) / 1000.0
   
Until KeyHit(1) = 1
End


mfg
Rone
 

MrJack

BeitragMi, Jul 26, 2006 16:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Jo danke... Jetzt hab ichs richtig.
Aber es tut sich schon das nächste für mich unlösbare problem auf.
die Kollision.
Ich habe zwar eine kollision aber wie bei dir geht der ball zunächst
durch den vektor. wird dann zurückgesetzt. das kann weil
ich den ball steuern will zu problemen führen wenn
man direkt an einer wand ist(man fährt langsam durch)

man müsste also die kollision exakter machen.
Ich habe schon versucht den ball pixelweise zurückzusetzen aber das funktionier auch nur wenn der ball direkt auf eine wand prallt.
nicht z.b. an eine kante von zwei wänden "rollt".

vielleicht kann mir auch da wer ne hilfe geben
(will das spiel endlich mal fertig machen) Rolling Eyes

danke leute

Rone

BeitragMi, Jul 26, 2006 18:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Ich habe zwar eine kollision aber wie bei dir geht der ball zunächst
durch den vektor. wird dann zurückgesetzt.

Naja, ist ganz normal das der Ball durch den Vektor geht, wenn du den Ball um mehr als einen pixel pro Durchlauf bewegst... . Wenn du die Position richtig zurückberechnest, sollte es da aber eigendlich kein Problem geben...
Code: [AUSKLAPPEN]
y = y - ( vy * oldtime )
x = x - ( vx * oldtime )

...wobei 'oldtime' die Zeit ist, mit der der Ball im letzten Schleifendurchlauf vor bewegt wurde.
Zitat:
man müsste also die kollision exakter machen.

Wenn du eh nur eine Kugel hast und die Vektoren als Bilder, nimm doch ein Bild für die Kugel und mach das mit ImmagesCollide(ball ist ja kein RECT)...
Im Endeffekt musst du aber sowieso aus den Staart/End - Punkten des vektors die x/y komponenten biden und entweder mit vektorrechnung oder Winkelsätzen+Abfragen den neuen Winkel berechnen, weshalb man auch gleich alles Rechnerisch machen kann...

Ansonsten könnte man das höchstens verhindern, indem man die Bewegung des Balls ein Stück weit vorberechnet: Halt wenn zb. bei t=0.67s eine Kollision ist bei der der Ball durch den Vektor geht, einfach die position für dieses t ensprechend zurückberechen und speichern.... Wenn man zB. den Ballflug immer für eine Skunde vorberechnet, Psoudocode:
Code: [AUSKLAPPEN]
Dim FlugBahn(1001,4)
FlugBahn(0,0)  = x
FlugBahn(0,1)  = y
FlugBahn(0,2)  = vx
FlugBahn(0,3)  = vy

For i=1 To 999
   If  FlugBahn(i-1,1) + r < 500 Then
      ;Gravitation anwenden
      FlugBahn(i,0)  = FlugBahn(i-1,0) + ( vx * 0.001 )
      FlugBahn(i,1)  = FlugBahn(i-1,1) + ( vy * 0.001 )

   Else
      FlugBahn(i,0) = FlugBahn(i,0) - ( vx * 0.001 )
      FlugBahn(i,1) = FlugBahn(i,1) - ( vy * 0.001 )
      ;Neue Geschwindigkeitsvektoren erstellen
      ;...
   EndIf
Next 

Mit ner Que wäre das vieleicht praktischer, halt jeden durchlauf dann hinten ein neuer Punkt rein, vorne der erste raus und immer an FlugBahn(0,0) /FlugBahn(0,1) zeichnen...

Poste doch mal ein bisschen Code, dannn kann man dir auch besser helfen... Wink

mfg
Rone
 

MrJack

BeitragMi, Jul 26, 2006 22:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Jo, verstehe. Ich werde versuchen etwas zu suchen, aber ich denke nicht
das ich das noch vernünftig hinkriege.... trotzdem thx

also kann meines erachtens geclosed werden Sad

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group