driving a car:)

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
porki
Posts: 15
Joined: Fri Jun 08, 2007 2:18 pm

driving a car:)

Post by porki »

I have this fragment of code for my car model loaded as AnimatedMesh(node1) :

class MyEventReceiver : public IEventReceiver
{
public:
bool OnEvent(SEvent event)
{
if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
{
switch(event.KeyInput.Key)
{
case KEY_KEY_W:
case KEY_KEY_S:
{
core::vector3df v = node1->getPosition();
v.Z += event.KeyInput.Key == KEY_KEY_S ? 25.0f : -25.0f;
node1->setPosition(v);
}
return true;
case KEY_KEY_A:
case KEY_KEY_D:
{
core::vector3df v = node1->getPosition();
v.X += event.KeyInput.Key == KEY_KEY_A ? 25.0f : -25.0f;
node1->setPosition(v);
}
return true;
}
}
return false;
}
};
Just like in tutorial 4 I can move my car model. But now I would like to change it:
1)I would like to ROTATE my car by pressing A,D buttons
2)I would like my car to move in direction changed by rotation, using W,S buttons.
How to make my car move while W or S button is pressed?In the code above I have to press the button every time I want to change position. What should I do to change this position constantly WHILE the button is pressed?Like in a car game?
Thank you for help!
olivehehe_03
Posts: 157
Joined: Tue Mar 20, 2007 8:30 am

Post by olivehehe_03 »

Try these functions, I found them on the forums and stuck them in my game, but can't remember who I should give credit to for them :D

They will let you move and rotate an scene::ISceneNode in relative space, that is they let it move forwards and backwards and turn left and right rather than moving in positive X or rotating in negative y (if that makes sense)

Code: Select all

using namespace irr;
void move(scene::ISceneNode *node, core::vector3df vel) //velocity vector
{
	core::matrix4 m;
	m.setRotationDegrees(node->getRotation());
	m.transformVect(vel);
	node->setPosition(node->getPosition() + vel);
	node->updateAbsolutePosition();
}

void rotate(scene::ISceneNode *node, core::vector3df rot)
{
	core::matrix4 m;
	m.setRotationDegrees(node->getRotation());
	core::matrix4 n;
	n.setRotationDegrees(rot);
	m *= n;
	node->setRotation( m.getRotationDegrees() );
	node->updateAbsolutePosition();
}

//turning left and right
void turn(scene::ISceneNode *node, f32 rot)
{
	rotate(node, core::vector3df(0.0f, rot, 0.0f) );
}

//rotating up and down
void pitch(scene::ISceneNode *node, f32 rot)
{
	rotate(node, core::vector3df(rot, 0.0f, 0.0f) );
}

//rolling left and right
void roll(scene::ISceneNode *node, f32 rot)
{
	rotate(node, core::vector3df(0.0f, 0.0f, rot) );
}

void moveForward(scene::ISceneNode* node, f32 dist)
{
	core::vector3df vect(0.0f, 0.0f, 0.0f);
	vect.Z += dist;
	move(node, vect);
}

void moveBackward(scene::ISceneNode* node, f32 dist)
{
	core::vector3df vect(0.0f, 0.0f, 0.0f);
	vect.Z -= dist;
	move(node, vect);
}

void moveLeft(scene::ISceneNode* node, f32 dist)
{
	core::vector3df vect(0.0f, 0.0f, 0.0f);
	vect.X -= dist;
	move(node, vect);
}

void moveRight(scene::ISceneNode* node, f32 dist)
{
	core::vector3df vect(0.0f, 0.0f, 0.0f);
	vect.X += dist;
	move(node, vect);
}
EDIT: I think those moveForward, Backward, Left and Right functions are mine that I added to make my job a little easier, but I don't use them any more since I added physics to my game so feel free to use them yourself :D

EDIT EDIT: I'm in a helpful mood today, so I'm gonna help you with your event receiver code. It looks like you took that straight from the movement example, which is a good start, but there's a much better way to do it, have a look below.

Code: Select all

class MyEventReceiver : public IEventReceiver
{
	public:
		bool OnEvent(SEvent event)
		{
			if (event.EventType == EET_KEY_INPUT_EVENT)
			{
				// if key is Pressed Down
				if (event.KeyInput.PressedDown == true)
				{
					keyState[event.KeyInput.Key] = true;
				}
			}
			return true;
		}
	
		// Keyboard key states.
		bool keyState[KEY_KEY_CODES_COUNT];

		MyEventReceiver()
		{
			//KeyBoard States.
			for (int i = 0; i <= KEY_KEY_CODES_COUNT; i++)
			{
				keyState[i] = false;
			}
		}
} receiver;
First of all, if you want an event receiver thats even better than that, go here.

Ok, to use that code, when you want to see if a key was pressed you do it like this, look for EKEY_CODE in the Irrlicht documentation to see what each key is:

Code: Select all

if (receiver.keyState[EKEY_CODE] == true) 
{
	do whatever;
}
So to combine all that into one simple answer, moving a node forward when you pess 'W' would look something like this:

Code: Select all

//note: the '== true' doesn't need to be there because the code below means that anyway
if (recevier.keyState[KEY_KEY_W]) 
{
	moveForward(carNode, 1.0f); //carNode is the scene node for your car, 1.0f is the distance to move
}
Hope that helps :D
Tell me what you cherish most. Give me the pleasure of taking it away.
porki
Posts: 15
Joined: Fri Jun 08, 2007 2:18 pm

Post by porki »

I'm thankful:) I'll check it out and tell you!
porki
Posts: 15
Joined: Fri Jun 08, 2007 2:18 pm

Post by porki »

where should I place this fragment?
if (receiver.keyState[KEY_KEY_W])
{
moveForward(node1, 50.0f);
}
After making this EventReceiver program compiles but car doesn't move at all and I lost control of my camera:) Here is all the code from my program:
#include <irrlicht.h>
#include <iostream>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")
float predkosc;
float wilgotnosc;
float tarcie;
scene::IAnimatedMesh* mesh = 0;
scene::IAnimatedMeshSceneNode* node1 = 0;

void move(scene::ISceneNode *node, core::vector3df vel) //velocity vector
{
core::matrix4 m;
m.setRotationDegrees(node->getRotation());
m.transformVect(vel);
node->setPosition(node->getPosition() + vel);
node->updateAbsolutePosition();
}
void rotate(scene::ISceneNode *node, core::vector3df rot)
{
core::matrix4 m;
m.setRotationDegrees(node->getRotation());
core::matrix4 n;
n.setRotationDegrees(rot);
m *= n;
node->setRotation( m.getRotationDegrees() );
node->updateAbsolutePosition();
}
void turn(scene::ISceneNode *node, f32 rot)
{
rotate(node, core::vector3df(0.0f, rot, 0.0f) );
}
void pitch(scene::ISceneNode *node, f32 rot)
{
rotate(node, core::vector3df(rot, 0.0f, 0.0f) );
}
void roll(scene::ISceneNode *node, f32 rot)
{
rotate(node, core::vector3df(0.0f, 0.0f, rot) );
}
void moveForward(scene::ISceneNode* node, f32 dist)
{
core::vector3df vect(0.0f, 0.0f, 0.0f);
vect.Z += dist;
move(node, vect);
}
void moveBackward(scene::ISceneNode* node, f32 dist)
{
core::vector3df vect(0.0f, 0.0f, 0.0f);
vect.Z -= dist;
move(node, vect);
}
void moveLeft(scene::ISceneNode* node, f32 dist)
{
core::vector3df vect(0.0f, 0.0f, 0.0f);
vect.X -= dist;
move(node, vect);
}
void moveRight(scene::ISceneNode* node, f32 dist)
{
core::vector3df vect(0.0f, 0.0f, 0.0f);
vect.X += dist;
move(node, vect);
}
class MyEventReceiver : public IEventReceiver
{
public:

bool OnEvent(SEvent event)
{
if (event.EventType == EET_KEY_INPUT_EVENT)
{
if (event.KeyInput.PressedDown == true)
{
keyState[event.KeyInput.Key] = true;
}
}
return true;
}

bool keyState[KEY_KEY_CODES_COUNT];

MyEventReceiver(scene::ISceneNode* terrain)
{
Terrain = terrain;
for (int i = 0; i <= KEY_KEY_CODES_COUNT; i++)
{
keyState = false;
}
}
private:
scene::ISceneNode* Terrain;

}; //receiver;

int main()
{
printf("Podaj predkosc: ");
std::cin >> predkosc;

printf("Podaj wilgotnosc: ");
std::cin >> wilgotnosc;

printf("Podaj tarcie: ");
std::cin >> tarcie;

IrrlichtDevice* device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(1024, 768));
device->setWindowCaption(L"Symulacja");
if (device == 0)
return 1;

video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
gui::IGUIEnvironment* env = device->getGUIEnvironment();

driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
//////////////////////WRZUCAMY ALFĘ
mesh = smgr->getMesh("../../media/alfa.3ds");
node1 = smgr->addAnimatedMeshSceneNode( mesh );
node1->setPosition(core::vector3df(0,0,30));
node1->setMaterialFlag(video::EMF_LIGHTING, false);
//////////////////////////////////////

env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"),
core::position2d<s32>(10,10));

env->getSkin()->setFont(env->getFont("../../media/fontlucida.png"));

gui::IGUIStaticText* text = env->addStaticText(
L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map",core::rect<s32>(10,440,250,475), true, true, 0, -1, true);

scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0,100.0f,1200.f);

camera->setPosition(core::vector3df(1900*2,255*2,3700*2));
camera->setTarget(core::vector3df(2397*2,343*2,2700*2));
camera->setFarValue(12000.0f);

device->getCursorControl()->setVisible(false);

scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode(
"../../media/terrain-heightmap.bmp",
0, // parent node
-1, // node id
core::vector3df(0.f, 0.f, 0.f), // position
core::vector3df(0.f, 0.f, 0.f), // rotation
core::vector3df(40.f, 4.4f, 40.f), // scale
video::SColor ( 255, 255, 255, 255 ), // vertexColor,
5, // maxLOD
scene::ETPS_17, // patchSize
4 // smoothFactor
);

terrain->setMaterialFlag(video::EMF_LIGHTING, false);
terrain->setMaterialTexture(0, driver->getTexture("../../media/1.bmp"));
terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg"));
terrain->setMaterialType(video::EMT_DETAIL_MAP);
terrain->scaleTexture(1.0f, 20.0f);
//terrain->setDebugDataVisible ( true );
scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain, 0);
terrain->setTriangleSelector(selector);
selector->drop();

scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
selector, camera, core::vector3df(60,100,60),
core::vector3df(0,0,0),
core::vector3df(0,50,0));
camera->addAnimator(anim);
//node1->addAnimator(anim);
anim->drop();

MyEventReceiver receiver(terrain);
device->setEventReceiver(&receiver);

if (receiver.keyState[KEY_KEY_W])
{
moveForward(node1, 50.0f);
}

driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);

smgr->addSkyBoxSceneNode(
driver->getTexture("../../media/irrlicht2_up.jpg"),
driver->getTexture("../../media/irrlicht2_dn.jpg"),
driver->getTexture("../../media/irrlicht2_lf.jpg"),
driver->getTexture("../../media/irrlicht2_rt.jpg"),
driver->getTexture("../../media/irrlicht2_ft.jpg"),
driver->getTexture("../../media/irrlicht2_bk.jpg"));

driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);

int lastFPS = -1;

while(device->run())
if (device->isWindowActive())
{
driver->beginScene(true, true, 0 );
smgr->drawAll();
env->drawAll();
driver->endScene();

int fps = driver->getFPS();
if (lastFPS != fps)
{
core::stringw str = L"Terrain Renderer - Irrlicht Engine [";
str += driver->getName();
str += "] FPS:";
str += fps;
str += " Height: ";
str += terrain->getHeight(camera->getAbsolutePosition().X, camera->getAbsolutePosition().Z);

device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
device->drop();
return 0;
}
olivehehe_03
Posts: 157
Joined: Tue Mar 20, 2007 8:30 am

Post by olivehehe_03 »

It should go in the main loop before driver->endScene();. Just remember for later that if you want to move anything you should do it in the main loop or it won't work properly.
Tell me what you cherish most. Give me the pleasure of taking it away.
porki
Posts: 15
Joined: Fri Jun 08, 2007 2:18 pm

Post by porki »

I managed to move my car but it doesn't stop after releasing W button, it goes constantly. What should I do to force it to move constantly bt only when button is pressed and held
Perceval
Posts: 158
Joined: Tue May 30, 2006 2:42 pm

Post by Perceval »

Code: Select all

 bool OnEvent(SEvent event)
{
if (event.EventType == EET_KEY_INPUT_EVENT)
{
if (event.KeyInput.PressedDown == true)
{
keyState[event.KeyInput.Key] = true;
}
}
return true;
} 
This code is wrong. Change it to

Code: Select all

 bool OnEvent(SEvent event)
{
if (event.EventType == EET_KEY_INPUT_EVENT)
{
keyState[event.KeyInput.Key] = true;
}
return true;
} 
This way , you will be able to change the keystate to false when a key is released, that was your problem.

ps : you could change

Code: Select all

if (receiver.keyState[EKEY_CODE] == true) 
to

Code: Select all

if (receiver.keyState[EKEY_CODE])
porki
Posts: 15
Joined: Fri Jun 08, 2007 2:18 pm

Post by porki »

Great, these lines of code and it works!
keyState[event.KeyInput.Key] = true;
if (event.KeyInput.PressedDown == false)
{
keyState[event.KeyInput.Key] = false;
}

But how can I get my camera control back?:)It's fps camera and after all these changes connected with EventReceiver I'm unable to control my camera with cursor keys, only change angle with mouse.
Perceval
Posts: 158
Joined: Tue May 30, 2006 2:42 pm

Post by Perceval »

Oups, sorry. I've made a mistake in my last post. I should have written :

Code: Select all

 bool OnEvent(SEvent event)
{
if (event.EventType == EET_KEY_INPUT_EVENT)
{
keyState[event.KeyInput.Key] = event.KeyInput.PressedDown;
return true;
}
return false;
}
porki
Posts: 15
Joined: Fri Jun 08, 2007 2:18 pm

Post by porki »

ok, that works, but what with a camera? What are the states for cursor keys?

if (receiver.keyState[KEY_KEY_S])// what should be here for cursor key(up)?
{
moveForward(camera, 50.0f);
}

I can do the same thing I did with car, for example choose IKJL keys to control camera, but how can I do this to use cursor keys?
olivehehe_03
Posts: 157
Joined: Tue Mar 20, 2007 8:30 am

Post by olivehehe_03 »

Perceval wrote:Oups, sorry. I've made a mistake in my last post. I should have written :

Code: Select all

 bool OnEvent(SEvent event)
{
if (event.EventType == EET_KEY_INPUT_EVENT)
{
keyState[event.KeyInput.Key] = event.KeyInput.PressedDown;
return true;
}
return false;
}
Thanks for pointing that out, I was just typing from memory because I use a different receiver myself.

@porki
Up is just KEY_UP, have a look at the keycodes.h source file page in the documentation, it lists all 255 of them and what key they are for.
Tell me what you cherish most. Give me the pleasure of taking it away.
dudMaN
Posts: 111
Joined: Fri Mar 02, 2007 6:37 pm

Post by dudMaN »

I See you have been asking for help on alot of trivial stuff, such as how to rotate something.

actually reading the tutorials, and checking the docs will save you alot of time.

*hint* setRotation'


-dudMan
Post Reply