Text Box question [solved]

Started by DrewCCU, Wed 04/08/2010 04:41:37

Previous topic - Next topic

DrewCCU

I realize there may be several ways to do what i'm about to ask but seeing as how i've never used the text box option before i wanted to ask around for what may be the best solution so i don't end up with any bugs.  So let me go ahead and ask the question so you get the idea:

I have a GUI text box on a gui (obviously) and what i would like to be able to do is something like this:

I want the player to type in a number (from 1-100) and then i want that number to be converted to an integer so that AGS can use it in a mathematical equation in the script.
i.e. something like:  
Code: ags

int VAR = txtUserInput.Text;


Now the problems i'm foreseeing are things like what if the player types in numbers that are above 100 or below 1?  Or even worst, what if they type in letters?  My ideal situation is that if they type in something that is not 1-100 i want to display a message that says something like "Input only a value between 1 & 100." or something like that.

Any suggestions?  
"So much of what we do is ephemeral and quickly forgotten, even by ourselves, so it's gratifying to have something you have done linger in people's memories."
-John Williams

Gilbert

#1
First,
Code: ags

int VAR = txtUserInput.Text;

doesn't work, as this will cause a type-mismatch error.

You need to convert the String to an integer with functions like say, String.AsInt.

To check whether there are "illegal" characters just check each character of the string. So you may make some function like (untested):

Code: ags

function CheckConvertText(String tempstr){
  int ii=0;
  while (ii<tempstr.Length){
    if (tempstr.Chars[ii]<'0'||tempstr.Chars[ii]>'9') return -1;  //"illegal" character
    ii++;
  }
  int value=tempstr.AsInt;
  if (value>=1||value<=100) return value;
  else return -1;
}


Then when you want to check for the validity of the textbox just do womething like:
Code: ags

int VAR=CheckConvertText(txtUserInput.Text);
if (VAR==-1) Display("Input only a value between 1 & 100.");

DrewCCU

#2
Thanks. I'll try that out.

Another question I have:

Is there a way to set a maximum character length for a text box?

EDIT:

Okay, I put the custom function into the global script then in the global.ash i used the import function code so the room could access it.  I put the
Code: ags

int VAR=CheckConvertText(txtUserInput.Text);
if (VAR==-1) Display("Input only a value between 1 & 100.");


in the room script (in rep exec).

I got a parse error in the global script.asc on the line:
Code: ags

if (tempstr.Chars[ii])<'0'||tempstr.Chars[ii])>'9') return -1;  //"illegal" character

PE04: Parse error at '<'

Another thing - i read the String.AsInt file but i'm having a little trouble interpreting how to convert txtUserInput.Text into an int with it.
"So much of what we do is ephemeral and quickly forgotten, even by ourselves, so it's gratifying to have something you have done linger in people's memories."
-John Williams

Gilbert

Quote from: DrewCCU on Wed 04/08/2010 05:43:39
Thanks. I'll try that out.
PE04: Parse error at '<'
There're some obvious typos in that line, that I put two extra )'s in it. Supposed to be fixed now.

Quote
Another thing - i read the String.AsInt file but i'm having a little trouble interpreting how to convert txtUserInput.Text into an int with it.
The AsInt property works just like how the examples show. The problem is that it seems that you cannot use something like txtUserInput.Text.AsInt or (txtUserInput.Text).AsInt in AGS (this is one reason why OOP sucks IMO as normally StringToInt(txtUserInput.Text) is much more readable and makes more sense, I don't know whether this is possible for programming languages in general, but I think it's possibly more doable on dialects that support the -> syntax), so you probably need to use another String to hold its content first, like this:
Code: ags

String blah=txtUserInput.Text;
int VAL=blah.AsInt;

DrewCCU

ah i see. it makes sense now.  thank you very much.  tomorrow i will try out this new information and let you know what happens.  thanks again.
"So much of what we do is ephemeral and quickly forgotten, even by ourselves, so it's gratifying to have something you have done linger in people's memories."
-John Williams

monkey0506

#5
Quote from: Gilbet V7000a on Wed 04/08/2010 06:14:58The problem is that it seems that you cannot use something like txtUserInput.Text.AsInt or (txtUserInput.Text).AsInt in AGS

Why not? I do this all the time. What you can't do, is you can't access properties of a member of static properties such as DateTime.Now. So you couldn't, for example, do int rawtime = DateTime.Now.RawTime directly, because DateTime.Now is a static property. This is actually a known issue and not by convention.

However, whenever you're dealing with non-static properties such as TextBox.Text you can then call members of that property where applicable, such as TextBox.Text.AsInt.

Edit: Just as a test, I just started a new game project using the Empty Game template, added a new Room, a new GUI, and a new TextBox control. Then I added the following code:

Code: ags
function game_start() 
{
  TextBox1.Text = "10";
  int val = TextBox1.Text.AsInt;
  Display("%d", val);
}


As expected, the value of 10 is displayed.

Gilbert

Thanks for the explanation! It's been quite some time, but I think I got that impression when I tickled with DynamicSprites (or DrawingSurfaces, or Overlays as I cannot remember the details). The example DateTime.Now.RawTime is not very good though, as we already have the workaround DateTime.RawTime. I think there're other examples of static properties that exhibit this limitation but I'm too lazy to check.

Though still, I'm never fond of this OOP way of writing unnecessarily long stuff. I'd rather use the function-parameter approach.

monkey0506

I think you're misreading the manual. Although the property is listed as DateTime.RawTime it is not a static property. That means you still have to use a DateTime object to access the member. So, as in the example in the manual, you still have to use DateTime.Now before you can access the RawTime property.

Only properties listed in the manual as static are accessed directly on the class name as opposed to an instance of the class.

You do have a point that:

Code: ags
int rawtime = GetRawTime();


Is shorter than:

Code: ags
DateTime *dt = DateTime.Now;
int rawtime = dt.RawTime;


However, consider instead something like Character.ActiveInventory:

Code: ags
// non-OOP
InventoryItem *activeItem = GetCharacterActiveInventory(GetPlayerCharacter());

// OOP
InventoryItem *activeItem = player.ActiveInventory;


Not only is the code here shorter, it's also more to-the-point IMO. Let's take it a step further, and change the Graphic property of the character's active inventory.

Code: ags
// non-OOP
SetInventoryItemGraphic(GetCharacterActiveInventoryItem(GetPlayerCharacter()), 42);

// OOP
player.ActiveInventory.Graphic = 42;


The OOP code in this case is much easier to read and understand what is going on.

I'm getting completely off-topic here, but I just wanted to point out that OOP has advantages. Understandably it may not be perfect, but neither is "the function-parameter approach".

Khris

If you added this to the applying rep_exe, you could prevent the player from entering characters other than digits:

Code: ags
function room_RepExec() {
  String t = tbInputNumber.Text;
  String l;
  if (String.IsNullOrEmpty(t)) return;
  if (t.Length > 0) {
    l = t.Substring(t.Length-1, 1);
    if (l.AsInt == 0 && l != "0") {
      t = t.Substring(0, t.Length-1);
      tbInputNumber.Text = t;
    }
  }
}


If does sort of work, the typed letter does flash for half a second though.

Gilbert

Quote from: monkey_05_06 on Wed 04/08/2010 09:01:52
The OOP code in this case is much easier to read and understand what is going on.
I don't think so, but yeah it's just a personal preference, so there's no point in arguing this OT stuff anyway.

DrewCCU

THanks for all of the input.  I still haven't had a chance to plug anything in yet but as soon as i can i will experiment with what you guys have suggest and i'm sure i can get it working. 

However, i believe in all of the discussion one of my questions was overlooked.  So i'll ask again:

Is there a way to set a maximum character length for a text box?

"So much of what we do is ephemeral and quickly forgotten, even by ourselves, so it's gratifying to have something you have done linger in people's memories."
-John Williams

Atelier

Adjust the text box width to the width of the font you're using, multiplied by how many characters you want, but it depends whether your font has monospaced digits. 123456 all look the same to me, so it saves some coding if it does work.

DrewCCU

#12
Quote from: AtelierGames on Wed 04/08/2010 18:10:17
Adjust the text box width to the width of the font you're using, multiplied by how many characters you want, but it depends whether your font has monospaced digits. 123456 all look the same to me, so it saves some coding if it does work.

I tried that but the problem is the font i want to use ISNT monospaced.  So in the text box you can type 100 (andno more) but you could also type 1111.  I want there to be a 3 digit maximum characters allowed.  So being able to type 1111 isn't good. (while its improbable the player will do that and probably not a big deal - i still would like to account for it if possible.)

EDIT:

Actually i believe i have gathered all the information i need from this thread.  Thanks everyone.  You guys helped me and taught me some things.
"So much of what we do is ephemeral and quickly forgotten, even by ourselves, so it's gratifying to have something you have done linger in people's memories."
-John Williams

Khris

Yeah, you can easily modify my code to also delete a fourth char, regardless of what it is.

Another way would be to use something else for input, e.g. a clickable numpad.

SMF spam blocked by CleanTalk