Abprallen, ich kriegs nicht hin!!!!
Übersicht

MrJackBetreff: Abprallen, ich kriegs nicht hin!!!! |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Moin,
Guck mal Hier...da ist ein code der sowas ähnliches macht. Halt kollision von Kugeln mit Vektoren.... ![]() 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... ![]() mfg Rone |
||
MrJack |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo,
Hab das jetzt mal ausprobiert. Gravitation funktioniert ![]() 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 ![]() Hier nochmal die exe... mfg Rone |
||
- Zuletzt bearbeitet von Rone am Mi, Jul 26, 2006 21:54, insgesamt 3-mal bearbeitet
MrJack |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
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. ![]() 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.. ![]() |
||
![]() |
Rone |
![]() Antworten mit Zitat ![]() |
---|---|---|
moin,
das ist aber komisch, bei mir ist es genau andersrum, nur jeder 10. klebt sofort an der Linie.. ![]() Hier ist mal ne etwas bessere Version. Edit: Hier nochmal in B2D und nur auf die Gravitation beschränkt: ![]() 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 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
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) ![]() danke leute |
||
![]() |
Rone |
![]() Antworten mit Zitat ![]() |
---|---|---|
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... ![]() mfg Rone |
||
MrJack |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
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 ![]() |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group