Node Movement Using Mouse && Keyboard

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
PriestlyD
Posts: 2
Joined: Tue Oct 26, 2004 8:32 pm

Node Movement Using Mouse && Keyboard

Post by PriestlyD »

Hiya chaps.

I have a question regarding the implementation of a GTA 3 kind of system, where your character strafes and moves foward using the keyboard, and rotates using the mouse.

The only snag I've hit in creating this kind of thing is pretty major. Just how do you get the node to move foward according to it's rotation?

(I tried using the forum search but I think my browser is cooked, because I keeping getting the same results over and over for a previous search)

Thanks in advance for any help.
"I once had a koala bear infestation. It was the cutest infestation ever."
dingo
Posts: 95
Joined: Tue Mar 09, 2004 5:02 am
Location: Brisbane, Australia
Contact:

Post by dingo »

I'm not familiar with GTA so bear with me......
I assume you want a 3rd person camera like Tomb Raider etc?

If so you also have the problem that the camera is not point directly at the rotation of the node. The user swings the mouse, the character knows to turn left 30 degrees, the character doesn't do this straight away, there is a deliberate lag time of like 1 second. Then the camera also deliberately lags and only starts to move to the left once the character has started.

You also have the problem that the animation of the character, to look realisitic has to shift its weight before it moves (in case you quickly turn back the other way). This way you need one heading tracking the character, one heading for where the camera should end up (where the mouse is pointing) and another heading for the camera itself. And plenty of tricky animation for the character becuase it is a major part of the player's experience being in front of the camera the whole time.

Remember the game Draken? Witha chick and her dragon as the main characters? It was third person and the main character and the dragon's animations, models, textures etc were something like 35megs. This is because the main character and the dragon were in front of the camera the whole time and needed to look really good.

By no means is it impossible to do, it will just take a bit of doing.
-= Want your C code to control real life robots? www.users.on.net/~symes =-
fdr

Post by fdr »

The only snag I've hit in creating this kind of thing is pretty major. Just how do you get the node to move foward according to it's rotation?
The engine will not do this for you - you have to write the code yourself. How you do it, depends on HOW you choose to store the position of your character and HOW does your game work. A short example in BASIC (engine agnostic):

Code: Select all

10 let x=100
20 let y=100
30 let speed=10
40 let angle=0

50 print "coords:",x,y
60 if left then angle=angle+5
70 if right then angle=angle-5
80 if forward then x=x+speed*sin(angle):y=y+speed*cos(angle)
90 goto 50
In Irrlicht you also have a nice set of tools for doing vectors, so you do not have to do the trigonometry by hand.

Hope this helps.[/code][/quote]
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

It's actually quite easy.

You have a camera and a node ( your character ).

You need to maintain your 3 "world vectors" ( Right [ X Axis ], Forward [ Z Axis ], Up [ Y Axis ] ). After rotating your camera ( there are functions in Irrlicht to rotate vectors around certain axes in the vector class called - RotateXZBy(...), RotateXYBy(...) and RotateYZBy(...) ) you'll then need to re-calculate your "world vectors". Here's some simple code to do that, based on the camera postion and the node position -

Code: Select all

// Compute new forward vector (line of sight vector) ( Z Movement Axis )
forwardVector = node->getPosition ( ) - camera->GetPosition ( );
forwardVector.normalize ( );
	
// Compute new right vector ( X Movement Axis )
rightVector = WORLDUPVECTOR.crossProduct ( forwardVector );
rightVector.normalize ( );

// Compute new up vector ( Y Movement Axis )
upVector = forwardVector.crossProduct ( rightVector );
This is not all, however, you also must now, when moving do it based off of these forward and right vectors, not the standard X and Z axis. So for instance, if you pushed the key to move you forward, you would do the following to move your node ( and camera forward )

Code: Select all

movementVector = forwardVector * ( movementAmount );

nodePosition += movementVector;
cameraPosition += movementVector;
Hope this helps, and you understand me, if not, ask away, I'm bad at explaining this stuff sometimes.

Oh, also, doing it this way, you'll need to maintain these vectors yourself. The CCameraSceneNode class in Irrlicht only maintains an UpVector.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

The one trick, I haven't yet figured out, is how to rotate the camera and the node the same amount.

For example, I have, in my game so far, they keys setup so that W and S move forwards and backwads, Q and E strafe left and right, and A and D turn left and right. When turning, I turn teh node at 0.01f degrees each render pass. I call a function I have called RotateY2D and here's the code for it -

Code: Select all

const float fPI = 3.14159265359f;

core::vector3df RotateY2D ( float degrees, core::vector3df center, core::vector3df rotation )
{
	degrees *= fPI / 180.0f;

	float cs = cosf ( degrees );
	float sn = sinf ( degrees );

	// Translate to the world's origin
	rotation.X -= center.X;
	rotation.Y -= center.Y;

	// Rotate 
	rotation.Y = rotation.X * sn + rotation.Y * cs;

	// Translate back
	rotation.X += center.X;
	rotation.Y += center.Y;

	return rotation;
}
So when I press A to turn left, I do this -

Code: Select all

if ( m_key_buffer[KEY_KEY_A] ) // Rotate Node Left
{
	newNodeRotation = movementNode->getRotation ( );
	newNodeRotation = RotateY2D ( 0.01f, newNodePosition, newNodeRotation );
	movementNode->setRotation ( newNodeRotation );
	cameraPosition.rotateXZBy ( 0.01f, newNodePosition );
The problem here is the node ends up rotating faster than the camera. I'm not sure how to go about lining them up, so that the camera is always directly behind the node, based on the direction the node is facing. If anyone's got any pointers on that, it'd be great!
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Bah, this was so easy, and I was making it so complicated!!! :evil:

Anyways, to rotate say 1 degree around the Y axis, all you have to do is

Code: Select all

core::vector3df rotation = node->getRotation ( );
rotation.Y += 1.0f;
node->setRotation ( rotation );
Then, to rotate camera the same degrees, you just do -

Code: Select all

nodePosition = node->getPosition ( );
cameraPosition = camera->getPosition ( );
cameraPosition.rotateXZBy ( 1.0f, nodePosition );
Can't believe how simple this was and I made it so complicated! Should have read the help file more closely for Irrlicht! :roll:
Post Reply