Keypresses speeding up text "typing" (SOLVED)

Started by Kinoko, Thu 17/03/2005 04:07:02

Previous topic - Next topic

Kinoko

I've just noticed in one of my TypeLine functions that even though I've set a rather slow delay for the text speed, if you press or hold down a key while the text is "typing", the text will seem to ignore the delay and type the next letter straight away.

Here's the code, though for the life of me I can't see what the problem would be.

Code: ags

function TypeLineInvis (string say, int xpos, int vpos, int width, int delay, int wait) {
if (IsGamePaused()==0) {
	StrCopy (line, say);

	StopMoving(EGO);
	SetTextWindowGUI(31);
	//declare local vars
	  textid = 0;
	//initialise vars
	  length = 0;  
	  i=0; 
	  StrCopy(displayedline,"");
	  textid = CreateTextOverlay(xpos, 100, 400, 1, 1, displayedline);
	
		  //get string length, to know how long the loop must run
	  length=StrLen(line); //set string length
		 //start loop
	while((i<length) && (1||(WaitKey(delay)==0))) {
		 // pick character at position "i"and stick it at the end of string "displayed line"
	    StrFormat(displayedline, "%s%c", displayedline, StrGetCharAt(line,i));
		 //set textoverlay as displayedline
	    SetTextOverlay(textid,xpos,vpos,width,1,1,displayedline); 
	
		 // if a space is added to the string do not play a sound, else play a 'tick'
	    if (StrGetCharAt(line,i) == ' '){
	   }
	   else{
		PlaySound(1);
	    }
		   //increase the loop counter
	    i++;  
	   if (i==length) if (wait>0) Wait(wait);
	   }
	 RemoveOverlay(textid);
	 Wait(5);
}
}


I tried blocking keypresses in on_key_press while this function is running, using: if (keycode==keycode) keycode=0; but that didn't work. Of course, it might have been stupid to try keycode==keycode.

stuh505

QuoteWaitKey (int time)

Pauses the script and lets the game continue until EITHER:
(a) TIME loops have elapsed, or

(b) the player presses a key

Returns 0 if the time elapsed, or 1 if the player interrupted it.

---

QuoteWait (int time)

Pauses the script and lets the game continue for TIME loops.

;)

Kinoko

Argh! I'm blind. There was another WaitKey in there and I got rid of that one, I forgot about the other >_< It passed me right by...  how many times must I humiliate myself in this forum? -_-

Thanks stuh!

strazer

#3
Just a few notes:

Code: ags

//declare local vars
  textid = 0;


You don't declare this variable anywhere in this function, otherwise it would have to be
  int textid = 0;
And since you set its value with CreateTextOverlay anyway, why initialize it to 0 at all?

If you declare it outside of the function, it's a global variable and not a local one.
This concerns almost all variables in this function. Where do you declare "line", "length", "i"?
Unless you need a variable in other functions, there's no reason to make it a global one.

Also, you use a lot of redundant variables.

Here is a cleaned up version of your function:

Code: ags

function TypeLineInvis (string text, int xpos, int vpos, int width, int delay, int wait) {

  if (IsGamePaused()==0) {

    StopMoving(EGO);
    SetTextWindowGUI(31);

    string displayedline; // declare string holding the letters to display
    StrCopy(displayedline, ""); // initialize string

    int overlay_id = CreateTextOverlay(xpos, 100, 400, 1, 1, displayedline); // create empty text overlay

    int i = 0; // declare loop counter
    while (i < StrLen(text)) { // loop for each position of the supplied string

      StrFormat(displayedline, "%s%c", displayedline, StrGetCharAt(text, i)); // stick letter from current position "i" to end of string "displayedline"
      SetTextOverlay(overlay_id, xpos, vpos, width, 1, 1, displayedline); // set text overlay to "displayedline" string
      if (StrGetCharAt(text, i) != ' ') PlaySound(1); // if letter is NOT a space, play 'tick' sound

      Wait(delay); // wait for specified game loops before looping to next letter
      i++; // increase loop counter: loop to next position
    }
    // loop ends here: all letters displayed

    WaitKey(wait); // wait until specified game loops elapse or player presses a key

    RemoveOverlay(overlay_id); // remove the text overlay
//  Wait(5); // what for?

  } // endif (IsGamePaused() == 0)

}


Hope this helps.

Kinoko

#4
Actually, it's not "my" function at all, I didn't write any of this. I er, can't remember who did but it was someone else's doing.

I have modified it over time though, so that's why I took the "int" from the textid=0 line (I guess it didn't occur to me to get rid of the whole line, but I always like to make extra sure variables are valued at what  they should be anyway). I see your point though.

I do need declare those ints outside of the function though, I have other functions that use them.

RickJ

Quote
If you declare it outside of the function, it's a global variable and not a local one.
Perhaps some clarification about variables would be useful here.  If I get some terminology wrong someone please correct me. 

Dynamic Variables
These  variables are declared inside the bounds of a function.  They exist only while the function is being executed.  When the function completes dynamic variables are "destroyed" (i.e. the memory allocated to such variable(s) is freed and may be reallocated for other purposes).  These variables are used to hold intermediate results of calculations or other values that are calcualted every time the function is executed.   These variables do not retain their values from one executition of the function to another.   It is generally accepted practice to declare such variables at the beginning of the function prior to executable statements.

Static Variables
These variables are declared outside the bounds of any functions.  They are created when the game is loaded and remain in existence and retain their values for the duration of the session.  These variables are accessable by any function defined in the same script file but not by functions in other script files.  The values of such variables are also saved and restored byt the "Save/Restore Game" mechanism.  It is generally accepted practice to declare such variables at the beginning of the script file prior to executable statements.  In a large script file, such as the global script, that is organized into functional groups it is also acceptable to declare such variables at the beginning of the function group where it is intended to be used. 

Global Variables
These are static variables that have been made available to all script files via export and import statements.  Normally these variables are declared in the Global Script file and immediately followed by the corresponding export statement.  An import statement in the Script Header then ives access to the variable from all room scripts.

Quote
I do need declare those ints outside of the function though, I have other functions that use them.
In the case of "textid", "length", and "i",  in the example, I would declare these inside each function where they are being used.  You will of course have to eliminate the curent declarations that are outside any function bounds. 

Kinoko

How do you make a dynamic variable then? As far as I was aware, you make a variable, it's a static one. It's always around. How do you 'destroy' it?

Quote
In the case of "textid", "length", and "i",  in the example, I would declare these inside each function where they are being used.  You will of course have to eliminate the curent declarations that are outside any function bounds.

Not to be rebellious, but why? Actually, let me ask for clarification here. When people say 'declare' a variable, are you talking about creating it, ie. int i; or giving it a value ie. i=0;

When I said I'd declared it outside of the function, I meant that it's created at the top of the global script (where I pretty much create all my variables), and I use "textid=0;" inside the function just for... extra security I guess.

Gilbert

When you declare a variable inside a function it's "dynamic", that variable is local only to that function and is destroyed once the function call ended. Like:

function Blargh(){
  int hahaha=5;
  Display("%d",hahaha);
}

Kinoko

Then why is it that when I had the line "int typeline;" in several different functions, I got errors? It just seems that if a variable is contained within a function, it should be allowed to be created as new in another function.

Kweepa

Quote from: Kinoko on Fri 18/03/2005 03:28:28
How do you make a dynamic variable then? As far as I was aware, you make a variable, it's a static one. It's always around. How do you 'destroy' it?
AGS will do this automatically for variables "intstantiated" (created) inside functions. Variables outside functions are static.

Quote
Quote
In the case of "textid", "length", and "i",  in the example, I would declare these inside each function where they are being used.  You will of course have to eliminate the curent declarations that are outside any function bounds.

Not to be rebellious, but why?

There are a number of reasons.

1) You can guarantee the value isn't changed between functions. Consider this code:

Code: ags

int bah;
int meh;
function psshaw(int pff)
{
   bah = 1;
   meh = 2;
   while (bah < pff) { meh *= meh; bah++ }
   return meh;
}

function whatever()
{
   bah = 0;
   meh = 0;
   while (bah < 5) { meh += psshaw(bah); }
   Display("%d", meh);
}


Calling psshaw from whatever tramples all over bah and meh, and you don't get what you expect.

2. Creating variables locally makes things more legible - you can see what type the variable is (string, int, float, etc) without having to scroll up and down the code. You don't have a lot of temporary variables cluttering up the top of your script, and you can use whatever name you want for a variable immediately.

3. If you decide to change the type of the variable (say from int to float) you don't need to worry about where it's been used.

4. Static variables have to be saved in the save game, even though you don't care about their contents. Not a big deal normally, but it could add up.

5. There are other reasons in languages that are compiled and optimised, but we don't need to go into that.

Quote
Actually, let me ask for clarification here. When people say 'declare' a variable, are you talking about creating it, ie. int i; or giving it a value ie. i=0;

When I said I'd declared it outside of the function, I meant that it's created at the top of the global script (where I pretty much create all my variables), and I use "textid=0;" inside the function just for... extra security I guess.

Declaration is for example "import int i;".
Instantiation (creation) is "int i;".
Instantiation and initialization is "int i = 0;".
Assignment is "i = 0;".

For statics in a single script file (not exported) you can call "int i;" a declaration as well as an instantiation as it's the first occurrence of "i".
Still waiting for Purity of the Surf II

Gilbert

Quote from: Kinoko on Fri 18/03/2005 04:00:35
Then why is it that when I had the line "int typeline;" in several different functions, I got errors? It just seems that if a variable is contained within a function, it should be allowed to be created as new in another function.
If there's a variable with the same name declared as static (like on top of the script, or importing one from the global script) it may be illegal to declare a variable with the same name in a function. Check if there're such declarations of "static" variables.

Kinoko

But these weren't static variables outside of the functions. Only inside several functions did the line "int textid;" occur, and it told me every place other than the first time it was declared that the variable has already been declared.

Gilbert

Really? Shouldn't be, unless there're some bracket errors that somehow two declarations went into the same function or went outside of a function.
Hopefully this isn't a bug, which version of AGS are you using?

Kinoko

I just tried it again and it doesn't give me any errors. Mind you, it was a few months ago since I last tried it, I could have had a different version of AGS back then or there could have been an error in the code.

SMF spam blocked by CleanTalk