Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Professional Discussion / ASCII to Scancode

Author
Message
Fluffy Paul
22
Years of Service
User Offline
Joined: 16th Dec 2002
Location: United Kingdom
Posted: 20th Jul 2009 22:40
Hi there.
I've seen a lot of code for converting scancodes to ascii, however I need to do the opposite as I'm trying to read key bindings from an ini file, but I want to convert the keys (specified in letter form e.g. "w") into a scancode for use in the game (e.g. 17).

For a while I used a lookup array so I could map symbols such as "w" or "backspace" in my ini files to scancode values such as 17 and 14. However, I'd rather use the equivalent of this code:



... but in the other direction i.e. ascii to scancode.

This would let my games reliably convert the key bindings in the ini files into the appropriate scancodes for PCs with different keyboard layouts to my own.

Ending a sentence with a French word is so passé
NeX the Fairly Fast Ferret
20
Years of Service
User Offline
Joined: 10th Apr 2005
Location: The Fifth Plane of Oblivion
Posted: 20th Jul 2009 23:12
Hehe, I still have two conversion functions that are literally screenfuls of switch/cases in my older programs.

Fluffy Paul
22
Years of Service
User Offline
Joined: 16th Dec 2002
Location: United Kingdom
Posted: 20th Jul 2009 23:47
I hear you NeX.

I used to have the same thing but currently I use a program to generate a scancode map and then I load it into an array and search it...



I only look stuff up once though - I store the scancode in a variable after that. And I only do the lookups when I load the ini file.

Ending a sentence with a French word is so passé
bobbel
16
Years of Service
User Offline
Joined: 5th Jan 2009
Location: In my DBPro case xD
Posted: 21st Jul 2009 00:22 Edited at: 21st Jul 2009 00:22
Can;t you have one big array, each item contains the ascii code of a letter, like Item num 17 contains the ascii code for "w". that way you can just convert the letter to ascii, loop though the array and when the 2 numbers match, you now what the keystate code is

Oh No, there's too much blood in my caffeine system!
Stack Overflow: Too many pancakes...
The programmer's national anthem is 'AAAAAAAAHHHHHHHH'. -Weinberg, p.152
Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 21st Jul 2009 08:06
Why not create a file which is a list of #constants for all keys? You would only have to create the file once and then include it in any program that needs it.




Mobiius
Valued Member
22
Years of Service
User Offline
Joined: 27th Feb 2003
Location: The Cold North
Posted: 21st Jul 2009 14:21 Edited at: 21st Jul 2009 14:22
Maybe you could convert this little bit of code I wrote for my games...



Good old fashioned hard work and sweat! lol

Your signature has been erased by a mod because it is way too awesome!
Fluffy Paul
22
Years of Service
User Offline
Joined: 16th Dec 2002
Location: United Kingdom
Posted: 21st Jul 2009 16:11 Edited at: 21st Jul 2009 16:12
Thanks Scraggle, Bobbel and Mobiius!
These are all fine solutions, however they don't protect you against your code running on a machine whose keyboard doesn't match your array or constants.



My situation is this: We conviced our boss at work to have a LAN party for a departmental social. His condition was that the software has to be free. So far we've got Quake 3 and Warzone 2100 and a special surprise game. The surprise game is a networked vehicular shooter game I wrote a couple years ago. It works fine on my PC but we have very different keyboards at work. They're not the standard 104/5 key I have at home. This is why I need to be smart with how I convert ascii to scancodes.

I need the program to read a line in my ini file like "FORWARD=W" and then be able to ask the PC it's running on what scancode matches "W", for example. On my PC at home "W" is scancode 17, but there's no guarantee that will be true on the fancy keyboards where I work.

As a last resort I'll run the code in the snippet above and generate a machine-specific keymap and then load the ini file like usual. However - that seems like a step too far. My instinct tells me that, if I can ask User32.dll to convert a scancode to a string value, then I should be able to do it the other way around - give it a string and get a scancode back.

Ending a sentence with a French word is so passé
Diggsey
19
Years of Service
User Offline
Joined: 24th Apr 2006
Location: On this web page.
Posted: 21st Jul 2009 19:32 Edited at: 21st Jul 2009 19:34
Easy



For extra speed, you could sort the KeyCodes array and do a binary search instead of a linear one.

Agent
20
Years of Service
User Offline
Joined: 7th Sep 2004
Location: Sydney, Australia
Posted: 21st Jul 2009 19:49 Edited at: 21st Jul 2009 19:51
Just forum browsing a high speed, but a quick thought occurs to me:

What if you take a scancode() during runtime, then pass the value to a function containing a for..next loop through all 255 characters, asking user32 for the scancode of each ascii character, and when it replies with the scancode() you've sampled, you've got a hit; EXIT the for..next loop and return the value the loop reached - your return value will be the ascii code of the keypress.

That wouldn't require any arrays, tables or external files and would work regardless of keyboard layout, but it won't account for keypresses outside the scope of the ascii table; you'll need a few case specific user32 queries if the for..next loop doesn't hit a match.

Might this logic be good enough for your purposes?

[EDIT]: Looks like Diggsy posted some code following my logic while I was typing this post out
Fluffy Paul
22
Years of Service
User Offline
Joined: 16th Dec 2002
Location: United Kingdom
Posted: 21st Jul 2009 22:02 Edited at: 21st Jul 2009 22:41
How the game works is that it loads the ini file with all the user's key definitions thus:



(Don't worry about the strafe and turn keys - vehicles only do one or the other. Turn keys are almost always used when there's a mouse-controlled turret)

When I load the ini file I do a lookup using something akin to what Diggsey provided and then store the value in variables with strikingly similar names!



And then in the game I check for:



This avoids checking the array every time the player presses a key.

Thanks for all your input, guys. I'm kinda glad to see I've not missed something obvious!

Ending a sentence with a French word is so passé
Grog Grueslayer
Valued Member
19
Years of Service
User Offline
Joined: 30th May 2005
Playing: Green Hell
Posted: 22nd Jul 2009 00:07 Edited at: 22nd Jul 2009 00:08
If you really don't know what keyboard the program is going to work with why not just get the scancode when the program runs (as Agent said). You don't have to get the entire keyboard though... just the keys they need for the game. You don't even need to know what keys they are. When the program runs for the first time ask what keys to use and save those in a file... when it's ran again just load the old values.



Fluffy Paul
22
Years of Service
User Offline
Joined: 16th Dec 2002
Location: United Kingdom
Posted: 22nd Jul 2009 01:20 Edited at: 22nd Jul 2009 01:24
Hi Grog,
I read somewhere that people can only remember an average of seven new things at a time, so I think your way is good if there are seven or less keys to define.

I know for my game it would be impractical as I have lots of different things the user can do in different control modes. In my game you have an RTS view and you can also control individual units (like in Dungeon Keeper, if you remember that?) and you can use the same keys to do different things.

I say that, but that only applies to asking the user to define keys when the game starts. If they want to redefine their keys in-game then your way is pretty much *THE* way to do it (with maybe them picking an action like "forward") - and then I'd save their choices in my ini file as "forward=w" or something.

It's really important to me that the ini file is human readable, hence I'm not saving scancodes in it.

Ending a sentence with a French word is so passé
Grog Grueslayer
Valued Member
19
Years of Service
User Offline
Joined: 30th May 2005
Playing: Green Hell
Posted: 22nd Jul 2009 08:19
Quote: "I read somewhere that people can only remember an average of seven new things at a time, so I think your way is good if there are seven or less keys to define."


Yeah I heard that too but you could also give them recommendations on what keys they should be picking (like the w key for forward). It's no problem to make it grab the actual text of the key pressed so you can make the save file user friendly... but to do it right the scancode must also be saved... which probably defeats the purpose of allowing users to edit the ini file. Me, I'd just not let them modify the file used to save the keys and make a key selection menu in the game. Sometimes it's better to keep the users away from modifying any files via notepad.

The following is a modified version of my code above that uses a UDT instead and adds defining mouse clicks or keys. With the mouse it makes the key code a negative number of MOUSECLICK() and checks if the code is a negative number and if MOUSECLICK() equals the ABS() of the code in the array.



Fluffy Paul
22
Years of Service
User Offline
Joined: 16th Dec 2002
Location: United Kingdom
Posted: 23rd Jul 2009 00:24
Grog, I think you've got a handle on how to ask a user for keys but I don't think I could do that to people when they start up...

However - maybe a tutorial level where users are shown what the controls are and then asked if they're happy with them might be the way to go. But maybe in a later version of the game...

For this version I need to remember that my target audience will never have seen my game before, but they won't have much time to play it (compared to a commercial game they might have bought), so I need to use familiar things like "WASD keys" and "left click to shoot/select units" in order to reduce the time they spend learning it.

I feel a tangent into user interfaces and game experiences coming on!

Must... be... strong...

Ending a sentence with a French word is so passé
Grog Grueslayer
Valued Member
19
Years of Service
User Offline
Joined: 30th May 2005
Playing: Green Hell
Posted: 23rd Jul 2009 05:20
Quote: "Grog, I think you've got a handle on how to ask a user for keys but I don't think I could do that to people when they start up..."


Yeah it would be annoying to see that every time a person would run the program. Well... ideally it would be ran once if the key file doesn't exist then it's created with the keys they selected... so the next time it's ran it'll just load the key file.

Quote: "For this version I need to remember that my target audience will never have seen my game before, but they won't have much time to play it (compared to a commercial game they might have bought), so I need to use familiar things like "WASD keys" and "left click to shoot/select units" in order to reduce the time they spend learning it."


Yeah it makes it easier to use standard keys so 99% of people are used to the controls already. I just recently found one of the 1% that didn't know about the WASD keys. A friend of mines new boyfriend that had never played a FPS on a computer before. But it didn't take him long to get used to using the WASD keys.

Quote: "I feel a tangent into user interfaces and game experiences coming on!

Must... be... strong..."


Hahaha... a new thread in the Game Design Theory base perhaps?

Zuka
17
Years of Service
User Offline
Joined: 21st Apr 2008
Location: They locked me in the insane asylum.
Posted: 23rd Jul 2009 11:17
Try the "entry" command, and clear the entry buffer each frame. Then you can go through each character in the entry string. I guess.
Fluffy Paul
22
Years of Service
User Offline
Joined: 16th Dec 2002
Location: United Kingdom
Posted: 24th Jul 2009 11:33
Hi Zuka,
I've found entry$() is good for capturing text, like if players were typing into the in-game chat. However, I'm talking more about controlling an avatar, which is less about the keyboard buttons as text and more about them being buttons, like a massive, overcomplicated control pad.

In theory entry$() wouldn't perform much different to inkey$(). The problem with using inkey$() for control is that it only picks up one keypress at a time.

This means if you're holding down "W" and "A" because you want to strafe left while running forwards, you will only be doing one of those things.

Only the keystate(<scancode> command can help with that problem.

Ending a sentence with a French word is so passé

Login to post a reply

Server time is: 2025-05-15 18:56:24
Your offset time is: 2025-05-15 18:56:24