Darkseed style GUI

Started by Anarcho, Sun 30/04/2006 18:18:08

Previous topic - Next topic

Anarcho

Hi, I'm trying to create a GUI similar to that used in Darkseed.  There's a text box at the bottom of the screen that displays text in real time.  When you look at an object, the text should be displayed in that box rather than over the character's head or in a regular text box.  I found a thread that about something similar:

http://www.adventuregamestudio.co.uk/yabb/index.php?topic=25169.0

I can't seem to get it to work.  Also, I'd like the text to remain on, and allow the player to scroll up and down to view previously displayed text.  Maybe after a certain number of lines the text would be deleted.  I suppose it's similar to what you have in the Baldur's Gate games.

I'm not a very good programmer so please treat me like an idiot.  I'm using 2.71.  I've created a GUI for this: gFrame, with a label: framelabel.  I tried using the script Ashen suggested in the link above, using this:

function FrameEx(string message) {
  Framelabel.SetText(message);
  gFrame.Visible = true;
  WaitMouseKey(40);
  gFrame.Visible = false;
}

I put it in the repeatedly execute section of the global script.  What am I doing wrong exactly?

Thanks,

Logan


Ashen

#1
QuoteI can't seem to get it to work.
Can you be a bit more specific - is there something it's doing that you don't want it to (or not doing that you want it to), do you get an error message and a crash, is it just not doing anything at all?

Why is it in rep_ex? That almost certainly would cause a crash, as you can't have functions declared inside other functions, and anyway the code doesn't need to be called repeatedly. To have the text stay on screen, you can delete the WaitMouseKey line, and both the gFrame.Visible lines - basically you could do it without using a custom function, just calling Framelabel.SetText("Your text here.");. Or rather, since you're using 2.71, Framelabel.Text = "Your text here.";. Using 2.71 also means that the string message parameter should be String message (note capitalisation), if you keep the function.

For keeping previous lines viewable, there're a couple of ways you could do it. The easiest would be to use a ListBox to display them, rather than a Label which would add the new text after the existing ones and allow you scroll back and forth as you want, e.g. (untested):
Code: ags

function FrameEx(String message) {
  FrameList.AddItem(message); // Where 'FrameList' is a ListBox object on gFrame
  FrameList.TopItem = FrameList.ItemCount - 1; // Makes sure the ListBox is scrolled to newest message
}

EDIT: Obviously, this doesn't take into account that some mesages may be more that one 'line'. That's doable, but more complicated. First things first ....

It'd be easy enough to add code to delete the earlier messages, after a certain number had been added (so the ListBox only sorts last 20 (for example) messages).

I know what you're thinking ... Don't think that.

Anarcho

Thanks for responding Ashen.  I wasn't experiencing any crashes, it's just that nothing was happening at all.  I originally put the code in the repeatedly execute section because I didn't know where to put it.  Where am I supposed to put it? 

I haven't scripted anything in AGS in many many many months.  I also haven't used 2.71 before today.  So you'll have to bear with me.


Ashen

Where are you supposed to put which bit?
The function declaration (i.e. the bit you posted) can go anywhere in the Global Script, provided it's not in an existing function. Remeber though that you can only use it in the script after it's been declared - so as close to the top as possible is probably best. You'll probably also want to import it into the Script Header, so it can be used in Room Scripts. I'm guessing you haven't actually got that in rep_ex, as that would cause a compile error, as opposed to just not doing anything.

The function itself should be called (FrameEx("Hello, world!"); whenever you want to display a new message.

You might want to do some random 'test' stuff to familiarise yourself with the new (as of 2.71) String types   and the whole new OO style, depend on how long many many many months actually is - before launching yourself into a 'real' project. Unless that's what this is, of course...
I know what you're thinking ... Don't think that.

Anarcho

Thanks Ashen.  Ok, so I put this bit in the beginning of the global script:

function FrameEx(String message) {
  FrameList.AddItem(message);
  FrameList.TopItem = FrameList.ItemCount - 1;
}

Now how do I go about importing this into the Script Header.  I've read the section on import in the help files, but I still don't quite get what I'm supposed to write...


Ashen

The manual's pretty clear, I'd have thought - it's basically the first line of the declaration, with import in front of it. So in this case:
Code: ags

import function FrameEx(String message);


Since it's a function, you don't have to worry about exporting it first - just make sure that goes into the Script Header (Ctrl-H) and not the Global Script itself.
I know what you're thinking ... Don't think that.

Anarcho

Oh, i guess it was clear enough, I used that very code but nothing happened so I thought it was wrong.  I didn't understand that I had to put FrameEx("I'm looking at a hotspot!") for the script when looking at a hotspot.

It's sorta working, but hopefully I can figure it out from here.  Thanks for bearing with me!


Anarcho

Sorry to double post, but I've got some lingering problems with this.

1) How do I set the width of the text within the label?  I've set the size of the label, but the text just keeps going past the label border.  I figure I have to put a DisplayAt command somewhere, but I'm not sure how and where.

2) As it is right now, when i use this custom function to say, call up a message when looking at a hotspot, it looks fine.  But when i then try to look at another hotspot, nothing happens.  Am I missing something?


Scorpiorus

#8
Quote from: Anarcho on Tue 02/05/2006 01:56:291) How do I set the width of the text within the label?Ã,  I've set the size of the label, but the text just keeps going past the label border.Ã,  I figure I have to put a DisplayAt command somewhere, but I'm not sure how and where.

Well yes, if you're using a custom GUI with label the text won't be aligned automatically. But you can't use the DisplayAt function for such interface because it's blocking -- the game will be paused then. A workaround is to script it to replicate Display() behaviour but non-blocking.

Quote2) As it is right now, when i use this custom function to say, call up a message when looking at a hotspot, it looks fine.Ã,  But when i then try to look at another hotspot, nothing happens.Ã,  Am I missing something?

You have to put this function within LookAt event of each hotspot you want to display the message for.


EDIT:

I've just found a handy function here and then updated it to Ags v2.71 scripting.

The StrCutByWidth function can then be used to align some text:

main global script:
Code: ags
// main global script file

String StrCutByWidth_Tail;
String StrCutByWidth(String input, int width, int font) {

Ã,  Ã,  String temp = "";
Ã,  Ã,  String output = "";
Ã,  Ã,  StrCutByWidth_Tail = "";
Ã,  Ã, 
Ã,  Ã,  int i = 0;
Ã,  Ã,  int tail_index = 0;
Ã,  Ã, 
Ã,  Ã,  while (i < input.Length)
Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã,  temp = temp.AppendChar(input.Chars[i]);
Ã,  Ã,  Ã,  Ã,  
Ã,  Ã,  Ã,  Ã,  // if there is a space character or the end of string *ahead*:
Ã,  Ã,  Ã,  Ã,  if ((input.Chars[i+1] == ' ') || (i+1 == input.Length))
Ã,  Ã,  Ã,  Ã,  {
			if (GetTextWidth(temp, font) <= width)
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, output = temp;
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, tail_index = i + 1;
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  }
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  else
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, i = input.Length; // abort the while loop;
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  }
Ã,  Ã,  Ã,  Ã,  }
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  
Ã,  Ã,  Ã,  Ã,  i++;
Ã,  Ã,  }
Ã,  Ã,  
Ã,  Ã,  
Ã,  Ã,  if (tail_index < input.Length)
Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã,  // skip a space character unless it's beginning of the string:
Ã,  Ã,  Ã,  Ã,  i = tail_index + (tail_index > 0);
Ã,  Ã,  Ã,  
Ã,  Ã,  Ã,  Ã,  while (i < input.Length)
Ã,  Ã,  Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  StrCutByWidth_Tail = StrCutByWidth_Tail.AppendChar(input.Chars[i]);
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  i++;
Ã,  Ã,  Ã,  Ã,  }
Ã,  Ã,  }
Ã,  Ã,  
Ã,  Ã,  return output;
}


Code: ags
function FrameEx(String message) {

Ã,  Ã,  int width = FrameList.Width;
Ã,  Ã,  int font = 0;
Ã,  Ã,  
Ã,  Ã,  FrameList.AddItem( StrCutByWidth(message, width, font) );
Ã,  Ã,  
Ã,  Ã,  int count = 1;
Ã,  Ã,  
Ã,  Ã,  while (StrCutByWidth_Tail.Length > 0)
	{
Ã,  Ã,  Ã,  Ã,  FrameList.AddItem( StrCutByWidth(StrCutByWidth_Tail, width, font) );
Ã,  Ã,  Ã,  Ã,  count++;
	}
	
	int i = count;
	if (FrameList.ItemCount > 100)
	{
		while (i > 0)
		{
			FrameList.RemoveItem(0);
			i--;
		}
	}
	
	FrameList.TopItem = FrameList.ItemCount - count; 
}


Also, note int font = 0; there. With AGS v2.71, you should manually change it to the font number of the FrameList listbox.

See if this can be of some help...

Anarcho

Sorry for the delay in responding to this (i got distracted with other things), but thanks Ashen and Scorpiorus.  That code seems to be working Scorpiorus.  My only issue now is being able to scroll up and down through previous entries in the list.  Is there a ScrollUp or ScrollDown function for lists?  Or just inventories?  I can't seem to find one.

As it is, I could just make sure that each hotspot description or random message fits within the list box, but I anticipate having longer messages that you would need to scroll down to read.  How should I go about doing this?

Thanks for the help,

Logan


Gilbert

For lists you need to set the TopItem property to do "scrollings".

Anarcho

Ok, I believe I've already set the TopItem property...I'm using Scorpiorus's code above.  My question now is (and by the way, I'm now using 2.72), where do you place the code for my up and down buttons for the listbox.   So for my scroll up button, I've set the script name to ScrollButtonUp and I've set it to Run Script in the little GUI control panel...and I'd like to give the button this script:

function FrameButtonUp_Click(GUIControl *control, MouseButton button) {
  FrameList.ScrollUp(); 
 
  }
 
function FrameButtonDown_Click(GUIControl *control, MouseButton button) {
  FrameList.ScrollDown();   
 
  }

which will hopefully scroll up the listbox.  Though I'm not really sure that this would work.  Now where do I place this script?  I take it also have to import these functions too?


Khris

Double click the button in the gui editor, AGS will add the function at the end of the global script, open the script's window and take you there. Then add the code inside.

There's no need to import the functions.

Anarcho

Am I crazy, or does it not explain that in the manual under "Buttons"?

Thanks!


SMF spam blocked by CleanTalk