How to stop the IrrlichtDevice properly?

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
ayman
Posts: 51
Joined: Sat Feb 05, 2005 7:33 pm
Location: Piefke State

How to stop the IrrlichtDevice properly?

Post by ayman »

Hi.

I want to stop the IrrlichtDevice, so that device->run() will result to false.
And I want to do this as a reaction of a key event.

EDIT: I tried the following inside the Example 04 (Movement).

I tried:

Code: Select all

...
class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(SEvent event)
	{
          ...
			switch(event.KeyInput.Key)
			{
			case KEY_KEY_Q: 
				device->closeDevice();   // <-- this is the line
				break;
...
... but this caused a crash.

Naturally device->drop(); resulted in an other crash. That was no surprise.

So, what's the trick?

Thanks in front.
Ayman

P.S.
I did search the forum, but didn't find an answer.
Last edited by ayman on Tue Mar 27, 2007 8:00 pm, edited 1 time in total.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

You did not find an answer because closeDevice() should not cause it to crash. Something else is probably wrong, what does your application contain?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The problem is that device is an unvalid pointer.
ayman
Posts: 51
Joined: Sat Feb 05, 2005 7:33 pm
Location: Piefke State

Post by ayman »

Thanks for telling me that, BlindSide.
But the problem remains the same. I just tried it with the original Movement Example 04.
I added only the three lines as mentioned above and I get a crash every time I hit "Q"-Key.

Code: Select all

...
		if (node != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT&&
			!event.KeyInput.PressedDown)
		{
			switch(event.KeyInput.Key)
			{
			case KEY_KEY_Q: 				// added these three lines
				device->closeDevice();   // causes a crash. why?
				return true; 				// return false; crashes just the same. What does it do anyhow?

			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;
			}
		}
...
Maybe it has something to do with my Dev-Cpp settings? But I can compile and run every example without any problems (using Irrlicht 1.3 with OpenGL or any Software Renderer; DX doesn't work with Dev-Cpp).
Also if I terminate with Alt+F4, every thing is ok.

Would anybody care trying to add these three lines to example-04 and see himself?

Thanks in front.
Ayman
ayman
Posts: 51
Joined: Sat Feb 05, 2005 7:33 pm
Location: Piefke State

Post by ayman »

hybrid wrote:The problem is that device is an unvalid pointer.
Yes, that's what I thought too.

But it shouldn't, should it? Cause device is global and get's initialized right in the beginning. Same is with "node", that is used without a problem four lines below.

So if device can not be used here, how should I handle a termination key stroke?

Regards
Ayman
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Maybe the problem is within your main loop...
please show it to us, too... ;)
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Works fine for me. You are probably making the classic mistake of naming a global variable the same as a local variable, like this...

Code: Select all

IrrlichtDevice* device = 0;

int main()
{
  IrrlichtDevice* device = createDevice(...);

  //...
If you do this, the global device will not get initialized. To avoid problems like this, most people use special notation to indicate the scope of the variable. As an example, you could prepend a g_ to your global variable names. Any variable that is global would have a g_ at the beginning, and anything that is local would not.

Also, this has been mentioned many times before, but you should avoid globals if you can. The following would be a better way to do the same thing without using a global device pointer.

Code: Select all

class MyEventReceiver : public IEventReceiver
{
public:
  MyEventReceiver()
    : Device(0)
  {
  }

  virtual bool OnEvent(SEvent event)
  {
    if (event.EventType == irr::EET_KEY_INPUT_EVENT &&
        event.KeyInput.PressedDown)
    {
      switch(event.KeyInput.Key)
      {
        case KEY_KEY_Q:
          if (Device)
            Device->closeDevice();
          Device = 0;
          return true;

        default:
          return false;
      }
    }

    return false;
  }

  void setDevice(IrrlichtDevice* device)
  {
    if (Device)
      Device->setEventReceiver(0);

    Device = device;

    if (Device)
      Device->setEventReceiver(this);
  }

private:
  IrrlichtDevice* Device;
};

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

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

  MyEventReceiver receiver;
  receiver.setDevice(device);
Travis
ayman
Posts: 51
Joined: Sat Feb 05, 2005 7:33 pm
Location: Piefke State

Post by ayman »

Thanks vitek/Travis!
That's it indeed. It works now :D

But I still have one related question:
Why is the value of "node" available in receiver.OnEvent() then?

I am still talking about the original examples/04.Movement.

"node" is initialized just the same as device:

Code: Select all

scene::ISceneNode* node = 0;
IrrlichtDevice* device = 0;
When the receiver is created ...

Code: Select all

	MyEventReceiver receiver;
... neither "node" is passed as an argument nor it is set to a local "node" variable by a setNode() method.

Shouldn't the same problem apply to node as it applies to device?

Best Regards
Ayman
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

node is set inside main(), but it does not declare a new variable. It uses the global variable for storing the value. That's no clean code, but it keeps the tutorials small (and the tutorials are for showing Irrlicht features, not for teaching good C++ style).
Post Reply