Howdy - New To IRRLICHT, KBoard question

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
Phonica
Posts: 3
Joined: Wed Mar 17, 2004 10:21 pm
Location: England
Contact:

Howdy - New To IRRLICHT, KBoard question

Post by Phonica »

Hi everyone, ive just been having a look at this engine and im very impressed with it compared to the other engines ive used. :)

However, it is unclear from any of the samples how to check the keyboard? All im trying to do atm is check for the escape key :) Thankyou

Michael
AMD Athlon XP 1900 (1600mhz), 512MB Ram 55GB HDD, Mandrake Linux 9.1, Windows 2000, NVidia GeForce 2 Ti 64MB.

OpenGL ATW!
kakTuZ
Posts: 12
Joined: Sun Mar 14, 2004 7:28 pm
Location: Hannover (Germany)

Post by kakTuZ »

This code is from example #4 Movement

Code: Select all

/*
To get events like mouse and keyboard input, or GUI events like 
"the OK button has been clicked", we need an object wich is derived from the 
IEventReceiver object. There is only one method to override: OnEvent. 
This method will be called by the engine when an event happened. 
We will use this input to move the scene node with the keys W and S.
*/
class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(SEvent event)
	{
		/*
		If the key 'W' or 'S' was left up, we get the position of the scene node,
		and modify the Y coordinate a little bit. So if you press 'W', the node
		moves up, and if you press 'S' it moves down.
		*/

		if (node != 0 && 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 = node->getPosition();
					v.Y += event.KeyInput.Key == KEY_KEY_W ? 2.0f : -2.0f;
					node->setPosition(v);
				}
				return true;
			}
		}

		return false;
	}
};
Hope this will help.
Oterwise have a look at the documentation and searchfor IEventReceiver.h (headerfile where the SEvent struct is defined) and "irr Namespace Reference" where you can find the enumertion definitions for the Keys

Maxi
Phonica
Posts: 3
Joined: Wed Mar 17, 2004 10:21 pm
Location: England
Contact:

Post by Phonica »

Ive basically got the hang of how it works, but it doesnt :|

Code: Select all

class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(SEvent event)
	{
		/*
			Checking for esc
		*/

		if (node != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT&&
			!event.KeyInput.PressedDown)
		{
			switch(event.KeyInput.Key)
			{
			case KEY_ESCAPE:
				{
					printf("hey");
				}
				return true;
			}
		}

		return false;
	}
};
thats the code for my class. the prog is a console app

Code: Select all

	MyEventReceiver receiver;

	device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(800, 600),
		32, false, false, &receiver);
Compiles O.K. but when i try to run it crashes :|
any ideas?
Mike
AMD Athlon XP 1900 (1600mhz), 512MB Ram 55GB HDD, Mandrake Linux 9.1, Windows 2000, NVidia GeForce 2 Ti 64MB.

OpenGL ATW!
thesmileman
Posts: 360
Joined: Tue Feb 10, 2004 2:20 am
Location: Lubbock, TX

Post by thesmileman »

I am not sure the way it is done in the demos is a very good way to do input handling. I would suggest doing something like this:

define an array for all keys as such:

Code: Select all

//For Key Handling
bool keys[KEY_KEY_CODES_COUNT]; 
Then in the event reciever all you need to do is set the value at the array position of the current event to the value of wether it is pressed down as such:

Code: Select all

class MyEventReceiver : public IEventReceiver {
   public:
      virtual bool OnEvent(SEvent event) {
			if(irrDevice != 0 && irrDevice->getSceneManager()->getActiveCamera()) {
				keys[event.KeyInput.Key] = event.KeyInput.PressedDown; //Store Key input for control of objects and actions
				//Send all other events to camera(Put your camera code here
         }
      }
};
Then in the main event loop(a a function called there) handle the input. This will also let you handle things like the left or right key being pressed down at the same time(or near the same time):

int main() {
if(keys[KEY_KEY_O]){
node->setRotation( paddle1Node->getRotation()+ core::vector3df(0,0,-0.2f));
}
if(keys[KEY_KEY_Q]){
exit(0);
}
//Put the rest of you main event loop code here
}



Also note this is based on someone elses code originally (it may even be identical. It was so long ago I do not remember if I have changeded it). I just don't want someone geting pissed at me.
Guest

Post by Guest »

the problem im having is that trying to set the event handler in the engines init is what actually seems to cause the prog to crash :| (heavy crash) to experiment i had a empty event handler that returned 0; and it still went poo poo shaped.

Heres my complete code. its where ive taken the 2d tutorial and tried playing with it.

Code: Select all

#include <stdio.h>
#include <wchar.h>
#include <irrlicht.h>

using namespace irr;

static video::IVideoDriver* driver;
static IrrlichtDevice *device = 0;
static scene::ISceneNode* node = 0;

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

/*
To get events like mouse and keyboard input, or GUI events like 
"the OK button has been clicked", we need an object wich is derived from the 
IEventReceiver object. There is only one method to override: OnEvent. 
This method will be called by the engine when an event happened. 
We will use this input to move the scene node with the keys W and S.
*/
class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(SEvent event)
	{
		/*
			Checking for esc
		

		if (node != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT&&
			!event.KeyInput.PressedDown)
		{
			switch(event.KeyInput.Key)
			{
			case KEY_ESCAPE:
				{
					printf("hey");
				}
				return true;
			}
		}
		*/
		return 0;
	}
};
		
/*
At first, we start up the engine, set a caption, and get a pointer
to the video driver.
*/
int startengine()
{
	MyEventReceiver receiver;

	device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(800, 600),
		32, false, false, &receiver);

	device->setWindowCaption(L"The World");

	driver = device->getVideoDriver();

	return 0;
}

int main()
{
	startengine();

	gui::IGUIFont* font = device->getGUIEnvironment()->getFont("media/font.bmp");

/*
	Everything is prepared, now we can draw everything in the draw loop,
	between the begin scene and end scene calls. In this example, we 
	are just doing 2d graphics, but it would be no problem to mix them
	with 3d graphics. Just try it out, and draw some 3d vertices or set
	up a scene with the scene manager and draw it.
*/
	while(device->run() && driver)
	{
		if (device->isWindowActive())
		{
			u32 time = device->getTimer()->getTime();

			driver->beginScene(true, true, video::SColor(0,0,0,0));

			/*
			Drawing text is really simple. The code should be self explanatory.
			*/

			core::position2d<s32> m = device->getCursorControl()->getPosition(); // get the mouse position

			// draw some text
			if (font)
			font->draw(L"This is a test.", 
				core::rect<s32>(m.X,m.Y,m.X+270,m.X+50),
				video::SColor(255,255,255,255));


			// draw transparent rect under cursor
			driver->draw2DRectangle(video::SColor(100,255,255,255),
				core::rect<s32>(m.X, m.Y, m.X+16, m.Y+16));

			driver->endScene();
		}
	}

	/*
	That's all, it was not really difficult, I hope.
	*/

	device->drop();

	return 0;
}
When i compile and run, i get an access violation error :s

pls note that some code has been commented out :)
Tx

Mike
AndyH
Posts: 2
Joined: Tue Mar 30, 2004 1:55 pm
Location: UK
Contact:

Post by AndyH »

Wish we'd seen this sooner, might have saved us some leg work. I went through the same thing, made a boolean array in the same way as the code above but had odd crashes. I also wanted to be able to detect an initial keypress as well as key down. The way I found that seems 100% stable and does all this can be found below. Using an array of bytes now instead to store statuses.

Code: Select all

class MyEventReceiver : public IEventReceiver
{
    u8 keys[KEY_KEY_CODES_COUNT];

public:

    virtual bool OnEvent(SEvent event)
    { 
    	if (event.EventType == irr::EET_KEY_INPUT_EVENT)	
				if (event.KeyInput.PressedDown && keys[event.KeyInput.Key]==0 ) {
					keys[event.KeyInput.Key]=1;
				}
				if (!event.KeyInput.PressedDown && keys[event.KeyInput.Key]!=0) {
					keys[event.KeyInput.Key]=0;
				}	
			return true;
    }
    
    bool isKeyDown(u8 keycode) {
        if (keys[keycode]!=0)
                return true;
        return false;
    }
    bool isKeyPressed(u8 keycode) {
        if (keys[keycode]==1) {
                keys[keycode]=2;
                return true;
        }
        return false;
    } 
    
    void resetKeyboard(void) {
        int i;
        // set initial keystates to false
        for (i=0; i<KEY_KEY_CODES_COUNT; i++)
                keys[i]=0;
    }
};
In the class itself. Do the resetKeyboard first then can do something like: if (receiver.isKeyDown(KEY_KEY_P)) or if (receiver.isKeyPressed(KEY_KEY_P))
AndyH
Freeware games
http://www.ovine.net
rincewind
Posts: 35
Joined: Thu Mar 25, 2004 5:28 pm
Location: Germany --> Bonn

Post by rincewind »

Anonymous wrote:the problem im having is that trying to set the event handler in the engines init is what actually seems to cause the prog to crash :| (heavy crash) to experiment i had a empty event handler that returned 0; and it still went poo poo shaped.

Heres my complete code. its where ive taken the 2d tutorial and tried playing with it.

Code: Select all


(...)

int startengine()
{
	MyEventReceiver receiver;

	device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(800, 600),
		32, false, false, &receiver);

	device->setWindowCaption(L"The World");

	driver = device->getVideoDriver();

	return 0;
}

int main()
{
	startengine();

	gui::IGUIFont* font = device->getGUIEnvironment()->getFont("media/font.bmp");
well, i think the problem is, that your eventreceiver only exists in the scope
of your startengine()-function. After returning from this function, the instance of MyEventReceiver exists no more, and so you run into problems when trying to receive events with it.
One thing you can do, is to hold a pointer to MyEventReceiver in a global variable, create an instance of MyEventReceiver in your startengine-function with new and assign it to your pointer.

greetings, rincewind
AndyH
Posts: 2
Joined: Tue Mar 30, 2004 1:55 pm
Location: UK
Contact:

Post by AndyH »

Ah yes, we are creating our MyEventReceiver in the main function as in the tutorials on the Irrlicht site demonstrate so we don't get crashes due to the scope being lost. I am not certain what was the exact cause of the crashing problems we had at first, but it might have been to do with testing event.KeyInput.PressedDown before we were sure the event received was a keyboard event. We used to get crashes if you moved the mouse a lot but the code I posted above has so far proven to be stable for us.
AndyH
Freeware games
http://www.ovine.net
Post Reply