Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [SOLVED] Input handling: detect holding two keys  (Read 11102 times)

0 Members and 1 Guest are viewing this topic.

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
[SOLVED] Input handling: detect holding two keys
« on: October 08, 2014, 10:27:25 am »
Hi, since I introduced diagonal movement to my game, I encountered problems while detecting. Input handling works currently this way: The mainloop forwards the sf::Event (if type is KeyPressed or KeyReleased) to the GameObject's input component. At this component, I store this press/release in a (as map<Key, State>). On each cycle, my component is updated to move all previously pressed keys to currently hold - and previously released keys to currently "free" keys.

This system works great, unless one fact: When querying my input component, all predefined keys (the bindings for left,right,up,down and some additional ones - doesn't matter here) are checked. Key detection works this way:

if (keys.at(binding.up) == PRESS || keys.at(binding.up) == HOLD) {
    move.y = -1;
}
Left, down and right are handled in the same way. So the move var (btw sf::Vector2i) finally has values such es (0,1), (-1,1) etc. This works well, IF the keys are pressed EXACTLY at the same time. But often pressing A and W (as left and up) doesn't happen at the same time, because the program is even faster than the user.

Well, so I started delaying each of those queries to the input state for some milliseconds (so they aren't queried on each frame if a user is allowed to). But the effect isn't that great: Sometimes the movement looks delayed to the player (because of the delay ;D ) - and sometimes the previous effect (first walk left, than diagonally left-up) occures (because the up-key is pressed slitely after the first query).

What am I doing wrong referring to my input design? :-\

BTW: The first "left-only" movement is completly executed, because my systems avoids query input while an action (walking to the left tile) isn't completed. This system achieves some kind of discrete movement and simplifies collision detection etc.
« Last Edit: January 26, 2015, 08:26:30 pm by Glocke »
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: Input handling: detect holding two keys
« Reply #1 on: October 08, 2014, 11:24:19 am »
It's quite hard to understand how your system works in full details, but what if you just check for the hold status?

if (keys.at(binding.up) == HOLD && keys.at(binding.down) == HOLD) {
    move.y = 0;
}
else if (keys.at(binding.up) == HOLD) {
    move.y = -1;
}
else if (keys.at(binding.down) == HOLD) {
    move.y = 1;
}


if (keys.at(binding.right) == HOLD && keys.at(binding.left) == HOLD) {
    move.x = 0;
}
else if (keys.at(binding.left) == HOLD) {
    move.x = -1;
}
else if (keys.at(binding.right) == HOLD) {
    move.x = 1;
}
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: Input handling: detect holding two keys
« Reply #2 on: October 08, 2014, 11:38:03 am »
I tried this, but this just moved the problem. It's the same whether I check "W pressed|held & A pressed|held" as I check "W held & A held".

Because:
  • First case (press|held): if one button wasn't detected as pressed or held, there will be no diagonal movement
  • Second case (held only): if one button wasn't detected as held yet (so it might be pressed previously), there will be no diagonal movement

I guess the problem is about my "don't query again unless the action has been finished". Without this, the system could correct the movement direction duration the next frame (I'm currently working on this while keeping my discrete movement style).
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: Input handling: detect holding two keys
« Reply #3 on: October 08, 2014, 11:41:37 am »
I guess the problem is about my "don't query again unless the action has been finished".
Not sure what that means, but it sounds wrong. You should process all events every frame.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: Input handling: detect holding two keys
« Reply #4 on: October 08, 2014, 11:54:36 am »
Not sure what that means, but it sounds wrong. You should process all events every frame.

On each action (move, attack etc.) a cooldown is set. If this cooldown is zero, the action is finished and another action can be applied. This systems prevents the physics from changing the moving direction while moving. But exactly that change would fix my problem. Unfortunately, when avoiding this, my collision detecting is broken (but easy to fix).. but the rendering is randomly flickering while moving... Well, currently I'm trying to fix that ^^
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Input handling: detect holding two keys
« Reply #5 on: October 08, 2014, 12:08:46 pm »
You shouldn't mix input and game logic. Use a vector to store the input, pass it to a game logic routine, and check there whether it is applicable. Or adjust it where needed.

Same for collision detection. When there is a collision, don't change the input vector. Rather, introduce a separate additional force that prevents the player from running into the wall.

By the way, my Thor.Actions would simplify boolean combinations of multiple keys a lot.
« Last Edit: October 08, 2014, 12:10:54 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: Input handling: detect holding two keys
« Reply #6 on: October 08, 2014, 12:18:54 pm »
You shouldn't mix input and game logic. Use a vector to store the input, pass it to a game logic routine, and check there whether it is applicable. Or adjust it where needed.

Exactly that, what came to my mind before opening the thread :D [/quote]

Waiting for another key to be pressed (to achieve a diagonal movement) is a pure input-based application. So I'm going to delay a predefined number of milliseconds for waiting for another key. If an additional key was pressed - or the time elapsed - the movement will be forwarded to the game logic.. That's my current idea.
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Input handling: detect holding two keys
« Reply #7 on: October 08, 2014, 12:23:15 pm »
Elapsed time and cooldowns is clearly a game logic feature, so why already handle it at the input stage? There, you are only supposed to catch the pure user input (from arrow keys) and translate it to a game representation (through the key bindings or Thor, if you use it).

And keep things orthogonal. 4 statements are enough to check every key, 1 additional statement can detect and adjust diagonal movement. No need to check all 8 directions...
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: Input handling: detect holding two keys
« Reply #8 on: October 08, 2014, 12:27:51 pm »
Elapsed time and cooldowns is clearly a game logic feature, so why already handle it at the input stage? There, you are only supposed to catch the pure user input (from arrow keys) and translate it to a game representation (through the key bindings or Thor, if you use it).

Waiting for two keys pressed "at the same time" (user point of view) seems to me to be an input task. Game logic is handling the final move event.

And keep things orthogonal. 4 statements are enough to check every key

Well, I just extended by game to 8 directions because 4 were not enough. By the way I'm checking only 4 directions. The diagonal moves take place after e.g. the left key and the up key were checked and returned true. Then the left key will effect "move.x = -1" and the up key will effect "move.y = -1" which means move=(-1,-1).

1 additional statement can detect and adjust diagonal movement. No need to check all 8 directions...

How to detect diagonal movement else?
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Input handling: detect holding two keys
« Reply #9 on: October 08, 2014, 12:29:39 pm »
Waiting for two keys pressed "at the same time" (user point of view) seems to me to be an input task.
Yes, but for that you don't need any clocks and cooldowns...

How to detect diagonal movement else?
See here. You can still separate input and logics, though.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: Input handling: detect holding two keys
« Reply #10 on: October 08, 2014, 12:46:20 pm »
See here. You can still separate input and logics, though.

I guess that's some kind of misunderstanding. I'm querying my input exactly that way.
But sometimes the second's key isn't detected by the system as pressed - because the user isn't as fast as the computer to be able to press really at the same time. So there will be a first left-move followed by left-up :(
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Input handling: detect holding two keys
« Reply #11 on: October 08, 2014, 01:09:16 pm »
Is it tragic if the player moves left for a tenth of a second and then moves diagonally?

That's at least what I would expect as a player. I don't like the input system to meet "smart" decisions for me, if that means I am prevented from being fast. But that may depend on the game...
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: Input handling: detect holding two keys
« Reply #12 on: October 08, 2014, 01:12:56 pm »
Is it tragic if the player moves left for a tenth of a second and then moves diagonally?

As mentioned before: I intend discrete movement. This means the player steps an entire tile left and then an entire tile diagonally.

That's at least what I would expect as a player. I don't like the input system to meet "smart" decisions for me, if that means I am prevented from being fast. But that may depend on the game...

I guess waiting 80-120ms for an additional key is not a problem (at least for me). The input component isn't delay this at once but over some frames (using the given elapsed time from the mainloop). So the game itself isn't slowed down.
« Last Edit: October 08, 2014, 01:14:37 pm by Glocke »
Current project: Racod's Lair - Rogue-inspired Coop Action RPG

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Input handling: detect holding two keys
« Reply #13 on: October 08, 2014, 01:17:16 pm »
Ah, okay, that makes it clear :)

Yes, then I'd probably also handle the delay in the input module. It can then pass one of eight directions to the game logic.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Glocke

  • Sr. Member
  • ****
  • Posts: 289
  • Hobby Dev/GameDev
    • View Profile
Re: Input handling: detect holding two keys
« Reply #14 on: October 08, 2014, 01:19:43 pm »
Ah, okay, that makes it clear :)

Yes, then I'd probably also handle the delay in the input module. It can then pass one of eight directions to the game logic.

Ok, fine :) As said: just a case of misunderstanding ;D
Current project: Racod's Lair - Rogue-inspired Coop Action RPG