• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Check if an array exists/has been defined

I'm currently working on key bindings for the controls in my game.

It works fine, and I allow the player to bind most keys, but there's some keys I don't want to be binded (windows key, scroll lock, etc.)

I have a huge list of what each key's keycode translates to, which is stored in an array. Here's a short snippet:
Code:
t_key[37] = "LEFT"
t_key[38] = "UP"
t_key[39] = "RIGHT"
t_key[40] = "DOWN"
I want to add an extra check before a key can be binded that makes sure the array with that keycode exists, and if it doesn't, then to deny the player that key binding. So lets say the keycode for some key is 41, but there's no t_key[41] anywhere... I would want the script to check for that. I tried using is_undefined:
Code:
if !is_undefined(t_key[keyboard_lastkey]){
//insert key binding code here
}
But this isn't working, I just get an error saying the array is out of range. Is there any way to check if an array/variable has been set/exists?
 

2Dcube

Member
I'm not sure if there is.
You could check the length of the array with array_length_1d()
to make sure you aren't out of range.
For example
Code:
if keyboard_lastkey < array_length_1d(t_key) && !is_undefined(t_key[keyboard_lastkey]) {
 // code
}
No idea if the is_undefined works even on array checks within range, but worth a try?
To be honest it seems a bit cumbersome. You could also use a list or maps.
Maps: you can add extra data to each key if you want and checking for undefined works.
Lists: you won't have any "gaps".
 
I'm not sure if there is.
You could check the length of the array with array_length_1d()
to make sure you aren't out of range.
For example
Code:
if keyboard_lastkey < array_length_1d(t_key) && !is_undefined(t_key[keyboard_lastkey]) {
 // code
}
No idea if the is_undefined works even on array checks within range, but worth a try?
To be honest it seems a bit cumbersome. You could also use a list or maps.
Maps: you can add extra data to each key if you want and checking for undefined works.
Lists: you won't have any "gaps".
How would you go about using a map/list? I don't know how to do those.
 

TheouAegis

Member
That's a pretty big, pointless array. It also only applies to specific keyboards, too (not that big of an issue if you have localization patches, though). Just do it all algebraically. If the keycode is within one range, subtract the min of that range and look up the keycode in a small a=ay for that range. If the keycode is an existing string, justs the string. ...That right there would free up 40 or 50 entries.
 

2Dcube

Member
List
Code:
keys = ds_list_create(); // create a new list called "keys"

// add things to the list
ds_list_add(keys,
"LEFT",
"UP",
"RIGHT",
"DOWN");

if ds_list_find_index(keys, keyboard_lastkey) != -1 // check if keyboard_lastkey exists within the list
{
  // key binding code
}
To access a specific key you can use
Code:
key[| 0] // for the first (returns LEFT)
key[| 1] // for the second, etc


Map
Code:
keys= ds_map_create(); // create a new map called "keys"

// add each key and give it a value (this is how a map is used, not sure if you need the value, but if you do it can be useful)
keys[? "LEFT"] = 180;
keys[? "UP"] = 90;
keys[? "RIGHT"] = 0;
keys[? "DOWN"] = 270;

if ds_map_exists(keys, keyboard_lastkey)
{
  // key binding code
}
To access a specific key
Code:
keys[? "LEFT"] // returns 180
 
List
Code:
keys = ds_list_create(); // create a new list called "keys"

// add things to the list
ds_list_add(keys,
"LEFT",
"UP",
"RIGHT",
"DOWN");

if ds_list_find_index(keys, keyboard_lastkey) != -1 // check if keyboard_lastkey exists within the list
{
  // key binding code
}
To access a specific key you can use
Code:
key[| 0] // for the first (returns LEFT)
key[| 1] // for the second, etc
I implemented this, but instead of the key names themselves, I added their codes as the list values. It seems to be working fine for all unavailable keys.. except the left window key. The right window key isn't binded, which is correct, but if I press the left window key, it's binding the key as NO VALUE (i.e. Up = [ ] vs. Up = [W])

According to a keycode site, the windows key is 91, and I've made sure not to include that in the list, so I don't know why it's not working for the left window key but it is for the right.
 
Code:
if ds_map_exists(keys, keyboard_lastkey)
{
  // key binding code
}
That won't work. keyboard_lastkey doesn't return the string "LEFT" or anything like that, it returns a number (i.e. 38 or whatever the char value for that specific key is), so you would be checking if a stringed number key exists in the map, when only "LEFT", "RIGHT" strings exist, so it would never return true. Also, it doesn't seem like they are saving the directional values of the keys (i.e. "LEFT" = 0), but rather the ascii code value for the key (which, btw, should not be hard-coded as I believe different OS's can return different values for those keys that aren't letters or numbers, though I'm not entirely sure how GM handles this). So keys[? string(vk_left)] = "LEFT"; would both allow you to check for the map entry existing (ds_map_exists(keys,string(vk_left)) would return true and also get the string you want that key to stand for (i.e. draw_text(x,y,keys[? string(vk_left)]) would draw "LEFT").

However, you might have problems if you actually WANT to grab the ascii value instead of the text value from the map (you would have to loop through the map, which is particularly slow in comparison to list/array loops, though depending on how often you're accessing it, might not be a problem at all), in which case it might be better to store entries as keys[? "LEFT"] = vk_left, etc, and then use ds_map_exists(keys,"LEFT") to check if that entry exists and then keys[? "LEFT"] will return the ascii code for the key that is assigned to "LEFT". It all kinda depends on what functionality you want from the system.
 

2Dcube

Member
keyboard_lastkey doesn't return the string "LEFT" or anything like that, it returns a number
I see, I didn't realize it's a default variable.

Using maps the below would work nicely similar to the array then:
Code:
keys = ds_map_create(); // create a new map called "keys"

// add each key value with its name
keys[? 37] = "LEFT";
keys[? 38] = "UP";
keys[? 39] = "RIGHT";
keys[? 40] = "DOWN;

if ds_map_exists(keys, keyboard_lastkey)
{
  show_debug_message(keys[? keyboard_lastkey]); // would show LEFT, UP, RIGHT or DOWN
  // key binding code
}
 
Top