How fast is the OnEvent receiver?

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
wizard4

How fast is the OnEvent receiver?

Post by wizard4 »

So I am attempting to change the active camera when a key is released. The way is to set KeyDown[KEYS_MAX] to 0 and KeyUp[KEYS_MAX] to 1. The check works well and the virtual Toggle outputs when I release the key.
INPUT_EVENT no longer receives a key input. All the code is happening so fast within the OnEvent method.

I just wondered when to check a value within the Event system?

No, I probably haven't thought it through as much as I should have, but it's good to ask a question from time to time.

..

Code: Select all

class MyEventReceiver : public IEventReceiver
{
public:
    // give input a gui quit button
    MyEventReceiver(Context & c) : context(c) { }


	// This is the one method that we have to implement
	virtual bool OnEvent(const SEvent& event)
	{
		// Remember whether each key is down or up
		if (event.EventType == irr::EET_KEY_INPUT_EVENT)
        {
            KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
            // check here
            // D0 U1 (before event)
            // D1 U1 (line event.KeyInput.PressedDown
            // D1 U0 (line !event.KeyInput.PressedDown
            // D0 U0 (line event.KeyInput.PressedDown
            // D0 U1 (line !event.KeyInput.PressedDown
                                  
            if(KeyIsDown[event.KeyInput.Key] == 0 && KeyIsUp[event.KeyInput.Key] == 0)
                ToggleView();

            KeyIsUp[event.KeyInput.Key] = !event.KeyInput.PressedDown;

            // EVERY key released?
            //KeyIsReleased[event.KeyInput.Key] = 0;
        }

        if(event.EventType == irr::EET_MOUSE_INPUT_EVENT)
        {
            RightMouse = event.MouseInput.isRightPressed();

            mouse_xy.X = event.MouseInput.X;
            mouse_xy.Y = event.MouseInput.Y;
        }

        if(event.MouseInput.Event == EMOUSE_INPUT_EVENT::EMIE_RMOUSE_LEFT_UP)
            RightMouse = false;


		return false;
	}

	// This is used to check whether a key is being held down
	virtual bool IsKeyDown(EKEY_CODE keyCode) const
	{
		return KeyIsDown[keyCode];
	}

	virtual bool IsKeyUp(EKEY_CODE keyCode) const
	{
	    return KeyIsUp[keyCode];
	}


	virtual bool IsRightClick() const
	{
	    return RightMouse;
	}

	virtual bool IsQuit()
	{
	    return context.quit_app;
	}

	virtual core::position2d<s32> getXY()
	{
	    return mouse_xy;
	}

	virtual void ToggleView()
	{
	    context.viewing_cam = !context.viewing_cam;
	    std::cout << "?: " << context.viewing_cam;
	}

	virtual bool getView()
	{
	    return context.viewing_cam;
	}

	// init

	MyEventReceiver()
	{
		for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
			KeyIsDown[i] = false;

        for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
            KeyIsUp[i] = true;
	}

private:
	// We use this array to store the current state of each key
	bool KeyIsDown[KEY_KEY_CODES_COUNT];
	bool KeyIsUp[KEY_KEY_CODES_COUNT];

	bool RightMouse = false;

	int event_tot = 0;
	core::position2d<s32> mouse_xy = {0,0};
	Context context;
};

The calling code is here, but so far it is set to IsKeyDown, which isn't what I want. It does work (sort of) but only when the key is down. I'd like it to trigger when the key is up.

Code: Select all

        if(receiver.IsKeyDown(irr::KEY_KEY_1))
        {
            if(receiver.getView())
            {
                smgr->setActiveCamera(no_camera);
                fps_mention->setText(L"NO FPS");
            }
            else
            {
                smgr->setActiveCamera(camera);
                fps_mention->setText(L"FPS");
            }
        }
        
wizard4

Re: How fast is the OnEvent receiver?

Post by wizard4 »

I realised I'm sending an IsKeyUp on every keystroke now :)
wizard4

Re: How fast is the OnEvent receiver?

Post by wizard4 »

I literally thought a keypress triggers OnEvent. My problem was in the code running at the device->run() level accessing a OnRelease array that only "triggers" and then resets. OnEvent is as fast as it needs to be. It "Events" on an "Event".

Say I checked a triggered array within draw/render in my game loop. I wondered how fast I could check that "1 bit blip"?
wizard4

Re: How fast is the OnEvent receiver?

Post by wizard4 »

I guess an Event only cares about an Event when its happening. The FPS camera stops moving when a key is released. No more events are happening. Is the event system like, encapsulated to events only, and only cares about events? Why would my code in device->run care about inside an event? Event takes care of that?
CuteAlien
Admin
Posts: 10021
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: How fast is the OnEvent receiver?

Post by CuteAlien »

device->run() polls the system events. So every event is passed on to Irrlicht in device->run. So basically you get all events which happened since last frame (or last run call) together once per frame.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
wizard4

Re: How fast is the OnEvent receiver?

Post by wizard4 »

If the last event in OnEvent was an up toggle like my check does (D0U1/D1U1) and only needs OnRelease _at that exact time_, it makes sense now. Events are cool.
wizard4

Re: OnEvent receiver?

Post by wizard4 »

If the Irrlicht engine runs OnEvent each time an event happens (this time an event.EventType == KEY_INPUT_EVENT) that checks KeyInput.PressedDown… Then IsKeyDown[KEY_CODE] is being set to 1 (true). There is no KeyInput.KeyReleased, so how is IsKeyDown being set back to 0? Does MyEventReceiver() {} always get created new each time an event is fired?

The problem I have in my game is changing the active camera from a WASD camera to a non-WASD MouseLookOnly camera. So the camera follows the player like an FPS game until it switches to the MouseLookOnly camera when it reaches the perimeter of a sphere, and when I switch back to the WASD camera, the key I had held down which is no longer held, remembers the key and starts walking off when I want the player still.

I tried a virtual receiverResetKeys that calls IsKeyDown[all of them] = false.

I'd like to reset the key really. Oddly when I hit the key once more it stops the camera moving, or when I click the mouse button, and in the mouse click code I have camera->setInputReceiverEnabled(false)... So I tried calling that but it didn't help.

I guess I'm pausing the WASD movement but want it fresh on the player's next move?
CuteAlien
Admin
Posts: 10021
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: How fast is the OnEvent receiver?

Post by CuteAlien »

You control when and where MyEventReceiver is created and set. Usually you do that only once at start and so there is only one object. But there can be more than one event receiver. And you can switch between them or they can be chained. And the first event receiver which returns "true" prevents an event from being passed on to the next ones. And the camera animators tend to do that (eat the events). So yeah - when you switch to another animator (like set a camera active which comes with an event-receiver) it might be a good idea to set the keys in your old receiver to false. And maybe even check again the key-state when you switch back (no Irrlicht function for that you'd have to use system functions like
GetKeyboardState for that).

If you check the source for CSceneNodeAnimatorCameraFPS you'll notice it has the reset keys when you switch to it in CSceneNodeAnimatorCameraFPS::allKeysUp() which it calls every time isInputReceiverEnabled switches from false to true.

Can't help you with detais - you are on the right track. What exactly goes wrong in your case is hard to tell without me seeing the full code.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
wizard4

Re: How fast is the OnEvent receiver?

Post by wizard4 »

Code: Select all

        // cam
        // keep fixed cam following player until action phase
        if(!a.player_action)
            a.camera_fixed = a.camera->getPosition();
        // always keep the current position
        a.camera_distance_from_fixed = a.camera->getPosition();

        // check distance every loop
        float dist = a.camera_distance_from_fixed.getDistanceFrom(a.camera_fixed);

        // jump forward... this isn't true at the moment


        // when player reaches outer edge halt player, set new cam
        if(dist > 100.f && a.player_action)
        {
            std::cout << "Perimeter reached.\n";

            // copy the camera
            a.halt_camera->setPosition(a.camera->getPosition());
            a.halt_camera->setRotation(a.camera->getRotation());

            a.camera->setInputReceiverEnabled(false);
            a.smgr->setActiveCamera(a.halt_camera);
            a.halt_camera->setInputReceiverEnabled(true);

            fps_mention->setText(L"NO FPS");
            a.player_action = false;

        }

        if(receiver.IsKeyDown(KEY_KEY_2))
        {
            movement_sphere_obj->setPosition(a.camera->getPosition());
            // set where the middle of the sphere is
            a.camera_fixed = a.camera->getPosition();
            a.player_action = true;
        }

        if(receiver.IsKeyDown(KEY_KEY_3))
        {
            // free roam
            a.player_action = false;
            // back to WASD
            a.camera->setPosition(a.halt_camera->getPosition());
            a.camera->setRotation(a.halt_camera->getRotation());

            a.halt_camera->setInputReceiverEnabled(false);
            a.smgr->setActiveCamera(a.camera);
            a.camera->setInputReceiverEnabled(true);

            // deleted a bunch off confusing lines everywhere
            //a.camera->setInputReceiverEnabled(true);
            //a.halt_camera->setInputReceiverEnabled(false);

            fps_mention->setText(L"FPS");
            // no need
            //receiver.receiverResetKeys();
        }
        
Okay, so I kinda had a guide in my head telling me (or was it my intuition?) that my code was overcomplicated and computers only do what you tell it. So I was being dumb and the computer was being dumb. I guess I simplified it lots... but maybe CA was hovering over me?

I got it working. No need to reset anything. Perhaps setActive does the work and I don't need setInputReceiver stuff everywhere.
CuteAlien
Admin
Posts: 10021
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: How fast is the OnEvent receiver?

Post by CuteAlien »

Lol, not hovering around outside games ;-) But good it worked out.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
wizard4

Re: How fast is the OnEvent receiver?

Post by wizard4 »

Well I'm working on it but here is my run loop.

Code: Select all

    while(a.device->run() && !receiver.IsQuit())
    {

        // keep fixed cam following player until action phase
        if(!a.player_action)
        {
            a.camera_fixed = a.camera->getPosition();
            // keep the halt camera with the camera
            a.halt_camera->setPosition(a.camera->getPosition());
        }


        // always keep the current position
        a.camera_distance_from_fixed = a.camera->getPosition();
        // check distance every loop
        float dist = a.camera_distance_from_fixed.getDistanceFrom(a.camera_fixed);


        // when player reaches outer edge halt player, set new cam
        if(dist > (100.f * p.movement_int) && a.player_action)
        {
            std::cout << "Perimeter reached.\n";

            // copy the camera
            a.halt_camera->setPosition(a.camera->getPosition());
            a.halt_camera->setRotation(a.camera->getRotation());

            a.camera->setInputReceiverEnabled(false);
            a.smgr->setActiveCamera(a.halt_camera);
            a.halt_camera->setInputReceiverEnabled(true);

            fps_mention->setText(L"NO FPS");
            a.player_action = false;

        }

        if(receiver.IsKeyDown(KEY_KEY_2))
        {
            movement_sphere_obj->setPosition(a.camera->getPosition());
            // set where the middle of the sphere is
            a.camera_fixed = a.camera->getPosition();
            a.player_action = true;
        }

        if(receiver.IsKeyDown(KEY_KEY_3))
        {
            // free roam
            a.player_action = false;
            // back to WASD
            a.camera->setPosition(a.halt_camera->getPosition());
            a.camera->setRotation(a.halt_camera->getRotation());

            a.halt_camera->setInputReceiverEnabled(false);
            a.smgr->setActiveCamera(a.camera);
            a.camera->setInputReceiverEnabled(true);


            fps_mention->setText(L"FPS");
        }


        // no checks for halt camera or camera
        // the camera snapped to a far away position
        // and the RightClick suddenly stopped registering ++p.movement_int code
        // and this made the walking bug come back
        // so I am checking where halt and cam->setPosition()
        // and maybe some logs if the movement_int value is actually changing



		if(receiver.IsRightClick())
        {
            a.device->getCursorControl()->setVisible(true);
            complete_hud->setVisible(true);

            // if I comment this line out right click does not stop the camera
            // so I need this here
            a.camera->setInputReceiverEnabled(false);

            core::position2d<s32> chuck;
            chuck.X = receiver.getXY().X;
            chuck.Y = receiver.getXY().Y;
            scene::ISceneNode * grab2 = collMan->getSceneNodeFromScreenCoordinatesBB(chuck, IDIsHUD);

            if(grab2)
            {
                std::cout << grab2->getName();
            }
        }

/*
                if(receiver.IsLeftUp())
                {
                    c8* conv = "less";

                    if(grab2->getID() == (IDIsHUD | IDIsHUDLess) )
                    {
                        --p.movement_int;
                        if(p.movement_int < 1)
                            p.movement_int = 1;

                        p.movement_amount = p.hudTextItoS(p.movement_int);
                        hud_text->setText(p.movement_amount.c_str());
                        receiver.StopLeftUp();
                    }
                    else if(grab2->getID() == (IDIsHUD | IDIsHUDMore) )
                    {

                        ++p.movement_int;
                        if(p.movement_int > p.action_max)
                            p.movement_int = p.action_max;

                        p.movement_amount = p.hudTextItoS(p.movement_int);
                        hud_text->setText(p.movement_amount.c_str());
                        receiver.StopLeftUp();
                    }
                }
            }

        }
*/
        // I changed this to IsRightUp rather than else IsRightClick
        // runs whenever the HUD isn't showing
        if(receiver->IsRightUp())
        {
            a.device->getCursorControl()->setVisible(false);
            complete_hud->setVisible(false);

            // if I uncomment this line I can't program the HUD to capture the mouse
            // and return focus
            //a.camera->setInputReceiverEnabled(true);
        }

        
        core::vector3df inc_sphere_scale = p.movement_int * p.movement_obj_scale;
        movement_sphere_obj->setScale(inc_sphere_scale);

        
        //
        // scene
        //

        a.driver->beginScene(true, true, video::SColor(0,0,200,200));
        a.smgr->drawAll();
        a.guienv->drawAll();
        a.driver->endScene();

    }
wizard4

Re: How fast is the OnEvent receiver?

Post by wizard4 »

CuteAlien, I thought I'd show you the new villager or guy that's being added to the game. He has a black background because I've literally just added him in, so he's not ready just yet. There probably never is a finished game... so to speak.

Adam in a game!

Also a 1080p video...

HQ version

It would be better if I managed to finish somewhat the game. Lots more is needed. Thank you for the help. Maybe that's why Adam is in there.
Post Reply