SFML community forums

Bindings - other languages => DotNet => Topic started by: Lamonte on September 04, 2013, 09:09:12 pm

Title: Capturing keypresses every frame
Post by: Lamonte on September 04, 2013, 09:09:12 pm
I had issues using the win.keypressed window event handler so I found a post that said if I wanted to capture keypresses every frame I would need to use Keyboard.IsKeypressed() which works wonderfully, except Laurent said in a post I randomly stumbled upon that you shouldn't use this because it executes even if the window isn't focused.

Is there a work around to this?  Because I couldn't previously get the window key events to work how I wanted as it didn't want to capture when the key was being held down, I was forced to press down everytime to do what I wanted.  Which didn't make sense.

Hope I explained everything correctly.  Basically I'm looking for a way to disable the keyboard.iskeypressed when the window isn't focused or if there is a better way to use window keyboard events that captures when you hold down on the key properly because win.SetKeyRepeatEnabled(true); doesn't help the situation.
Title: AW: Capturing keypresses every frame
Post by: eXpl0it3r on September 04, 2013, 09:36:35 pm
You should simply track the GainedFocus and LostFocus event and only process the keyboard inputs if there's a focus.
Title: Re: Capturing keypresses every frame
Post by: Lamonte on September 04, 2013, 10:26:06 pm
Thanks, works nicely.

            //check window focus
            win.GainedFocus += (s, e) => focused = true;
            win.LostFocus   += (s, e) => focused = false;
Title: Re: Capturing keypresses every frame
Post by: Lamonte on September 04, 2013, 10:36:26 pm
Actually this is weird as hell.  When you load the application the window should automatically gain a focus state, but it doesn't.  So you have to focus, unfocus and refocus before it actually checks the event? uh?


                bool focused = true; //could be set to false as well
       
            //setup window
            RenderWindow win = new RenderWindow(new VideoMode((uint) width, (uint) height), title);
           
            //check window focus
            win.GainedFocus += (s, e) => focused = true;
            win.LostFocus   += (s, e) => focused = false;

            //setup frames
            win.SetFramerateLimit(60);

            while (win.IsOpen())
            {
                win.DispatchEvents();

                //... <snipped> ...//
            }
Title: Re: Capturing keypresses every frame
Post by: Laurent on September 04, 2013, 10:47:03 pm
A workaround to a workaround is often worse. Let's rather solve the initial problem:

Quote
I had issues using the win.keypressed window event handler

... which issues?
Title: Re: Capturing keypresses every frame
Post by: Lamonte on September 04, 2013, 11:09:11 pm
A workaround to a workaround is often worse. Let's rather solve the initial problem:

Quote
I had issues using the win.keypressed window event handler

... which issues?

My keypresses didn't trigger every frame when holding the key down, even with the set key repeat option set to true.  Making wasd movement silly as mentioned in the op.
Title: Re: Capturing keypresses every frame
Post by: G. on September 05, 2013, 12:12:47 am
Was you code inside the event checking loop?
Title: Re: Capturing keypresses every frame
Post by: Lamonte on September 05, 2013, 12:56:55 am
Was you code inside the event checking loop?

My current code passes a function to the window loop which checks the movement of the player eg.:

                        if(Keyboard.IsKeyPressed(Keyboard.Key.W)) {
                                y -= speed;
                        }

                        if(Keyboard.IsKeyPressed(Keyboard.Key.S)) {
                                y += speed;
                        }

You kind of get the point, well it was similar except it used the window.KeyPressed += EventHandler<KeyEventArgs>(myfunctionhere);

And the code was similar, don't have the original code anymore
if(e.Code == Keyboard.Key.W) {
        ...
}

Difference is the code wasn't much different in body, but the way it interacted was completed different.  I could hold down WASD and it would stay going in the direction I wanted my sprite to go until I let go of the key.  Using the event handler thing only executed once until i let go and pressed it again.  So basically spamming the button to move the sprite anywhere.  Like I said in previous posts, I had win.SetKeyRepeatEnabled(true); set and it gave the same effect.  It just didn't work as I intended it to.  I needed my sprite to move by frame, funny how much different the C# binding is from C++
Title: Re: Capturing keypresses every frame
Post by: zsbzsb on September 05, 2013, 03:20:20 am
Was you code inside the event checking loop?

In the .NET bindings there is no "event loop" like your used to in plain C++ SFML.

Difference is the code wasn't much different in body, but the way it interacted was completed different.  I could hold down WASD and it would stay going in the direction I wanted my sprite to go until I let go of the key.  Using the event handler thing only executed once until i let go and pressed it again.  So basically spamming the button to move the sprite anywhere.  Like I said in previous posts, I had win.SetKeyRepeatEnabled(true); set and it gave the same effect.  It just didn't work as I intended it to.  I needed my sprite to move by frame, funny how much different the C# binding is from C++

You are way over complicating something simple. Handle the key pressed and key released events like you were. Disable the key repeating (RenderWindow.SetKeyRepeatEnabled(false) and add a boolean flag to your class to determine if a key is pressed or not. Do something like this (not written in IDE - don't copy paste)...

class KeyPressExample
{
   private bool _uppressed = false;
   private void KeyPressed(object sender, KeyEventArgs e)
   {
       if (e.Key == Key.W)
      {
         _uppressed = true;
      }
   }
   private void KeyReleased(object sender, KeyEventArgs e)
   {
       if (e.Key == Key.W)
      {
         _uppressed = false;
      }
   }
   public void GameLoop()
   {
      win.DispatchEvents();
      if (_uppressed)
      {
         //Move Sprite
         //Remember delta time
      }
      win.Clear();
      //Draw Sprite
      win.Display();
   }
}
 

By the way this is the "correct" way to do this. Even in the C++ examples of the SFML Game Development book there is a boolean flag that is set from the C++ event loop to determine if the player is to move or not.
Title: Re: Capturing keypresses every frame
Post by: Lamonte on September 05, 2013, 04:22:36 am
Alright that worked, I guess my last question would now be why does the SFML window not refocus when you click inside the window, but only when clicking the window bar?
Title: Re: Capturing keypresses every frame
Post by: zsbzsb on September 05, 2013, 04:38:52 am
Alright that worked, I guess my last question would now be why does the SFML window not refocus when you click inside the window, but only when clicking the window bar?

This is a bug that was unintentionally introduced in SFML 2.1 as a fix to another bug.
Title: Re: Capturing keypresses every frame
Post by: Lamonte on September 05, 2013, 04:51:02 am
Alright that worked, I guess my last question would now be why does the SFML window not refocus when you click inside the window, but only when clicking the window bar?

This is a bug that was unintentionally introduced in SFML 2.1 as a fix to another bug.

Ah okay, thanks for the info.  Is there a place I can find a list of bugs for the current version?
Title: Re: Capturing keypresses every frame
Post by: Ixrec on September 05, 2013, 07:12:21 am
https://github.com/SFML/SFML/issues?milestone=8&state=open is probably the closest there is to an official bug list

The bug you were asking about is issue #437.