driving a car:)
driving a car:)
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!
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!
-
- Posts: 157
- Joined: Tue Mar 20, 2007 8:30 am
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
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)
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
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.
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:
So to combine all that into one simple answer, moving a node forward when you pess 'W' would look something like this:
Hope that helps
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 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;
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;
}
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
}
Tell me what you cherish most. Give me the pleasure of taking it away.
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;
}
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;
}
-
- Posts: 157
- Joined: Tue Mar 20, 2007 8:30 am
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;
}
Code: Select all
bool OnEvent(SEvent event)
{
if (event.EventType == EET_KEY_INPUT_EVENT)
{
keyState[event.KeyInput.Key] = true;
}
return true;
}
ps : you could change
Code: Select all
if (receiver.keyState[EKEY_CODE] == true)
Code: Select all
if (receiver.keyState[EKEY_CODE])
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.
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.
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;
}
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?
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?
-
- Posts: 157
- Joined: Tue Mar 20, 2007 8:30 am
Thanks for pointing that out, I was just typing from memory because I use a different receiver myself.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; }
@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.