• 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!

GameMaker Floating Inputs

dialgpalkia

Member
Hey all,

I'm trying to add a textbox into my game that takes only floating numbers, but I'm struggling to get it to work. here's my code:
GML:
if(string_length(keyboard_string) < maxNumberOfCharacters){
    var is_realnumber = is_real((keyboard_lastchar));
    if(string_length(is_realnumber)){
        message = keyboard_string; //Store what is typed in variable message
    }
} else {
    keyboard_string = message;
}
But it's throwing up an error whenever keyboard_lastchar = "" (which is the default). When I mess with the code, I can't type anything at all into the textbox. I've tried
GML:
var is_realnumber = is_real((keyboard_lastchar)) || keyboard_lastchar == "";
But that hasn't worked either - I can't put any numbers in the box.

Previously I was using:
GML:
    if(string_length(keyboard_string) < limit){
        var is_number = string_digits(keyboard_lastchar);
        if(string_length(is_number)){
            message = keyboard_string; //Store what is typed in variable message
            //keyboard_lastchar = "";
        }
    } else {
        keyboard_string = message;
    }

Which was working, but I need to use decimals too. Any ideas? I've scoured the web and haven't found anything that's really helped.
 

ophelius

Member
You have this line:
Code:
var is_realnumber = is_real((keyboard_lastchar));
which is storing a boolean value (true or false) in 'is_realnumber'.

But then you're checking the string length of that boolean value:
Code:
if(string_length(is_realnumber)){
which is not correct because it's not a string. string_length returns the amount of characters found in a string (string_length("test_123") would return 8)
 
Last edited:

dialgpalkia

Member
Ah yes I see the issue, thank you! I've removed that but I think it's still struggling with "", as I can't type anything in the textbox. I tried
GML:
if((is_number) || keyboard_string == ""){
    message = keyboard_string; //Store what is typed in variable message
}
But it still isn't registering anything...
 

dialgpalkia

Member
keyboard_lastchar is a string of at most one character. It is never a number. You would need to convert the string to a number, possibly using some combination of string_digits and real.
Good point, thanks! I still need way to check for floats and for blank strings... I've tried a manual check:
GML:
var _str = string(keyboard_lastchar);
var _num = string_digits(_str);
var _check = false;
if((_str=="")||(_str==".")){_check=true}
if((_num) || (_check)){
    message = keyboard_string; //Store what is typed in variable message
    keyboard_lastchar = "";
}
But it's still returning the following:
Code:
############################################################################################
FATAL ERROR in
action number 1
of  Step Event0
for object objInputBox_Value:

unable to convert string "" to bool
 at gml_Object_objInputBox_Value_Step_0 (line 19) -               if((_num) || (_check)){
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Object_objInputBox_Value_Step_0 (line 19)

I'm not trying to convert "" to a bool, I'm trying to check if _str is "" and if so then setting _check to true...?
 

dialgpalkia

Member
This is literally trying to convert _num, which is a string, to a bool.
Ahhh I see, I thought string_digits was a check if a string was a digit, not removing anything but the digit from the string. Thanks for that. I've now updated it to this which doesn't return any errors but nothing is displayed when I type:
GML:
var _num = is_real(keyboard_string);
if((_num) || (keyboard_string == "")){
    message = keyboard_string; //Store what is typed in variable message
}
"message" is then displayed in a simple draw_text.
 

Yal

🐧 *penguin noises*
GMC Elder
Just to get the obvious out of the way, have you tried using get_string / get_string_async to ask for a string in a dialog box, and get the entire thing at once?

if((_num) || (keyboard_string == "")){ message = keyboard_string; //Store what is typed in variable message }
This code will wipe the contents of message when keyboard_string is empty (setting it to ""), are you sure that's what you want since you use message later?
 

dialgpalkia

Member
Just to get the obvious out of the way, have you tried using get_string / get_string_async to ask for a string in a dialog box, and get the entire thing at once?


This code will wipe the contents of message when keyboard_string is empty (setting it to ""), are you sure that's what you want since you use message later?
This is a MUCH easier way of doing this! Thank you so much Yal. Now I just need a way to stop the player from using anything except numbers and decimals. Is there a way to do that? I need to set a global variable to the result of this, but the variable needs to be a float.
 

Yal

🐧 *penguin noises*
GMC Elder
In 2.3, you could do this:
GML:
try{
  global.thing = real(mystring)
}
catch( /*anything*/ ){
  show_message("That wasn't a valid real number you chump")
  global.thing = 0
}
I.e., try using real on the string directly, catch any errors.

real is notorious for not having any way to test if the operation is valid in beforehand, and GM has no error handling yet, so essentially floating point numbers can't be created from strings without you writing a custom interpreter. There's also no function to only filter out the digits, minus sign, and decimal markers. In 2.3, there's finally gonna be a way to handle it. But it's still in beta, so...

The best bet I'd say is to add a function that goes through the entire string and does string_char_at at every character in the string and checks that the following rules applies:
  • any character other than the digits, "." and "-" instantly invalidates the entire string.
  • Having more than one "." invalidates the string.
  • Having "." as the first character invalidates the string.
  • Having "-" anywhere except as the first character invalidates the string.
If the string is valid, split the string at the "." character, real() the part before and after the . character separately, and divide the part after the decimal dot by 10 as many times as it has characters. Add the two numbers together. Multiply the result with -1 if there was a leading minus sign.
 

dialgpalkia

Member
Wow looking forward to that 2.3! Makes things a lot simpler. That's a great idea though, taking and checking everything against those rules. I'll whip up a function and try to get it to work. Worst comes to worst, real(message) will just remove any weird things anyway - I didn't know it did that. Thanks, Yal, I appreciate it!
 
This is the exact code that I use in my puzzle editor to adjust things specifically to only allow digits (the user can type what they want, but if it contains digits, the string gets crushed down to just the digits and if it doesn't contain digits, it exits early):
Code:
if (numbers_only) {
    if (string_digits(value) == "") {
        value = new_value; // Reset the value to what it was before the user inputted something
        exit;
    }
    var str_len = string_length(value);
    var decimal = string_pos(".",value);
    var whole_string = value;
    if (decimal != 0) {
        whole_string = string_copy(value,1,decimal-1);
    }
    whole_string = string_digits(whole_string);
    str_len -= decimal;
    var decimal_string = "";
    if (decimal != 0) {
        decimal_string = string_copy(value,decimal+1,str_len);
    }
    decimal_string = string_digits(decimal_string);
    var whole = real(whole_string);
    var dec = real("0."+decimal_string);
    var real_no = whole+dec;
    new_value = real_no;
}
In that code, the value variable is the raw string that the user has inputted and the local variable real_no or instance variable new_value (which is what I return at the end) contains the full digits. It preserves decimal points (which string_digits did not when I was testing) and as far as my limited testing with it, it works fine. It doesn't check for negatives though, so any negative number will be returned as a positive number (though, this could pretty easily be fixed by adding the roughly the same kind of check that is being done for decimals).

There may be an easier way to do it, but any of the shortcuts I tried beyond this ended up muddling some part or another so that it could return garbage with certain inputs.
 
Top