Modifying TypeLine function - SOLVED

Started by Kinoko, Fri 18/06/2004 14:58:25

Previous topic - Next topic

Kinoko

Even though this post is related to the function discussed earlier (http://www.adventuregamestudio.co.uk/yabb/index.php?topic=14733.msg179671#msg179671) I thought I'd post this seperately since the previous problem -was- solved and this is a further extension of that idea... and probably complicated.

Basically, as a recap, I have this code:

In script header
Quote
import function TypeLine(string line, int vspacing,  int xpos, int font, int colour);
In global script
Quote
function TypeLine(string line, int vspacing, int xpos, int font, int colour) {
 
//declare local vars
  int length=0;
  int i = 0;
  string displayedline;
  int textid = 0;
//initialise vars , overdoing it a bit ;-)
  length = 0; 
  i=0;
  StrCopy(displayedline," ");
  textid = CreateTextOverlay(xpos,50,400,font,colour,displayedline);

          //get string length, to know how long the loop must run
  length=StrLen(line); //set string length
         //start loop
  while(i<length){
         // 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, 10,vspacing,400, font, colour, displayedline);

         // if a space is added to the string do not play a sound, else play a 'tick'
         Wait(10);
    if (StrGetCharAt(line,i) == ' '){
   }
   else{
        PlaySound(1);
        Wait(5);
    }
           //increase the loop counter
    i++;
  }
  return textid;
}

In room script
Quote
//type lines and play sound of ticking machine
int line1;
line1 = TypeLine(" First Line", 5, 50, 1, 3);
Wait(60);
int line2;
line2 = TypeLine(" Second Line", 5, 75, 1, 3);
Wait(60);
int line3;
line3 = TypeLine(" 3rd Line.", 5, 100, 1, 3);
Wait(60);

//after a pause the text is removed again
RemoveOverlay(line1);
RemoveOverlay(line2);
RemoveOverlay(line3);

}

(As a side note, this doesn't actually have the effect the last script would seem to suggest. Line 1 comes up fine, but disappears as soon as Line 2 appears, and the x position doesn't change between them - they all just start from the same place)

Usually I'd have a go at scripting this myself but I have no idea where to start with this one. I'm using the text window with background style of text display.

What I'd like to achieve is to modify the TypeLine function to always use the same size window regardless of text (I don't know if this is a matter of modifying the TypeLine function or whether it should be done elsewhere).

It already allows you to specify font and colour of text, but I'd also like to be able to control the x and y position of the text window, the speed of the typing, and if possible, have the text string point to a global message instead of typing the string out each time I use this function (though this one isn't a big deal). If possible (and I'm probably getting too ambitious here), I wondered about having another string parameter to specify a word or a phrase within the whole string to be highlighted (ie. coloured a set colour like yellow). So if the whole line of text was "This is a line of text." you could put in the highlight parameter "line" and that word would be yellow.

So maybe something like this - function TypeLine(string line, int ypos,  int xpos, int font, int colour, int speed, string highlight)

Also (feel free to shoot me), I wanted the text to be typed out as normal but instead of being controlled with 'wait's, to finish typing, and then stay on screen (blocking any other scripts) until a certain key is pushed (X = 88).

If anyone could offer any suggestions about this, point me in the right direction, whatever, anything, I'll REALLY appreciate it. I realise this is a lot all in one go but I'd rather do this then ask 50 different questions about the same essential piece of script in 50 different threads.
Quote

Pumaman

To make it use a global message, just replace:

function TypeLine(string line, int vspacing, int xpos, int font, int colour) {


With:

function TypeLine(int message, int vspacing, int xpos, int font, int colour) {
string line;
GetMessageText(message, line);



Adding the ypos to the function would be quite easy, and to make it wait for a keypress, just put something like:

while (WaitKey(100) == 0) { }

at the end, so that it will wait until a key is pressed.


Highlighting a certain word in the text is far more tricky though, and I can't think of an easy way to do it offhand.

Scorpiorus

Quote from: Pumaman on Sat 19/06/2004 21:54:08ighlighting a certain word in the text is far more tricky though, and I can't think of an easy way to do it offhand.
Yeah, especially with text overlays, since each color would require a separate overlay. I think the best way would be to use the RawPrint function instead of overlays but then again it prints onto background thus making the text appear behind the characters and objects.

Kinoko

Thanks, I can use Global Messages now and also control the x and y positioning, as well as width. The highlighted text thing isn't a big deal, it just would've been a nice feature.

I think for changing the speed I'll just create another function similar to this but with a Wait(5) line or something so I can use the slightly different function (like TypeLineSlow) when I need it.

I still have the problem with removing the text from the screen with a keypress so the next TypeLine can then play. At the moment, the first text runs, the box stays on screen and the second text window runs as soon as the first is done typing. I can't remove the boxes from the screens without using the RemoveOverlay lines (which are a bit annoying to have to type everytime so I'd like to incorporate the removal with a keypress into the global script).

Here's my global script:

function TypeLine(int message, int vspacing, int xpos, int font, int colour, int width) {
string line;
GetMessageText(message, line);

//declare local vars
  int length=0;
  int i = 0;
  string displayedline;
  int textid = 0;
//initialise vars , overdoing it a bit ;-)
  length = 0; 
  i=0;
  StrCopy(displayedline," ");
  textid = CreateTextOverlay(xpos,50,400,font,colour,displayedline);

          //get string length, to know how long the loop must run
  length=StrLen(line); //set string length
         //start loop
  while(i<length){
         // 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,vspacing,width,font,colour,displayedline);

         // if a space is added to the string do not play a sound, else play a 'tick'
         Wait(1);
    if (StrGetCharAt(line,i) == ' '){
   }
   else{
        PlaySound(1);
    }
           //increase the loop counter
    i++;
  }
  return textid;
}



And here's the code in my room script:

TypeLine (502, 100, 50, 1, 3, 200);
TypeLine (503, 100, 50, 1, 3, 200);

Ideally, I'd like to keep what I need to type in the room scripts as the one line as it is now, and have the global script code modified to have the text stay on screen until a key is pressed, and then have the next TypeLine run.

Scorpiorus

#4
Quote from: Kinoko on Sun 20/06/2004 04:53:40I think for changing the speed I'll just create another function similar to this but with a Wait(5) line or something so I can use the slightly different function (like TypeLineSlow) when I need it.
You can have a delay parameter passed to the Wait() function to specify how fast the text should be typed-in.

QuoteI still have the problem with removing the text from the screen with a keypress so the next TypeLine can then play. At the moment, the first text runs, the box stays on screen and the second text window runs as soon as the first is done typing. I can't remove the boxes from the screens without using the RemoveOverlay lines (which are a bit annoying to have to type everytime so I'd like to incorporate the removal with a keypress into the global script).
As I understand you want it following the next scenario:

-TypeLine function is running and the text is being typed;
-if the player pressed a key the text should go away so that the next one can go in.
-if there is no key pressed then after the text has been typed it should stay on the screen for some time and then be removed.

Here is a modification to the script in case that's what you are after:

function TypeLine(int message, int vspacing, int xpos, int font, int colour, int width, int delay, int wait) {

   string line;
   GetMessageText(message, line);

   //declare local vars
   int length=0;
   int i = 0;
   string displayedline;
   int textid = 0;
   //initialise vars , overdoing it a bit ;-)
   length = 0;Ã, 
   i=0;
   StrCopy(displayedline," ");
   textid = CreateTextOverlay(xpos,50,400,font,colour,displayedline);

   //get string length, to know how long the loop must run
   length=StrLen(line); //set string length
   //start loop
   while((i<length) && (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,vspacing,width,font,colour,displayedline);

      // if a space is added to the string do not play a sound, else play a 'tick'
      //Wait(1);
      if (StrGetCharAt(line,i) == ' '){
      }
      else{
         PlaySound(1);
      }
      //increase the loop counter
      i++;

      if (i==length)
         if (wait>0)
            if(WaitKey(wait)==1) {
               RemoveOverlay(textid);
               textid=-1;
            }

   }
   //RemoveOverlay(textid);
   return textid;
}

Kinoko

#5
This is so very very close to what I'm after. The only difference is that I don't want the text to be skippable until it has finished typing. So, effectively, while the text is still typing, the player can't do anything. Is this just a matter of changing (i<length) to something like (i==length) and removing the 'if (i==length) line?

EDIT: Also, what is the effect of changing the 'delay' parameter? Is it just 1 and 0 or any integer?

Scorpiorus

Quote from: Kinoko on Mon 21/06/2004 01:22:31The only difference is that I don't want the text to be skippable until it has finished typing.
It isÃ,  the while((i<length) && (WaitKey(delay)==0)) line that makes text typing being skippable. Changing it to while((i<length) && (1||(WaitKey(delay)==0))) should block the possibility to skip text's typing.

QuoteAlso, what is the effect of changing the 'delay' parameter? Is it just 1 and 0 or any integer?
It regulates the speed of typing. The higher the value is, the longer it'll take to type-in.

Kinoko

Perfect!

Now, just one more thing, is it possible to stop the text being removed after wait time? So that a keypress is the only thing that remove it. Otherwise, I guess I'll just set the wait time extremely high.

Scorpiorus

Sure, I changed it (see a previous post with the code) thus if a key was pressed the TypeLine function removes an overlay and returns -1, otherwise it returns the overlay number so that you can use it to remove an overlay manually (as it worked before):

int overlay = TypeLine(...);
...
...
...
// if function did remove it we do it ourselves:
if (IsOverlayValid(overlay)) RemoveOverlay(overlay);

Kinoko

So would I have to use it like this for every single TypeLine function I use?

int overlay = TypeLine(...);
if (IsOverlayValid(overlay)) RemoveOverlay(overlay);
int overlay = TypeLine(...);
if (IsOverlayValid(overlay)) RemoveOverlay(overlay);
int overlay = TypeLine(...);
if (IsOverlayValid(overlay)) RemoveOverlay(overlay);


...etc.

If so, I think I'll just go with setting a high wait time ^_^

Scorpiorus

You can of course ignore the returned value and type as usual if you don't care:
TypeLine(...);
TypeLine(...);
TypeLine(...);

But in that case the lines will stay on the screen forever (until a room changes) provided a player didn't press a key. Is it that behaviour you are after?

Kinoko

Well, no, because I don't want the player to be able to move the character (or do anything) while text is displayed. Now that I think about it, it's not the worst thing on earth to have the text window disappear after awhile. I forget that not everyone is like me and they don't leave a game in the middle of a conversation to go and make their lunch and do some laundry ^_^

Once again, Scorpiorus, thanks for all your tireless efforts in helping me.

Scorpiorus

Ah, so you don't want a message to disappear after a timeout but only after a key was pressed? Then, yeah you can pass a really high value or (to make it trully non-timeoutable) put a code suggested by CJ:

by replacing:

if (i==length) if (wait>0) WaitKey(wait);

with:

if (i==length)Ã,  if (wait>0) WaitKey(wait);
         else if (wait == -1) while (WaitKey(100) == 0) { }

Thus, passing wait = -1 a player will have to press a key to remove the message.

Kinoko

#13
Woohoo! ^_^ Fantastic, works wonderfully, thanks to you both.

Just another query (I'm like an Energizer battery!)...

Before every TypeLine text window comes up, just a -fraction- before and for only a flicker, probably one game cycle... I get a flash of an empty text window elsewhere on the page and to the right a bit. It's not getting in the way of anything as such but it's a little annoying and I don't know why it's happening. I thought that maybe the TypeLine code was taking too long to process or something...

EDIT: 'Colour' doesn't seem to work at all. Changing the integer in the TypeLine function does nothing. I can't figure out how it's supposed to be working in the first place.

Scorpiorus

Quote from: Kinoko on Tue 22/06/2004 02:33:23...I get a flash of an empty text window elsewhere on the page and to the right a bit.
I'm not sure what it is. The typeline function doesn't use any GUI, so you probably has your own? Maybe you have a script that makes it flash? Btw, how do you use a text window (it's a GUI?) with text overlays. AFAIK, overlays are drawn behind GUIs and you generally won't see them unless of course a GUI has some transparent area which overlays are visible through.

QuoteEDIT: 'Colour' doesn't seem to work at all. Changing the integer in the TypeLine function does nothing. I can't figure out how it's supposed to be working in the first place.
That's strange. I tried and it worked fine for me. The colour parameter specifies a colour in which a text line is drawn. It passed directly to the Create/SetTextOverlay function and I'm not sure about why it doesn't work. Try setting it to 14 or 15. It should then be drawn in either yellow or white colour respectively.

Kinoko

#15
I thought I'd discovered why it was happening. I only have 2 GUIs at the moment (0 and 1) and I created 0 first (with my current style of text window) until I realised it wouldn't allow the number 0 in the "Text windows use GUI __" option. Then I created 1 and that worked fine, but I just realised that GUI 0 still had the "Text window" box checked. I unchecked it, but I still get the flashing.

I unchecked the "Text windows use GUI __" option, tested the game, and the same thing happened but with the plain white text window (and a plain white text window flashing in the background for a second, same as before). I also tried unchecking the "Text window" box back in the GUI controls but no change...

So, it seems to me that it's some problem in the script. I'll repost my script but I'll keep mucking around, changing various things to see if I can pinpoint the problem.

In the script header:

Code: ags

import function TypeLine(int message, int vspacing, int xpos, int font, int colour, int width, int delay, int wait);


In the Global Script:

Code: ags

function TypeLine(int message, int vspacing, int xpos, int font, int colour, int width, int delay, int wait) {
string line;
GetMessageText(message, line);

//declare local vars
Ã,  int length=0;
Ã,  int i = 0;
Ã,  string displayedline;
Ã,  int textid = 0;
//initialise vars , overdoing it a bit ;-)
Ã,  length = 0;Ã,  
Ã,  i=0; 
Ã,  StrCopy(displayedline," ");
Ã,  textid = CreateTextOverlay(xpos,100,400,font,colour,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,vspacing,width,font,colour,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) WaitKey(wait);
Ã,  Ã, else if (wait == -1) while (WaitKey(100) == 0) { }
Ã,  Ã, }
 RemoveOverlay(textid);
}


In the room script:

Code: ags

TypeLine (501, 100, 50, 1, 12, 200, 0, -1);
TypeLine (502, 100, 50, 1, 13, 200, 0, -1);
TypeLine (503, 100, 50, 1, 14, 200, 0, -1);


As for the colour, changing the parameter in the TypeLine line does nothing. I just figured out though that it's dependant on what the foreground colour in the options for the GUI is set to. If I'm not supposed to be using a GUI with this TypeLine function, how can I get the style of text window I want?

Quote
Btw, how do you use a text window (it's a GUI?) with text overlays.

I simply have the TypeLine script as it is above, and the "Sierra style w/background" style of speech selected in the options. With that, the text types out on the white text window perfectly. If I then specify a GUI, I get the current text window I have.

Scorpiorus

Ah, you use the "Sierra style w/background" speech style and thus all text overlays are drawn within a text window! That really makes sense now, so yes since you set up a custom text window AGS uses its foreground color to draw text overlays in. It overrides a value that's passed to the SetTextOverlay function and thereby a colour parameter has no effect. If you tried to set the lucas-arts style speech the colour parameter would be taken into account. Since you are using the sierra style w/b (for a good reason here) the only way to change a text color is to change the foreground colour of the appropriate text window GUI. The main problem is that it's not currently possible (afaik) to alter text window's foreground colour with scripting at run-time. I think a good idea could be to have a function to change it but for now the only way out is to create several text windows - each having its specific color.

As for the flashing problem, after have tested the function with the sierra speech style enabled, I found out what' the problem is:

change the line within TextLine:

StrCopy(displayedline," ");

to

StrCopy(displayedline,""); // no space here :)

and the blinking effect should go away.

Pumaman

Hmm, that behaviour isn't very user-friendly. I'll see about fixing up CraetTextOverlay to use the actual passed colour

Kinoko

QuoteAh, you use the "Sierra style w/background" speech style and thus all text overlays are drawn within a text window!

Gee, I must have forgotten to mention that ^_^;; er, sorry. Probably would have made things much easier.

Anyway, thanks heaps! It works beautifully now. I was already going to use different functions for different sounds so I might as well use them to change the colours too. It's no big deal, because there will be one main text colour and a couple of others for only a couple of characters.

CJ: That'd be awesome ^_^

Scorpiorus

#19
Kinoko: I'm glad it works now :)

CJ: There is a thread posted about the same problem when using a custom text window with DisplaySpeech and DisplayThought where foreground colour overrides a character talking one. http://www.adventuregamestudio.co.uk/yabb/index.php?topic=14883

SMF spam blocked by CleanTalk