Neue direction richtig berechnen



  • Hey!

    Ein Objekt wird mit atan2(moveSpeedY, moveSpeedX) in seine Bewegungsrichtung gedreht. Dies soll aber nun Schrittweise geschehen.

    Leider komm ich nicht drauf, ob ich nun zum aktuellen Winkel hinzuaddieren oder subtrahieren soll.

    Beispiele:
    http://datakeeper.lima-city.de/winkel.jpg
    (Schwarzer Punkt: Startwinkel, roter Punkt: Endwinkel)

    Im ersten Beispiel ist es leicht:
    Startwinkel ist kleiner als Endwinkel: Inkrementiere Startwinkel bis größergleich Endwinkel

    Im zweiten Beispiel ist es blöd:
    Startwinkel ist größer als Endwinkel, es soll aber trotzdem inkrementiert werden, weil der Weg dann kürzer ist.

    Im dritten Beispiel wieder:
    Startwinkel ist kleiner als Endwinkel, es soll aber dekrementiert werden, da ja so der Weg wieder kürzer ist.

    Ich blicks einfach nicht, wie ich das ausrechnen soll. Habe die Variablen:

    objectDirection
    newObjectDirection

    Wie könnte der Algorithmus aussehen 🙄
    Ich weiß, nicht 3 sondern PI.
    Weiters soll, wenn die direction größer als PI ist, -PI sein und wenn kleiner als PI, +PI sein aber das ist sowieso klar.

    Danke!
    MfG



  • Hab das jetzt so gemacht 😮 😮

    if(newMove)
    	{
    		newMove = false;
    
    		GetCursorPos(&mouse);
    
    		playerMoveX = (float)mouse.x - HALF_SCREEN_WIDTH;
    		playerMoveY = (float)mouse.y - HALF_SCREEN_HEIGHT;
    
    		if(playerMoveX < 10 && playerMoveX > -10 && playerMoveY < 10 && playerMoveY > -10)
    			moving = false;
    		else
    		{
    			moving = true;
    			turning = true;
    		}
    
    		newPlayerPosX = playerPosX + playerMoveX;
    		newPlayerPosY = playerPosY + playerMoveY;
    
    		playerMoveSpeedX = 10.0f * (playerMoveX / sqrt(pow(playerMoveX, 2.0f) + pow(playerMoveY, 2.0f)));
    		playerMoveSpeedY = 10.0f * (playerMoveY / sqrt(pow(playerMoveX, 2.0f) + pow(playerMoveY, 2.0f)));
    
    		newPlayerDirection = atan2(playerMoveY, playerMoveX);
    
    		turnPP = false; // Turn from positive to positive
    		turnNN = false; // Turn from negative to negative
    		turnPN = false; // Turn from positive to negative
    		turnNP = false; // Turn from negative to positive
    		turnCW = false; // Turn clockwise
    
    		if(playerDirection >= 0.0f && newPlayerDirection >= 0.0f)
    		{
    			turnPP = true;
    
    			if(playerDirection < newPlayerDirection)
    				turnCW = true;
    			else
    				turnCW = false;
    		}
    		else if(playerDirection <= 0.0f && newPlayerDirection <= 0.0f)
    		{
    			turnNN = true;
    
    			if(playerDirection < newPlayerDirection)
    				turnCW = true;
    			else
    				turnCW = false;
    		}
    		else
    		{
    			float diff;
    
    			if(playerDirection < 0.0f)
    				diff = -playerDirection + newPlayerDirection;
    			else
    				diff = -newPlayerDirection + playerDirection;
    
    			if(diff >= 3.0f)
    				if(playerDirection > 0.0f)
    				{
    					turnEnd = playerDirection + ((D3DX_PI - playerDirection) + ((D3DX_PI) - (-newPlayerDirection)));
    					turnCW = true;
    				}
    				else
    				{
    					turnEnd = playerDirection - ((D3DX_PI - newPlayerDirection) + ((D3DX_PI) - (-playerDirection)));
    					turnCW = false;
    				}
    			else
    				if(playerDirection > 0.0f)
    					turnCW = false;
    				else
    					turnCW = true;
    
    			if(playerDirection < 0.0f)
    				turnNP = true;
    			else
    				turnPN = true;
    		}
    	}
    
    	if(moving)
    	{
    		if(turning)
    		{
    			if(turnPP)
    				if(turnCW)
    					if(playerDirection + playerTurnSpeed < newPlayerDirection)
    						playerDirection += playerTurnSpeed;
    					else
    						turning = false;
    				else
    					if(playerDirection - playerTurnSpeed > newPlayerDirection)
    						playerDirection -= playerTurnSpeed;
    					else
    						turning = false;
    			else if(turnNN)
    				if(turnCW)
    					if(playerDirection + playerTurnSpeed < newPlayerDirection)
    						playerDirection += playerTurnSpeed;
    					else
    						turning = false;
    				else
    					if(playerDirection - playerTurnSpeed > newPlayerDirection)
    						playerDirection -= playerTurnSpeed;
    					else
    						turning = false;
    			else
    				if(turnCW)
    					if(turnNP)
    						if(playerDirection + playerTurnSpeed < newPlayerDirection)
    							playerDirection += playerTurnSpeed;
    						else
    							turning = false;
    					else
    						if(playerDirection + playerTurnSpeed < turnEnd)
    							playerDirection += playerTurnSpeed;
    						else
    						{
    							playerDirection = atan2(playerMoveY, playerMoveX);
    							turning = false;
    						}
    				else
    					if(turnNP)
    						if(playerDirection - playerTurnSpeed > turnEnd)
    							playerDirection -= playerTurnSpeed;
    						else
    						{
    							playerDirection = atan2(playerMoveY, playerMoveX);
    							turning = false;
    						}
    					else
    						if(playerDirection - playerTurnSpeed > newPlayerDirection)
    							playerDirection -= playerTurnSpeed;
    						else
    							turning = false;
    
    			D3DXMatrixTransformation2D(&playerRotation, 0, 0, 0, &playerRotationCenter, playerDirection, 0);
    			playerSprite->SetTransform(&playerRotation);
    		}
    

    Wie man wohl sieht, EXTREME Rumfrickelei. Aber es funzt 😃 😃
    Ich wette, das geht mit paar Zeilen, aber dafür bin ich leider zu dumm.

    🙄

    MfG und in Hoffnung, dass das jemand blickt



  • Ich würde statt von -PI bis +PI den Wertebereich auf 0 bis 2PI legen.
    Dann nimmst du einfach die Differenz der beiden Winkel (Ende-Start) und schaust nach, ob der Wert größer oder kleiner als PI ist (bei exakt PI mußt du dich halt entscheiden -).
    Wenn du außerhalb des Wertebereichs bist, mußt du noch Modulo 2
    PI rechnen.
    Bei negativen Werten mußt du berücksichtigen, daß der Modulo gespiegelt ist, d.h. du mußt den Wert dann von (2*PI) wieder abziehen oder aber soweit 2*PI addieren, bis du wieder im Positiven bist.
    Darum ist es generell einfacher im reinen positiven Bereich zu rechnen.



  • Aber hier wird doch der Bereich vorgegeben:

    newPlayerDirection = atan2(playerMoveY, playerMoveX);

    Damit ich dann das tun kann...

    D3DXMatrixTransformation2D(&playerRotation, 0, 0, 0, &playerRotationCenter, playerDirection, 0);
    playerSprite->SetTransform(&playerRotation);

    Wie soll ich den Bereich ändern?

    MfG



  • Du sollst jetzt ja auch nur die Differenz aus den beiden Richtungen bilden und diese dann entsprechend des Einheitskreises in den Bereich von 0 bis 2*PI transformieren.
    In C++:

    double diff = newPlayerDirection - playerDirection; // Differenz bilden
    
    // Transformation auf 0 bis 2*PI
    if(diff >= 0)
      diff = fmod(diff, 2*PI);
    else
      diff = 2*PI - fmod(diff, 2*PI);
    
    // check, ob rechts oder links rum drehen
    if(diff <= PI)
      playerDirection += playerTurnSpeed;
    else
      playerDirection -= playerTurnSpeed;
    

    P.S. Ich habe auch deine anderen Fragen mal gelesen:
    Wie kommt es, daß du ein Spiel programmieren willst, ohne die einfachsten Mathekenntnisse? Dann versuche wenigstens, die Formeln zu verstehen, ansonsten leidet auch dein Programm darunter, falls du kleine Änderungen vornehmen willst und keinen Plan hast...



  • Tja, kann man wohl nix machen. Bin halt ned gut in Mathe 😕

    Wenn der Start links unten ist und das Ende links oben, macht der trotzdem volle Drehung gegen Uhrzeigersinn.

    Ja ich sollte mir mal Einiges genauer Anschauen, hilfst du mir hiermit trotzdem schnell?

    MfG



  • Passen denn alle anderen Richtungsänderungen?
    Kann sein, daß in meinem Algo noch ein Fehler ist (habe ich auch nicht selbst getestet).
    Auf die Schnelle fällt mir nur ein, daß du evtl. dann diesen Fall besonders behandeln mußt:

    if(playerDirection > PI && newPlayerDirection < -PI)
    


  • Hey!

    Wie soll denn (new)playerDirection größer als PI sein? Wird doch so berechnet:

    newPlayerDirection = atan2(playerMoveY, playerMoveX);

    Und... es stimmt schon alles aber wiegesagt:

    Links unten nach links oben: Gegen den Uhrzeigersinn (Im Uhrzeigersinn kürzere Strecke)
    Links oben nach links unten: Garnix passiert

    MfG



  • Help 😕



  • Lustig, dass alle Kiddies immer nen Spiel "proggen" wollen, auch wenn sie nicht einmal ansatzweise das Wissen mitbringen



  • Ich kann mehr als du denkst. Und wenn ich was nicht weiß, frage ich eben oder beschäftige mich solange damit bis es hinhaut. Hab es ja auch hinbekommen nur leider zu kompliziert.



  • Und weißt du warum ich ein 2D Spiel programmieren will? Gerade eben damit ich viel dazulerne. Wenn ich das Wissen schon hätte, würde ich kein Spiel proggen weil ich eh kein Team hab.



  • Sorry, ich meinte natürlich jeweils PI/2.

    if(playerDirection > PI/2 && newPlayerDirection < -PI/2)
    

    Wenn der Rest funktioniert, dann bau einfach diesen Sonderfall ein.

    Ich hatte vor ca. 5 Jahren mal ähnliche Probleme zu lösen (für ein Spiel, das dann doch nicht weiterentwickelt wurde), habe aber leider dessen Code nicht mehr...


Anmelden zum Antworten