simple WASD controls

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
roxaz
Posts: 575
Joined: Tue Jan 23, 2007 8:35 pm
Location: LT

simple WASD controls

Post by roxaz »

Its half-mine code.
Resources:
http://www.irrlicht3d.org/wiki/index.ph ... ByCmdKewin
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=19005

Code:

Code: Select all

#define RUN_SPEED 10

void Controls::keyDown(int key, bool b)
{
	keysDown[key] = b;
}

void Controls::movementUpdate(void)
{
	vector3df moveLoc;
	vector3df ax1;
	vector3df ax2;

	if(keysDown[KEY_KEY_W] && keysDown[KEY_KEY_D])
	{
		ax1 = vector3df(0, 0, 1 * RUN_SPEED); 
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax1);
		ax2 = vector3df(1 * RUN_SPEED, 0, 0);
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax2);
		moveLoc = vEngine->cam->getAbsolutePosition() + ax1 + ax2;
		moveLoc.Y = vEngine->cam->getAbsolutePosition().Y;
	}
	if(keysDown[KEY_KEY_W] && keysDown[KEY_KEY_A])
	{
		ax1 = vector3df(0, 0, 1 * RUN_SPEED); 
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax1);
		ax2 = vector3df(1 * RUN_SPEED, 0, 0);
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax2);
		moveLoc = vEngine->cam->getAbsolutePosition() + ax1 - ax2;
		moveLoc.Y = vEngine->cam->getAbsolutePosition().Y;
	}
	if(keysDown[KEY_KEY_S] && keysDown[KEY_KEY_D])
	{
		ax1 = vector3df(0, 0, 1 * RUN_SPEED); 
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax1);
		ax2 = vector3df(1 * RUN_SPEED, 0, 0);
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax2);
		moveLoc = vEngine->cam->getAbsolutePosition() - ax1 + ax2;
		moveLoc.Y = vEngine->cam->getAbsolutePosition().Y;
	}
	if(keysDown[KEY_KEY_S] && keysDown[KEY_KEY_A])
	{
		ax1 = vector3df(0, 0, 1 * RUN_SPEED); 
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax1);
		ax2 = vector3df(1 * RUN_SPEED, 0, 0);
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax2);
		moveLoc = vEngine->cam->getAbsolutePosition() - ax1 - ax2;
		moveLoc.Y = vEngine->cam->getAbsolutePosition().Y;
	}
	if(keysDown[KEY_KEY_W] && !keysDown[KEY_KEY_A] && !keysDown[KEY_KEY_D] && !keysDown[KEY_KEY_S])
	{
		ax1 = vector3df(0, 0, 1 * RUN_SPEED); 
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax1);
		moveLoc += vEngine->cam->getAbsolutePosition() + ax1;
		moveLoc.Y = vEngine->cam->getAbsolutePosition().Y;
	}
	if(keysDown[KEY_KEY_S] && !keysDown[KEY_KEY_A] && !keysDown[KEY_KEY_D] && !keysDown[KEY_KEY_W])
	{
		ax1 = vector3df(0, 0, 1 * RUN_SPEED); 
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax1);
		moveLoc += vEngine->cam->getAbsolutePosition() - ax1;
		moveLoc.Y = vEngine->cam->getAbsolutePosition().Y;
	}
	if(keysDown[KEY_KEY_D] && !keysDown[KEY_KEY_A] && !keysDown[KEY_KEY_S] && !keysDown[KEY_KEY_W])
	{
		ax1 = vector3df(1 * RUN_SPEED, 0, 0); 
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax1);
		moveLoc += vEngine->cam->getAbsolutePosition() + ax1;
		moveLoc.Y = vEngine->cam->getAbsolutePosition().Y;
	}
	if(keysDown[KEY_KEY_A] && !keysDown[KEY_KEY_S] && !keysDown[KEY_KEY_D] && !keysDown[KEY_KEY_W])
	{
		ax1 = vector3df(1 * RUN_SPEED, 0, 0); 
		vEngine->cam->getAbsoluteTransformation().rotateVect(ax1);
		moveLoc += vEngine->cam->getAbsolutePosition() - ax1;
		moveLoc.Y = vEngine->cam->getAbsolutePosition().Y;
	}
	if(!keysDown[KEY_KEY_W] && !keysDown[KEY_KEY_S] && !keysDown[KEY_KEY_A] && !keysDown[KEY_KEY_D])
	{
		moveLoc = vEngine->cam->getAbsolutePosition();
	}

	vEngine->cam->setPosition(moveLoc);
}

bool Controls::OnEvent(SEvent event)
{
	if(event.EventType == EET_KEY_INPUT_EVENT)
	{
		//Keyboard events here
		if(event.KeyInput.PressedDown)
		{
			keyDown(event.KeyInput.Key, true);
			movementUpdate();
		}
		else
		{
			for(int i = 0; i < 256; i++)
				keyDown(i, false);
		}
	}

	return true;
}
Known bugs: when camera begins to move it stops for a sec and then moves smoothly. I dont know how to remove that stucking up at the start of the movement. Also for the first move camera moves not to the direction that it should.

Note for newbies: vEngine is pointer to video engine object that holds ICameraSceneNode and other irrlicht goodies
Last edited by roxaz on Mon Mar 05, 2007 7:31 pm, edited 1 time in total.
lester
Posts: 86
Joined: Mon Jan 29, 2007 3:33 pm

Post by lester »

omg, there is a FPS cam with fully configurable key controls.
roxaz
Posts: 575
Joined: Tue Jan 23, 2007 8:35 pm
Location: LT

Post by roxaz »

Image

as far as i know ICameraSceneNode has same virtual OnEvent() just like IEventReceiver. The whole idea was about how to make cam move towards - backwards, left - right depending on where cam is looking at
lester
Posts: 86
Joined: Mon Jan 29, 2007 3:33 pm

Post by lester »

The whole idea was about how to make cam move towards - backwards, left - right depending on where cam is looking at
You mean, the current camera moves not where it is looking at, but where it wants to move itself, lol?
roxaz
Posts: 575
Joined: Tue Jan 23, 2007 8:35 pm
Location: LT

Post by roxaz »

simple added camera moves just using key controls and it moves in 3d space so if you look up - it moves up. my cam is better for gravity - enabled scene. it doesnt jump when you press forward and look up. got idea? ;)
lester
Posts: 86
Joined: Mon Jan 29, 2007 3:33 pm

Post by lester »

oh well, i see for now. The idea is not bad, but you shoud better use PressedDown state of the keys rather than just an input key event. This should make the moving smooth.
roxaz
Posts: 575
Joined: Tue Jan 23, 2007 8:35 pm
Location: LT

Post by roxaz »

yea, thats true. i have improved my code a bit (check the 1st post), now it knows how to move to all directions (W+A; W+D; S+A; S+D). Still movement isnt smooth, i cant find where problem is...
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Your code is over-complicated for what you are trying to do. There is a lot of unnecessary if logic in there. Seems like this would work just fine and the camera movement would be smooth [but starts and stops would be quite abrupt].

[Edit: partial code cut and moved to post below]
Last edited by vitek on Tue Mar 06, 2007 10:13 pm, edited 1 time in total.
roxaz
Posts: 575
Joined: Tue Jan 23, 2007 8:35 pm
Location: LT

Post by roxaz »

yes, your code is surely cleaner than mine but moevement still isnt smooth as it should be
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

I don't know what you are doing wrong, I've tested the code and it is smooth as butter. The only way it would not be smooth is if you are getting a very bad frame rate, and there isn't any amount of camera movement smoothing that can fix that.

Code: Select all

#include <irrlicht.h>
using namespace irr;

#pragma comment(lib, "Irrlicht.lib")

class MyEventReceiver : public IEventReceiver
{
public:
  MyEventReceiver()
  {
    u32 k = 0;
    for (k = 0; k < sizeof(Keys) / sizeof(*Keys); ++k)
      Keys[k] = false;
  }

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

    return false;
  }

  bool isKeyPressed(EKEY_CODE key) const
  {
    return Keys[key];
  }

private:
  bool Keys[KEY_KEY_CODES_COUNT];
};

int main()
{
  // ask user for driver

  video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D8;

  // create device and exit if creation failed

  IrrlichtDevice* device =
    createDevice(driverType, core::dimension2d<s32>(1024, 768));

  if (device == 0)
    return 1; // could not create selected driver.

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

  // load the scene

  smgr->loadScene("../../media/example.irr");

  // add a user controlled camera

  scene::ICameraSceneNode* camera = smgr->addCameraSceneNode();

  // setup receiver to move camera

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

  u32 then = device->getTimer()->getTime();
  u32 old = 0;

  while (device->run())
  {
    u32 now = device->getTimer()->getTime();
    f32 elapsed = (now - then) / 1000.f;
    then = now;

    if (device->isWindowActive())
    {
      // in your render/run loop
      core::vector3df move(0, 0, 0);

      if (receiver.isKeyPressed(KEY_KEY_W))
        move.Z += 1.f;

      if (receiver.isKeyPressed(KEY_KEY_S))
        move.Z -= 1.f;

      if (receiver.isKeyPressed(KEY_KEY_A))
        move.X -= 1.f;

      if (receiver.isKeyPressed(KEY_KEY_D))
        move.X += 1.f;

      core::vector3df pos( camera->getPosition() );

      // movement is in node coordinate system
      camera->getRelativeTransformation().rotateVect(move);

      const core::vector3df velocity(10.f, 0.f, 30.f); // we can move faster forward than sideways
      pos += (move * (velocity * elapsed));

      camera->setPosition(pos);

      if (driver->beginScene(true, true, video::SColor(255,20,20,20)))
      {
        smgr->drawAll();

        driver->endScene();
      }

      u32 fps = driver->getFPS();
      if (fps != old)
      {
        wchar_t caption[32];
        _snwprintf(caption, 32, L"fps=%u", fps);

        device->setWindowCaption(caption);

        old = fps;
      }
    }
  }

  device->drop();

  return 0;
}
roxaz
Posts: 575
Joined: Tue Jan 23, 2007 8:35 pm
Location: LT

Post by roxaz »

i have 30 fps (framerate limiter), its ok i think. maybe you understood me wrong when i said that movement isnt smooth. just movement is ok, but when i start to move or when i switch moving directory from forward to forward-left lets say, it stops after first movement and then continues to move on.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

but when i start to move or when i switch moving directory from forward to forward-left lets say, it stops after first movement and then continues to move on.
No, it does not. I don't know what you're doing, but using the code I posted above the camera does not stop at all when you switch from holding W to holding W+A [unless you release W].

As I mentioned in my previous posts, starts and stops would be abrupt. This is because the camera doesn't do acceleration to smoothly transition from stopped [no key down] to moving [any WASD key combination] and vice-versa. Of course that can easily be fixed, but I don't really care to add it...

Travis
Post Reply