brainlag: abpralllwinkel?



  • Ich hab mit dein code nicht genau angesehen, und ich hab meine idee auch noch nicht ausprobiert, sie ist rein theoretisch:

    Man könnte ja mal testen, ob der pixel hinter dem Ball (Abhängig von der Bewegungsrichting) mit der wand kollidiert. Wenn nicht, dann testet man den nächsten pixel im gleichen Abstand zum ball, aber ein bisschen weiter nach vorne rotiert. Das mach man so lange, bis ein Pixel getroffen wurde. Jetzt das ganze von hinten noch einmal, aber in die andere richtung. Mit diesen zwei punkten kann man nun ein steigungsdreieck bilden, an dem der Ball dann abprallen kann. Wie genau du das in SDL unsetzt ist dir überlassen.

    Man sollte bei dem lösungsansatz dabei drauf achten, das der Radus, in dem man die Pixelkollisionen testet nicht zu klein (unpräzise/eventuell keine oder nur eine kollision) und nicht zu groß (unberührte Kannten werden and kollisionspunkt genutzt/fehlerhaft) wird. Jetzt könnte man denke, dass das ganze recht langsahm laufen würde, aber ich denke nicht, da dieses ganze debakel ja nur dann ausgeführt werden soll, wenn eine kollision festgestellt wurde.



  • ich versteh deinen lösungsansatz nicht so ganz 😕
    aber da ich so kurz vor der lösung meines problems bin, würde ichs ganz gerne so machen wie hier geschrieben, nur funktioniert es momentan halt noch nicht ganz 😞 der ball springt manchmal genauso wie man es erwarten würde, meistens aber anders



  • naja, mein lösungsansatz kannst du dir wie folgt vorstellen, sobald sich der Ball und die Pixel berühren, ziehst du mit nem Zierkel einen Kreis um den ball, nimmst dir die beiden schnittpunkte und Ziehst eine gerade da durch. Jetzt musst du nurnoch die Kollision an einer geraden berechnen (Kollision ist bereits sichrergestellt, aber die richtung noch nicht). Das war jetzt so eine zettelerkärung, aber ich finde an der vorherigen kann man leichter ein weg der implementierung erkennen.

    Manchmal hilft auch ein neuanfang, mit frischen Ideen (den Quellcode dann hinzuschreiben sollte dann ganz schnell gehen).



  • Krux schrieb:

    naja, mein lösungsansatz kannst du dir wie folgt vorstellen, sobald sich der Ball und die Pixel berühren, ziehst du mit nem Zierkel einen Kreis um den ball, nimmst dir die beiden schnittpunkte und Ziehst eine gerade da durch. Jetzt musst du nurnoch die Kollision an einer geraden berechnen (Kollision ist bereits sichrergestellt, aber die richtung noch nicht). Das war jetzt so eine zettelerkärung, aber ich finde an der vorherigen kann man leichter ein weg der implementierung erkennen.

    Manchmal hilft auch ein neuanfang, mit frischen Ideen (den Quellcode dann hinzuschreiben sollte dann ganz schnell gehen).

    achso ich verstehe. wie kann ich denn den kreis in einer richtung ablaufen? xD und viel wichtiger, wo soll ich anfangen ?



  • hmm kann mir keiner weiterhelfen? ich hab versucht über 360/ umfang in schritten die kreishülle abzulaufen, habe da aber böse rundungsfehler, und ich weis immernoch nicht an welcher stelle ich anfangen soll 😞

    edit: so ich fange jetzt auf der "rückseite" zum bewegungsvektor an zu suchen:

    //Ballkram
    		ball = addVek(ball, gravity);
    		double cx = 0;
    		double cy = 0;
    		int toGo = ball.len;
    		int hit;
    		double d;
    		DblPoint spiegelv;
    		DblPoint newDir;
    		int dbgbreak = 0;
    		while(toGo > 0 && dbgbreak < 100)
    		{
    			dbgbreak++;
    			cx += ball.dir.x;
    			cy += ball.dir.y;
    			toGo--;
    			hit = 0;
    			spiegelv.x = 0;
    			spiegelv.y = 0;
    			double umfang;
    			double cAngle;
    			double step;
    			bool rhit = false;
    			bool hit = false;
    			for(i = ballRadius*-1; i <= ballRadius && !hit; i++)
    			{
    				for(int j = ballRadius*-1; j <= ballRadius && !hit; j++)
    				{
    					d = sqrt(i*i+j*j);
    					if(d < ballRadius)
    					{
    						if(cMap.collisionMap[(int)ball.pos.x+(int)cx+i][(int)ball.pos.y+(int)cy+j])
    						{
    							hit = true;
    							umfang = (ballRadius-1)*2*PI;
    							step = 360/umfang;
    
    							int breaker = 0;
    							for(cAngle = 180+atan2(ball.dir.x*-1, ball.dir.y*-1)*(360/PI); rhit == false && breaker < umfang; cAngle += step)
    							{
    								double xd = cos((PI/180)*(cAngle-180));
    								double yd = sin((PI/180)*(cAngle-180));
    								/*
    								if(cMap.collisionMap[(int)ball.pos.x+(int)cx+][(int)ball.pos.y+(int)cy+j]
    								double x = j;
    								double y = i*-1;
    								x = x/ballRadius;
    								y = y/ballRadius;
    								spiegelv.x += x;
    								spiegelv.y += y;
    
    							//	ball.len *= 0.98;
    								hit++;
    								*/
    								int xdir = ballRadius+(ballRadius)*xd;
    								int ydir = ballRadius+(ballRadius)*yd;
    								if(cMap.collisionMap[(int)ball.pos.x+(int)cx+xdir][(int)ball.pos.y+(int)cy+ydir])
    								{
    									rhit = true;
    									spiegelv.x += xdir;
    									spiegelv.y += ydir;
    								}
    								breaker++;
    
    							}
    							breaker = 0;
    							rhit = false;
    							for(cAngle = 360-(180+atan2(ball.dir.x*-1, ball.dir.y*-1)*(360/PI)); rhit == false && breaker < umfang; cAngle -= step)
    							{
    								hit = true;
    								double xd = cos((PI/180)*(cAngle-180));
    								double yd = sin((PI/180)*(cAngle-180));
    								/*
    								if(cMap.collisionMap[(int)ball.pos.x+(int)cx+][(int)ball.pos.y+(int)cy+j]
    								double x = j;
    								double y = i*-1;
    								x = x/ballRadius;
    								y = y/ballRadius;
    								spiegelv.x += x;
    								spiegelv.y += y;
    
    							//	ball.len *= 0.98;
    								hit++;
    								*/
    								int xdir = ballRadius+(ballRadius)*xd;
    								int ydir = ballRadius+(ballRadius)*yd;
    								if(cMap.collisionMap[(int)ball.pos.x+(int)cx+xdir][(int)ball.pos.y+(int)cy+ydir])
    								{
    									rhit = true;
    									spiegelv.x += xdir;
    									spiegelv.y += ydir;
    
    								}
    								breaker++;
    							}
    						}
    					}
    				}
    			}
    			if(hit)
    			{
    				//MessageBox(0,"","",0);
    				cx -= ball.dir.x*2;
    				cy -= ball.dir.y*2;
    				toGo+=2;
    				spiegelv.x /= 2;
    				spiegelv.y /= 2;
    				double w1 = atan2(spiegelv.y, spiegelv.x*-1);
    
    				double w2 = atan2(ball.dir.x, ball.dir.y);
    				double w = 2*w2-w1;
    
    				newDir.x = sin(w);
    				newDir.y = cos(w);
    				ball.dir = newDir;
    
    			}
    
    		}
    		ball.pos.x += cx;
    		ball.pos.y += cy;
    		tr.x = (ball.pos.x - ballRadius)+viewPos.x;
    		tr.y = (ball.pos.y - ballRadius)+viewPos.y;
    		SDL_BlitSurface(bs, NULL, screen, &tr);
    		SDL_BlitSurface(debug,NULL,screen,NULL);
    

    aber das problem ist, dass in den beiden ganz inneren schleifen relativ häufig KEIN treffer gefunden wird(sprich, ohne breaker wirde die schleife endlos laufen!)
    der ball springt jedenfalls immernoch ziemlich bescheuert rum 😕



  • pixartist schrieb:

    Krux schrieb:

    naja, mein lösungsansatz kannst du dir wie folgt vorstellen, sobald sich der Ball und die Pixel berühren, ziehst du mit nem Zierkel einen Kreis um den ball, nimmst dir die beiden schnittpunkte und Ziehst eine gerade da durch. Jetzt musst du nurnoch die Kollision an einer geraden berechnen (Kollision ist bereits sichrergestellt, aber die richtung noch nicht). Das war jetzt so eine zettelerkärung, aber ich finde an der vorherigen kann man leichter ein weg der implementierung erkennen.

    Manchmal hilft auch ein neuanfang, mit frischen Ideen (den Quellcode dann hinzuschreiben sollte dann ganz schnell gehen).

    achso ich verstehe. wie kann ich denn den kreis in einer richtung ablaufen? xD und viel wichtiger, wo soll ich anfangen ?

    anfangen tut man hinten, also bewigungsvektor *(-1). Der radius des abzutastenden Kreises muss größer als der Radius des Balls sein, sonst trifft man auf zu wenig wand. Wenn es dann doch vorkommen sollte, das kein Stück wand getroffen wurde (nach einem kompletten rundlauf), dann sollte die Abtastrate erhöht werden, spricht mehr Punkte abtasten. Sollten beide Punkte die man gefunden hat die selben sein (kommt vor) muss man so kollision berechnen, als wäre es eine kollision mit einem punkt, da kann man dann kein steigugsdreieck bilden.



  • wie bilde ich denn ein steigungsdreieck ? 😉 und was mache ich damit ?
    ach scheisse, mein code funzt einfach nicht, kannste mir das vielleicht n bissl umschreiben, bzw mir sagen was falsch ist ?



  • pixartist schrieb:

    wie bilde ich denn ein steigungsdreieck ? 😉 und was mache ich damit ?
    ach scheisse, mein code funzt einfach nicht, kannste mir das vielleicht n bissl umschreiben, bzw mir sagen was falsch ist ?

    wie wäre es, wenn begriffe unklar sind, erstmal google und co zu fragen?
    erster treffer unter google.
    http://www.learn-line.nrw.de/angebote/selma/foyer/projekte/koelnproj3/tut/reg_1_3_h.htm
    http://www.realmath.de/Neues/Klasse8/steigung/steigung.html
    übrigens allein an dem link kann man schon erkennen, das das Grundlagen der Mathematik sind, die jeder eigentlich kennen sollte.



  • ich hatte das ja auch in der schule..ist nur leider ewig lange her.
    geh mal auf die strasse und frag n paar leute. ich schätze 1-5% werden dir ein steigungsdreieck erklären können 😉

    könntest du dir vielleicht in meinem code die schleifen angucken, mit dem ich um den kreis laufe und mir sagen, was daran falsch ist? 😞



  • ne, weil ich da so auf den ersten blick nicht so durchblicke, aber ich könnte dir mal ein paar heufige fehlerquellen sagen:

    sin cos vertauscht
    Winkel nicht einheitlich berechnen (manchmal zum Horrizont, machmal zur senkrechten)
    etc.

    versuch das ganze doch so zu debuggen, dass du dir ein bisschen mehr ausgaben machst, z.B, dass du bei einer kollision abhälst, bis zum dast3endruck wartest, und in der Pausierten ansicht die berechneten Kollisionspunkte antzeigst. Ja Winkel und so geschichten auch nicht vergessen. Dann siehst du, wo der fehler ist. Du kannst natürlich auch konventionelle debugger nehmen, aber da kann man dann nur Zahlenwerte kontrollieren, aber dafür geht es schneller (breakpoints in die kollision setzen).



  • Warum macht ihr alle so eine komplizierte Sache daraus? Einfach einen Vektor vom Kollisionspunkt zum Mittelpunkt des Balles bilden, diesen normieren, den aktuellen Translations Vektor auf diesen Vektor projezieren und danach das doppellte des Resultats davon abziehen. Fertig! f'`8k

    Autocogito

    Gruß, TGGC (making great games since 1992)



  • TGGC schrieb:

    Warum macht ihr alle so eine komplizierte Sache daraus? Einfach einen Vektor vom Kollisionspunkt zum Mittelpunkt des Balles bilden, diesen normieren, den aktuellen Translations Vektor auf diesen Vektor projezieren und danach das doppellte des Resultats davon abziehen. Fertig! f'`8k

    Autocogito

    Gruß, TGGC (making great games since 1992)

    danke für die kompetente antwort 🙂 leider hab ich noch nie von "translationsvektoren" gehört 😕 sprich
    "Translations Vektor auf diesen Vektor projezieren" versteh ned so ganz 😉 bei wikipedia bin ich auch nicht fündig geworden, der einzige eintrag der translationsvektor enthält ist "oberflächenchemie" 🙂

    edit: achja, ganz vergessen: wie behandle ich denn dann das problem, dass immer mehrere pixel die wände berüren ?

    edit2: achso translationsvektor = richtungsvektor(meines objektes)? kk dann versuch ich das mal



  • auf meine art, und dann die Mitte nehmen



  • super, habs durch intensives debuggen hinbekommen! (waren einige fehler drin)
    das einzige was mich noch stört ist, das bei einem relativ flachen aufprall zu viel energie der alten bewegungsrichtung verloren geht und in die "abprallrichtung" übergeht (etwa so als wäre der ball aus gummi und hätte einen drall in die entgegengesetzte richtung)

    habt ihr vielleicht ne idee woran das liegen könnte? (falls ihr den quellcode sehen wollt, sagt bescheid)

    vielen dank



  • pixartist schrieb:

    danke für die kompetente antwort 🙂 leider hab ich noch nie von "translationsvektoren" gehört 😕 sprich
    "Translations Vektor auf diesen Vektor projezieren" versteh ned so ganz

    Translation == Verschiebung bzw. Bewegung, Translationsvektor == "Bewegungsvektor", so wie du ihn schon im ersten Post erwaehnst.

    Zur Projektion: http://de.wikipedia.org/wiki/Skalarprodukt#Grundlegende_Eigenschaften f'`8k

    Autocogito

    Gruß, TGGC (making great games since 1992)



  • achso natüüürlich 🙄 😮 projektion...hätte man auch drauf kommen können. aber sry, dass ich NOCHMAL nachfrage, ich hab jetzt die projektionslänge, aber wovon soll ich die abziehen?
    dachte eigentlich ich müsste den normierten vektor vom kollisionspunkt zum mittelpunkt mit der projektionslänge multiplizieren (*2) und dann vom translationsvektor abziehen, das resultiert aber nicht grade im korrekten verhalten 😕

    double tx = ball.dir.x*ball.len; //translationsvektor des balles
    double ty = ball.dir.y*ball.len; //translationsvektor des balles
    double projektion = apv.x*tx + apv.y*ty; //projektion auf den vektor vom kollisionspunkt(apv)
    apv.x *= projektion*2; //is klar (apv ist normiert)
    apv.y *= projektion*2;
    
    tx -= apv.x; //abziehen vom translationsvektor
    ty -= apv.y;
    double tl = sqrt(tx*tx+ty*ty);
    tx /= tl; //normieren
    ty /= tl;
    
    ball.dir.x = tx; //an den ball übergeben
    ball.dir.y = ty;
    

    edit: hm wieso muss ich den ball 2 schritte zurückbewegen damit es funzt ? 😕 dadurch bleibt er nie liegen sondern zittert immer so dumm rum



  • Doch, das resultiert in korrektem Verhalten. Damit wird das Einfalls == Ausfallswinkel Prinzip auf eine Spiegelung ueberfuehrt. Wenn eine Kugel kollidiert, so liegt die Ebene, an der gespiegelt wird, immer tangential an der Stelle, wo sich Kugel und Hinderniss beruehren. Diese Ebene kann daher durch den Vektor Kollisionspunkt->Mittelpunkt beschrieben werden, da dieser eine Normale der Ebene ist. Wenn du dir das mal aufmalst, sollte es recht schnell klar werden.

    Weitere Fehler liegen also wo anders, z.b. ungenaue Kollisionserkennung. f'`8k

    Autocogito

    Gruß, TGGC (making great games since 1992)



  • TGGC schrieb:

    Doch, das resultiert in korrektem Verhalten. Damit wird das Einfalls == Ausfallswinkel Prinzip auf eine Spiegelung ueberfuehrt. Wenn eine Kugel kollidiert, so liegt die Ebene, an der gespiegelt wird, immer tangential an der Stelle, wo sich Kugel und Hinderniss beruehren. Diese Ebene kann daher durch den Vektor Kollisionspunkt->Mittelpunkt beschrieben werden, da dieser eine Normale der Ebene ist. Wenn du dir das mal aufmalst, sollte es recht schnell klar werden.

    Weitere Fehler liegen also wo anders, z.b. ungenaue Kollisionserkennung. f'`8k

    Autocogito

    Gruß, TGGC (making great games since 1992)

    jau danke 🙂 nach gründlichem nachdenken hab ich jetzt auch alles verstanden 😉

    hast du vielleicht ne idee, wie man erkennen kann ob ein ball liegt und ihn dann festhalten kann ? denn dadurch, dass immer die schwerkraft draufgerechnet wird, hüpft der ball immernoch ein kleines bisschen.
    ich hab versucht, zu überprüfen, ob die länge des bewegungsvektors bei einer kollision einen bestimmten wert unterschreitet, das problem dabei ist aber, dass der ball ja auch z.B. beim "nach-oben-springen" eine oberfläche mit sehr geringer geschwindigkeit streifen kann und dann irrtümlicherweise festgehalten wird

    edit: und toll wär auchnoch, wenn du mir nen tipp geben könntest, wie ich die "bounciness" und rutschigkeit eines objektes unabhängig voneinander verändern könnte 🙂

    danke



  • Ruhelagen berechnen ist tatsaechlich nicht so ganz trivial, das kriegen auch die professionellen Physik Engines nie so richtig hin. Aber es wuerde sicher schonmal was bringen, wenn du testest, ob der Kollisionspunkt unten ist.

    Aber was genau soll bounciness und Rutschigkeit sein? Definier das mal. f'`8k

    Gruß, TGGC (making great games since 1992)



  • Hört sich nach nem Elastizitätsfaltor bzw. einem Reibungskoeffizient an. Schau dir mal die Geschichten hier an. Wird dir auf jeden Fall (früher oder später) eine Hilfe sein.

    http://de.wikipedia.org/wiki/Drallsatz
    http://de.wikipedia.org/wiki/Elastischer_Stoss


Anmelden zum Antworten