Legacy GM [SOLVED] keyboard_last_char + Press <any key> event problem

Phoebe Klim

Member
I'm trying to improve spaceship renaming for my game,

I'm using this code to rename in the Press <any key> event:

Code:
if mode_rename == true
{
    if keyboard_lastkey != vk_backspace
    {
        if keyboard_lastkey != vk_enter
        {
            if keyboard_lastkey != vk_shift
            {
                if string_length(ship_name) < 22
                {
                    if keyboard_lastchar != -1
                    {
                        if keyboard_check(vk_shift)
                        {
                        ship_name += string_upper(keyboard_lastchar);
                        }
                        else
                        {
                        ship_name += string_lower(keyboard_lastchar);
                        }
                    
                        keyboard_lastchar = -1;
                        audio_play_sound(snd_button, 1, false);
                    }
                }
                else
                {
                    scr_new_message(_t("error"), _t("name_error"), c_red);
                    
                    keyboard_lastchar = -1;
                    audio_play_sound(snd_error_1, 1, false);
                }
            }
            else
            {
                keyboard_lastchar = -1;
            }
        }
        else
        {
            if ship_name != "" && ship_name != " "
            {
            mode_rename = false;
            scr_achievement_check(18);
        
            keyboard_lastchar = -1;
            audio_play_sound(snd_button,1,false);
            }
            else
            {
            mode_rename = false;
            ship_name = old_ship_name;
        
            keyboard_lastchar = -1;
            audio_play_sound(snd_button,1,false);
            }
        }
    }
    else
    {
    var edit = string_delete(ship_name, string_length(ship_name), 0);
    ship_name = edit;
        
    keyboard_lastchar = -1;
    audio_play_sound(snd_button, 1, false);
    }
}

The problem is that strange things happen when I press Tab, Caps Lock, Ctrl, etc.

How can I prevent non-symbol keys from ruining the name?

I used to have a script that would only allow adding letters to the name, but I don't want to use it anymore, because of localization reasons.

I could also make add a lot if keyboard_lastkey != <key> lines, but some keys don't seem to have built-in variables for them and there are different keyboards.
 

The-any-Key

Member
Press <any key>
You called?

If you want it to work with localization, you need to ignore the ones you don't want.
Instead of a complicated if. Why not use a script and a switch?

Code:
switch (keyboard_lastkey)
{
   case vk_backspace:
   case vk_enter:
   case 32: // Space
   case 9: // Tab
      return "";
}
return keyboard_lastchar
 

jo-thijs

Member
I'm trying to improve spaceship renaming for my game,

I'm using this code to rename in the Press <any key> event:

Code:
if mode_rename == true
{
    if keyboard_lastkey != vk_backspace
    {
        if keyboard_lastkey != vk_enter
        {
            if keyboard_lastkey != vk_shift
            {
                if string_length(ship_name) < 22
                {
                    if keyboard_lastchar != -1
                    {
                        if keyboard_check(vk_shift)
                        {
                        ship_name += string_upper(keyboard_lastchar);
                        }
                        else
                        {
                        ship_name += string_lower(keyboard_lastchar);
                        }
               
                        keyboard_lastchar = -1;
                        audio_play_sound(snd_button, 1, false);
                    }
                }
                else
                {
                    scr_new_message(_t("error"), _t("name_error"), c_red);
               
                    keyboard_lastchar = -1;
                    audio_play_sound(snd_error_1, 1, false);
                }
            }
            else
            {
                keyboard_lastchar = -1;
            }
        }
        else
        {
            if ship_name != "" && ship_name != " "
            {
            mode_rename = false;
            scr_achievement_check(18);
   
            keyboard_lastchar = -1;
            audio_play_sound(snd_button,1,false);
            }
            else
            {
            mode_rename = false;
            ship_name = old_ship_name;
   
            keyboard_lastchar = -1;
            audio_play_sound(snd_button,1,false);
            }
        }
    }
    else
    {
    var edit = string_delete(ship_name, string_length(ship_name), 0);
    ship_name = edit;
   
    keyboard_lastchar = -1;
    audio_play_sound(snd_button, 1, false);
    }
}

The problem is that strange things happen when I press Tab, Caps Lock, Ctrl, etc.

How can I prevent non-symbol keys from ruining the name?

I used to have a script that would only allow adding letters to the name, but I don't want to use it anymore, because of localization reasons.

I could also make add a lot if keyboard_lastkey != <key> lines, but some keys don't seem to have built-in variables for them and there are different keyboards.
Unless you're fighting caps lock, you don't need to check if shift is held down to convert keyboard_lastchar to upper or lower case, GameMaker already does this for you.
(better yet, the OS already does this for you and GM just returns what the OS returns)
keyboard_lastchar is always a string by the way, so checking if it equals -1 is always false.
Assigning keyboard_lastchar the value -1 is not allowed.
I just tested what GM:S 1.4 reacts to it and apparently the assignment is just entirely ignored.
Pressing Tabs, Caps Lock, Ctrl, etc didn't have any effect on keyboard_lastchar whatsoever.
I only tested those on the windows target though, but behavior is probably similar for other targets.

This would mean that what's happening when you press Tab and such is the following:
The press any key event is fired.
The value of keyboard_lastchar from the last character you typed is used again.
This is the character you typed in the last key press event (if you typed a character there at least), because you never cleared keyboard_lastkey.
The odds are thus that you just duplicate your last character, possibly with a different capitalization.

By now, The-any-Key has replied with a possible pseudo code as answer, but I'll provide an alternative that might look more elegant.
Instead of resetting string_lastchar to -1, reset it to the empty string "".
Then only add a character if it meets the following conditions:
Code:
if (ord(c) >= ord('a') && ord(c) <= ord('z'))
|| (ord(c) >= ord('A') && ord(c) <= ord('Z'))
|| (ord(c) >= ord('0') && ord(c) <= ord('9'))
|| string_pos(c, " -") != 0
where c is the character keyboard_lastchar and " -" can be extended to contain any additionally allowed character.
If you wish to support all characters in the ranges that your fonts use, then check if the ord of the character lies in those ranges instead.

EDIT:
Oh, I almost forgot.
Using keyboard_lastkey is a bad idea as well.
keyboard_lastkey returns the key that was pressed in the last frame, not the current one.
As a result, your if keyboard_lastkey != ... checks will check if the second-to-last key you pressed was e.g. Enter.

EDIT2:
Or at least, that's how keyboard_lastkey used to work and how it's documented, but apparently it doesn't work like that anymore...
This is a GameMaker bug.

EDIT3:
Oh and I almost forgot this as well:
If you don't plan on customizing your renaming system further,
you could have just used keyboard_string instead.
This does all the things you're doing in your code for you already.
 
Last edited:

Phoebe Klim

Member
Unless you're fighting caps lock, you don't need to check if shift is held down to convert keyboard_lastchar to upper or lower case, GameMaker already does this for you.
(better yet, the OS already does this for you and GM just returns what the OS returns)
It doesn't.
keyboard_lastchar is always a string by the way, so checking if it equals -1 is always false.
Assigning keyboard_lastchar the value -1 is not allowed.
Ooh, so that's why I was setting it to -1...

upload_2018-6-12_18-0-12.png
 
Top