Default arrow keys behavior

Make games! Discuss those games here.

Moderators: Bob the Hamster, marionline, SDHawk

Post Reply
lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Default arrow keys behavior

Post by lennyhome »

First of all, this is not about diagonal movement. This only applies when diagonal movement is not allowed and the arrow control have not been re-defined via scripting.

The relevant code is in game.pas at 840:

Code: Select all

   IF carray(ccUse) > 1 [...]
    cancel_hero_pathfinding(0)
   ELSEIF carray(ccUp) > 0 THEN
    herow(0).ygo = 20
    setdir = dirUp
   ELSEIF carray(ccDown) > 0 THEN
    herow(0).ygo = -20
    setdir = dirDown
   ELSEIF carray(ccLeft) > 0 THEN
    herow(0).xgo = 20
    setdir = dirLeft
   ELSEIF carray(ccRight) > 0 THEN
    herow(0).xgo = -20
    setdir = dirRight
   END IF
The UP key is checked first as a result, if it's pressed, no other key is ever really checked and the character will move up. That makes the UP direction somewhat special, but there is no reason for it to be special.

There should be no hard-coded preferred direction. Instead there should be some smarter logic able to choose which arrow key should take priority based upon some context. I believe that's especially important when playing with a joypad.

You can check:
https://github.com/EasyRPG/Player
to see how the arrow keys behave in there. Try pressing UP and LEFT at the same time for example. You'll notice that the direction of movement is chosen depending on which of the two keys is pressed last.

Changing this behavior shouldn't break compatibility with any existing game and I think most people won't even notice except for the fact that the default character controls will feel a little better.
User avatar
Bob the Hamster
Lord of the Slimes
Posts: 7658
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Re: Default arrow keys behavior

Post by Bob the Hamster »

I have no objection to changing this logic.

I guess to implement the logic of prioritizing whichever arrow key was pressed last, we would need to track how long each of them has been held down.
lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Re: Default arrow keys behavior

Post by lennyhome »

Yes. You need to keep track of when an arrow key "became pressed" in addition to its current state. Then the direction to choose is the one that "became pressed" more recently and is still currently pressed.

EDIT:
I've never written anything in FreeBasic and I made no attempt at making it look good but I got it working. I've followed your idea of "pressed time counters" instead of mine of "pressed timestamps". But I'm sure it could be done either way.

It needs work from somebody who actually knows better, but here it goes:

Somewhere in the global scope:

Code: Select all

DIM up_key_counter as integer
DIM down_key_counter as integer
DIM left_key_counter as integer
DIM right_key_counter as integer

DIM best_direction as integer
DIM best_counter as integer
Then somewhere inside the "master loop" before the original if/elseif block:

Code: Select all

  IF carray(ccUp) > 0 THEN
   up_key_counter += 1
  ELSE
   up_key_counter = 0
  END IF
  IF carray(ccDown) > 0 THEN
   down_key_counter += 1
  ELSE
   down_key_counter = 0
  END IF
  IF carray(ccLeft) > 0 THEN
   left_key_counter += 1
  ELSE
   left_key_counter = 0
  END IF
  IF carray(ccRight) > 0 THEN
   right_key_counter += 1
  ELSE
   right_key_counter = 0
  END IF
Next we'll be looking for the counter that has the lowest value but also greater than 0:

Code: Select all

  best_direction = -1
  best_counter = 32767
  
  IF up_key_counter > 0 AND up_key_counter < best_counter THEN
  	best_direction = ccUp
  	best_counter = up_key_counter
  END IF
  IF down_key_counter > 0 AND down_key_counter < best_counter THEN
  	best_direction = ccDown
  	best_counter = down_key_counter
  END IF
  IF left_key_counter > 0 AND left_key_counter < best_counter THEN
  	best_direction = ccLeft
  	best_counter = left_key_counter
  END IF
  IF right_key_counter > 0 AND right_key_counter < best_counter THEN
  	best_direction = ccRight
  	best_counter = right_key_counter
  END IF
And finally the new conditions for the original if/elseif block:

Code: Select all

   ELSEIF best_direction = ccUp THEN
    herow(0).ygo = 20
    setdir = dirUp
   ELSEIF best_direction = ccDown THEN
    herow(0).ygo = -20
    setdir = dirDown
   ELSEIF best_direction = ccLeft THEN
    herow(0).xgo = 20
    setdir = dirLeft
   ELSEIF best_direction = ccRight THEN
    herow(0).xgo = -20
    setdir = dirRight
I've tested it on Vikings a little bit and it seems to work fine.
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Re: Default arrow keys behavior

Post by TMC »

Thanks. Actually just a few days ago I suggested adding a "keypress time" script command to return how long a key has been down, since the engine does track that internally. So I just added that (unsurprisingly it turned out vastly more work than I expected, which was a trivial amount) and corresponding FB function, and I simplified your patch to use that.

It definitely feels nicer.

Unfortunately, this is a compatibility break because it breaks the hero will move and parallax scripts on the wiki if you press multiple arrow keys at once causing some jarring parallax glitches. I know several games use those. Honestly it's my fault for writing those assumption-dense scripts instead of adding that sort of thing as builtin. So although I've applied the patch already I think maybe I should add a backcompat bit to only enable it in new games, which would be unfortunate. Backcompat is tough!
User avatar
Bob the Hamster
Lord of the Slimes
Posts: 7658
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Re: Default arrow keys behavior

Post by Bob the Hamster »

Nice work lennyhome!

Yeah, I guess this might be a case for a backcompat bit...

Logic to search for the presence of the "hero will move" script and default the bit accordingly is possible, but might be overkill :D
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Re: Default arrow keys behavior

Post by TMC »

Actually that's way simpler than the hack I was giving some consideration which was to patch out those scripts! Searching for a script by name is easy enough that I think I'll do that, because in future we may want to do more of that. And I'll just fix and change the name of the offending script on the wiki.
lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Re: Default arrow keys behavior

Post by lennyhome »

If it's possible to re-implement this new controller logic as a script, then maybe it's better to go that route. I proposed a FreeBasic implementation because I thought it would benefit existing games.
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Re: Default arrow keys behavior

Post by TMC »

It's definitely better builtin rather than as a script. It's done, there's a backcompat bit that's turned on only as required. I've got to admit though, even at just a few lines of code it was overkill and I should probably be working on higher priorities.
Post Reply