Advertisement

Speed Division Problem, Help Please.

Started by December 15, 2017 06:12 PM
14 comments, last by Josheir 6 years, 11 months ago



void update()
{

	if (thrust)
	{
		dx += cos(angle*DEGTORAD)*.02;
		dy += sin(angle*DEGTORAD)*.02;
	}
	else
	{
		dx*=0.99;
		dy*=0.99;
	}

	int maxSpeed = 15;
	float speed = sqrt(dx*dx+dy*dy);

	if (speed>maxSpeed)
	{
		dx *= maxSpeed/speed;
		dy *= maxSpeed/speed;
	}

	x+=dx;
	y+=dy;

.
.
.

}

In the above code, why is maxSpeed being divided by the speed variable.  I'm stumped.

 

Thank you,

Josheir

it caps the speed to maxSpeed.

basically it's a minor optimization instead of doing:


	float maxSpeed = 15.0f;
	float Len = sqrt(dx*dx+dy*dy);
	float Speed = min(Len, maxSpeed);
	dx = dx/Len*Speed;
	dy = dy/Len*Speed;
	

which normalizes the vector(this means the vector has a length of 1) then scaling to your desired speed, the above sidesteps that dy/Len*Speed to do dy *= maxSpeed/Len;  which is effectivly the same operation, but only done when your speed is actually higher instead of every frame.

if you don't understand what normalizing a vector means then i'd start with learning that, then things should become more clear.

Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.
Advertisement

maxSpeed should be a float, not an int.

To unserstand the math, reduce it to 1D:

maxSpeed = 15

speed = 20

if (20>15)

{

factor = 15/20, so 0.75

speed * 0.75 = 15, so the max speed we want

}

That's easy. Do you understand the move from 2D to 1D here?

It's been a long time...They're both helpful!

4 hours ago, Josheir said:

float speed = sqrt(dx*dx+dy*dy);

Now, I'm understanding that speed is the magnitude of the vector.  What I'm not understanding is how dx's and dy's time numerator is working.  

Thank you,

Josheir

What we want is to set the magnitude to max speed, maybe altering the equation helps:

dx *= maxSpeed/speed;

new_dx = dx * maxSpeed / speed

new_dx = dx / speed * maxSpeed // note that speed is the current magnitude

so, first dividing by speed we set the magnitude of the vector to 1 (assuming we do it fot y as well)

Then by multiplying with maxSpeed the new magnitude becomes maxSpeed.

Thank you, everyone.  Enjoy the holiday season safely!

Josheir

Advertisement
On ‎12‎/‎15‎/‎2017 at 1:12 PM, Josheir said:

float speed = sqrt(dx*dx+dy*dy);

A quick question:  how is speed achieved from the sqrt(... )?  Speed is distance over time and I am failing to understand if dx and dy are distance over time too?

Thank you,

Josheir

 

EDIT: perhaps the time is one second and the :   dx += cos(angle*DEGTORAD)*.02

is adjusting the dx by the decimal multiplication.

1 hour ago, Josheir said:

A quick question:  how is speed achieved from the sqrt(... )?  Speed is distance over time and I am failing to understand if dx and dy are distance over time too?

 

dx and dy are the x and y components of the velocity vector, so they are in terms of "distance/time" along the x and y basis of the coordinate frame.   The code uses the Pythagorean Theorem to calculate the length of that vector, i.e. the speed.  Dividing by the speed at the end normalized the vector to length 1.0, and then multiplying by maxSpeed sets the speed to that while keeping the direction.

Thank you, just making sure I am on the right page...

Sincerely,

Josheir

That's pretty much the 'dimension reduction' i meant earlier what you ask for.

 

First let's look at this:

x = cos(angle);

y = sin(angle);

Depending on angle we always get a point with a distance of exactly 1 from the origin at (0,0).

(If we do it for every angle and plot each point, we get the unit circle with example points (0,1), (1,0), (0.7*0.7), (-1,0) etc. - Every possible direction, but each at a distance of one)

 

x = cos(angle) * 5;

y = sin(angle) * 5;

 

So if we multiply both dimensions with a constant (5), the resulting length of the vector becomes 5 as well, but how to calculate this if we don't know neither length nor angle?

Imagine a line from origin (0,0) to a given point (3,5). We want to know the length of that line. Note the right angled triangle we get if we set one dimension to zero, e.g.: (3,5) (3,0) (5,0). We get side lengths of the right angled sides of a:3 and b:5.

Now we can use Pythagoras right angled triangle rule applied to get the length if that vector.

a*a + b*b = c*c  // c is the non right angled side we want to calculate

sqrt (a*a + b*b) = c

sqrt (3*3 +5*5) = 5.83 

Note that a negative length of -3 would result in the same: (-3*-3 + 5*5) == (3*3 + 5*5). Signs get canceled out by multiplication with itself. So it does not matter what direction the vector points, to the negative or positive sides of our coordinate system, we get the correct length anyways.

 

This is what you see in that line:

speed = sqrt(x*x+y*y)

 

Here, we do not care which direction the 2D vector (x,y) points or in what direction an example vehicle is driving, we only care about its 1D speed, and that's the length of it's 2D vector.

There are other possibilities of reduced dimensions, e.g. if we set each y (upwards) coord of a rotating 3D cube to zero and draw this in black, we get a shadow of the cube. What we do is projecting the cube to the 2D xz plane, which is different to the example above where we use lengths.

 

1 hour ago, Josheir said:

EDIT: perhaps the time is one second and the :   dx += cos(angle*DEGTORAD)*.02

The context of the given code is not clear, it seems dx,dy means acceleration, but i'm not sure what's the timestep etc.

Here is a example for simple physics of an object under constant external force like gravity to introduce some better terminology:

 


vec2 p(0,-8); // position
vec2 v(1,0.1); // velocity
vec2 a(0,0.2); // acceleration (we keep this constant like gravity)
float timestep = 0.16;

for (float time = 0; time < 20.0; time += timestep) // do a number of integration steps
{
v += a * timestep; // update velocity with acceleration
p += v * timestep; // update position with velocity
PlotPoint (p);
}

The plot should show a hyperbolic trajectory like we see when throwing a stone.

Games like Super Mario use this kind of physics, while games like Pac Man don't use acceleration and objects just use (mostly constant) velocity.

(You could rewrite this code using float pX=0, pY=-8; etc. instead vec2 p(0,-8);)

 

 

 

 

 

 

 

This topic is closed to new replies.

Advertisement