combining strafe and walk?

Started by
20 comments, last by cozzie 10 years, 3 months ago

Okay, I'm not sure if I understand it correct then.

Wouldn't normalizing the vector mean it gets a length of 1.0 instead of the wanted 0.7 in this example?

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Advertisement

Yep, hence the movespeed multiplication


Vmove = normalize(V) * movespeed
Ah ok, I get it.
This is a much cleaner and better approach :)

Thanks

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Just be careful you don't use the same limited vector for player movement as you do for things like gravity or getting flung by a catapult or whatever, as they should be normalized under a different set of constraints.

Ie Don't do this:

playerVec += walkMovementVec

playerVec += gravityVec

playerVec= normalize(playerVec) * playerWalkSpeed

Thanks, I'll keep that in mind

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Since you have different velocities in each direction it might be even better to scale after normalization, i.e.


if(_dinput.KeyDown(DIK_W)) movement.z += 1;
if(_dinput.KeyDown(DIK_S)) movement.z -= 1;
			
if(_dinput.KeyDown(DIK_A)) movement.x += 1;
if(_dinput.KeyDown(DIK_D)) movement.x -= 1;

if(_dinput.KeyDown(DIK_PRIOR)) movement.y += 1;
if(_dinput.KeyDown(DIK_NEXT)) movement.y -= 1;

movement = normalized(movement); // returns 0 if original length is 0, otherwise a unit vector is returned
movement.x *= _player.GetStrafeSpeed();
movement.y *= _player.GetWalkSpeed();
movement.z *= _player.GetWalkSpeed();

I've put the changes through, seems to work fine:


			Crealysm_math::VECTOR3 movement = Crealysm_math::VECTOR3(0.0f, 0.0f, 0.0f);

			if(_dinput.KeyDown(DIK_W)) movement.z += 1.0f; 
			if(_dinput.KeyDown(DIK_S)) movement.z -= 1.0f;
			
			if(_dinput.KeyDown(DIK_A)) movement.x -= 1.0f;
			if(_dinput.KeyDown(DIK_D)) movement.x += 1.0f;

			if(_dinput.KeyDown(DIK_PRIOR)) movement.y += 1.0f;
			if(_dinput.KeyDown(DIK_NEXT)) movement.y -= 1.0f;

			movement.normalize();
			movement.x *= _player.GetStrafeSpeed() * _timer.GetDelta();
			movement.y *= _player.GetWalkSpeed() * _timer.GetDelta();
			movement.z *= _player.GetWalkSpeed() * _timer.GetDelta();
			
			_player.SetPosition(_d3dcam.Move(movement));

Maybe a bit of topic, but can someone help me with the following.

I've made a inline normalize function for my vector struct, this works:


	VECTOR3 normalize()
	{
		float mag = sqrt(x*x + y*y + z*z);
		VECTOR3 normalized;
		normalized.x = x / mag;
		normalized.y = y / mag;
		normalized.z = z / mag;
		return normalized;
	}

But when I try this, it doesn't:


	VECTOR3 normalize()
	{
		float mag = sqrt(x*x + y*y + z*z);
		x = x / mag;
		y = y / mag;
		z = z / mag;
		return *this;
	}

What am I doing wrong?

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

I've put the changes through, seems to work fine:









			Crealysm_math::VECTOR3 movement = Crealysm_math::VECTOR3(0.0f, 0.0f, 0.0f);

			if(_dinput.KeyDown(DIK_W)) movement.z += 1.0f; 
			if(_dinput.KeyDown(DIK_S)) movement.z -= 1.0f;
			
			if(_dinput.KeyDown(DIK_A)) movement.x -= 1.0f;
			if(_dinput.KeyDown(DIK_D)) movement.x += 1.0f;

			if(_dinput.KeyDown(DIK_PRIOR)) movement.y += 1.0f;
			if(_dinput.KeyDown(DIK_NEXT)) movement.y -= 1.0f;

			movement.normalize();
			movement.x *= _player.GetStrafeSpeed() * _timer.GetDelta();
			movement.y *= _player.GetWalkSpeed() * _timer.GetDelta();
			movement.z *= _player.GetWalkSpeed() * _timer.GetDelta();
			
			_player.SetPosition(_d3dcam.Move(movement));

Maybe a bit of topic, but can someone help me with the following.
I've made a inline normalize function for my vector struct, this works:


	VECTOR3 normalize()
	{
		float mag = sqrt(x*x + y*y + z*z);
		VECTOR3 normalized;
		normalized.x = x / mag;
		normalized.y = y / mag;
		normalized.z = z / mag;
		return normalized;
	}

But when I try this, it doesn't:


	VECTOR3 normalize()
	{
		float mag = sqrt(x*x + y*y + z*z);
		x = x / mag;
		y = y / mag;
		z = z / mag;
		return *this;
	}
What am I doing wrong?


Various problems:

Consider what happens if movement is zero. 'mag' will be zero. You'll divide x, y, and z by zero - getting an undefined result (or an exception).

Also your line:

movement.normalize();

You're not using the return value, which is why the behavior of your two normalize methods differ. The first normalize method will not change 'this', and you're not using the return value, so it doesn't actually do anything right now. Both methods can divide-by-zero, but the second one will actually be used because it changes 'this' itself.


Also, consider what normalizing a vector does: It FORCES it to be length = 1, even if the length was less than 1. What if the player wants to move slower than that? What if they don't want to move at all? Let's say you have an analog joystick instead of keys. The possible x/y inputs from the joystick are a continuous range from zero to maximum movement in each direction. Normalizing forces those to adhere to the points on the edge of a unit sphere, meaning you'll always move at maximum speed in SOME direction even if you don't want to.

Look at what I suggested in my first post:


if (speed > limit)
Essentially, this limits movement to anywhere inside the unit sphere, not just the edge of it. It protects from division by zero and amplified jitter when normalizing vectors that are extremely close to zero.

Thanks.

- I understand what you mean with the division by 0, strange thing is that it isn't crashing when I don't move, even when I initially start up the demo/ application

Action: I could check if mag != 0 and only if so, proceed. Is that the way to go?

- OK, so my second normalize function of my vector struct is the right way to go. I'll use that and see what it's going wrong, probably because of the division by zero :)

- I read back your earlier reply/ post and I'm chewing on it (again)

I'll let you know when it's finished and I understand it :)

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Think I've got it, results below.

To make sure I understand correct, I think this is what I'm doing:

1. creating a zero vector

2. get keyboard input to determine the base movement

3. based on the magnitude of the vector, 'limit' the movement (over all axes now) to my max walking speed * delta

4. update the position of the camera and player

A few thoughts:

- DeltaT is now multiplied when 'limiting', I could also do that in the end when updating the position (difference?)

- If I wanted to distinguish walking/ strafing/ 'flying' speed I could copy this line three times, using a different 'walkspeed':

movement = movement * ((_player.GetWalkSpeed() * _timer.GetDelta()) / speed);

- "Movement = movement *" can also be "movement *=" smile.png

I don't think distinguishing walking and strafe speed is necessary anymore, since I introduced it as a hack to prevent walking + strafing to be to quick smile.png)

I also remade my vector functions, I'll split it to a separate header with the prototypes and move the implementations to a new cpp file

(it's growing too large, I'll also have to add more operations, !=, == etc.).


			_player.Running(_dinput.KeyDown(DIK_LSHIFT));	
			Crealysm_math::VECTOR3 movement = Crealysm_math::VECTOR3(0.0f, 0.0f, 0.0f);

			if(_dinput.KeyDown(DIK_W)) movement.z = 1.0f; 
			if(_dinput.KeyDown(DIK_S)) movement.z = -1.0f;
			
			if(_dinput.KeyDown(DIK_A)) movement.x = -1.0f;
			if(_dinput.KeyDown(DIK_D)) movement.x = 1.0f;

			if(_dinput.KeyDown(DIK_PRIOR)) movement.y = 1.0f;
			if(_dinput.KeyDown(DIK_NEXT)) movement.y = -1.0f;

			float speed = movement.magnitude();
			if(speed > _player.GetWalkSpeed())
				movement = movement * ((_player.GetWalkSpeed() * _timer.GetDelta()) / speed);

			_player.SetPosition(_d3dcam.Move(movement));


// a few of the vector functions

	// RETURN MAGNITUDE OF VECTOR
	float magnitude()
	{
		return sqrt(x*x + y*y + z*z);
	}

	// NORMALIZE THE VECTOR IF MAGNITUDE != 0
	VECTOR3 normalize()
	{
		float mag = sqrt(x*x + y*y + z*z);
		if(mag != 0.0f)
		{
			x = x / mag;
			y = y / mag;
			z = z / mag;
		}
		return *this;
	}

	// MULTIPLY A VECTOR WITH A SCALAR
	VECTOR3 operator* (const float pScalar)
	{
		VECTOR3 newVector = *this;
		newVector.x *= pScalar;
		newVector.y *= pScalar;
		newVector.z *= pScalar;
		return newVector;
	}

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

This topic is closed to new replies.

Advertisement