GUI.Y co-ordinates are out of range

Started by Blondbraid, Wed 10/01/2018 17:28:01

Previous topic - Next topic

Blondbraid

Hi, I've been experimenting with trying to make text for hotspots appear near the mouse when players move it over the hotspots, the script I use is:

gGui1.SetPosition(mouse.x + 10, mouse.y + 10);

under repeatedly execute in the global script. It works and looks fine until I move the mouse too close to the edge of the window, because then the game crashes and I get a message saying that the GUI.Y co-ordinates are out of range, how can I prevent this?


Crimson Wizard

#1
I keep forgetting to fix this, AGS has some weird condition that if GUI is moved out of room background, then it stops the game.

Anyway, there are two methods, depending on how you want your gui to act.
If you need something to stay on screen at all times, like hotspot description, then use X, Y, Width and Height to ensure it does not go over viewport range.

Code: ags

int x = mouse.x + 10;
int y = mouse.y + 10;
if (x < 0)
    x = 0;
if (y < 0)
   y = 0;
if (x + gGui1.Width > System.ViewportWidth)
    x = System.ViewportWidth - gGui1.Width;
if (y + gGui1.Height > System.ViewportHeight)
    y = System.ViewportHeight - gGui1.Height;
gGui1.X = x;
gGui1.Y = y;


If you allow it to go out of screen, then simply check for coordinates to go over the viewport range and make it invisible and then visible again.
But I guess this is not your case.

Blondbraid

Thank you, but I'm afraid that I don't understand how I should use the code you provided in the game script.
I tried putting it under gGui1.SetPosition(mouse.x + 10, mouse.y + 10); in the Global Script, but that didn't solve the problem.


Matti

You don't need gGui1.SetPosition, it's replaced by
Code: ags
gGui1.X = x;
gGui1.Y = y;


gGui1.SetPosition(x, y) should also work.

Blondbraid

Quote from: Matti on Wed 10/01/2018 20:13:11
You don't need gGui1.SetPosition, it's replaced by
Code: ags
gGui1.X = x;
gGui1.Y = y;


gGui1.SetPosition(x, y) should also work.
I tried disabling the line with gGui1.SetPosition, and it stopped the game from crashing when I moved the mouse towards the window border,
but then the hotspot description appeared at the top of the window instead of next to the mouse.


Crimson Wizard

#5
There is a typo in my script:

if (y > 0)
   y = 0;

Should be

if (y < 0)
   y = 0;

Blondbraid

Quote from: Crimson Wizard on Wed 10/01/2018 20:31:16
There is a typo in my script:

if (y > 0)
   y = 0;

Should be

if (y < 0)
   y = 0;
OK, I changed the typo and everything seems to be working, but the text sometimes appear far away from the cursor if the hotspot is near the right border, so I wonder, can I make the GUI text align in the middle when the cursor is near the right border?
There is also some overlap on the text and sprite when the cursor shifts to an inventory item, any advice how I can fix this?


Crimson Wizard

#7
Quote from: Blondbraid on Wed 10/01/2018 21:10:44
the text sometimes appear far away from the cursor if the hotspot is near the right border, so I wonder, can I make the GUI text align in the middle when the cursor is near the right border?

I think you might just resize the GUI & Label to match the text's width. E.g., assuming your label is the only thing on GUI and positioned at 0,0, try this
Code: ags

int width = GetTextWidth(lblHotspotName.Text, lblHotspotName.Font) + X; // replace X with small number (1,2,..) just for safety
lblHotspotName.Width = width;
gGui1.Width = width;


Quote from: Blondbraid on Wed 10/01/2018 21:10:44
There is also some overlap on the text and sprite when the cursor shifts to an inventory item, any advice how I can fix this?

Could you post screenshot, I am not sure I understand the situation correctly?

Blondbraid

Quote from: Crimson Wizard on Thu 11/01/2018 00:03:37
Quote from: Blondbraid on Wed 10/01/2018 21:10:44
the text sometimes appear far away from the cursor if the hotspot is near the right border, so I wonder, can I make the GUI text align in the middle when the cursor is near the right border?

I think you might just resize the GUI & Label to match the text's width. E.g., assuming your label is the only thing on GUI and positioned at 0,0, try this
Code: ags

int width = GetTextWidth(gGui1.Text) + X; // replace X with small number (1,2,..) just for safety
lblHotspotName.Width = width;
gGui1.Width = width;


Quote from: Blondbraid on Wed 10/01/2018 21:10:44
There is also some overlap on the text and sprite when the cursor shifts to an inventory item, any advice how I can fix this?

Could you post screenshot, I am not sure I understand the situation correctly?
I tried putting the script below the previous script, but I just got this message when I tried.
GlobalScript.asc(28): Error (line 28): Not enough parameters in call to function

As for the cursor overlapping the text, here is a screenshot of the problem:


Crimson Wizard

Quote from: Blondbraid on Thu 11/01/2018 10:33:25
I tried putting the script below the previous script, but I just got this message when I tried.
GlobalScript.asc(28): Error (line 28): Not enough parameters in call to function

Oh, duh, I forgot the second parameter to GetTextWidth. Also I said "gGui1.Text", while it should have been label's text:  GetTextWidth(lblHotspotName.Text, lblHotspotName.Font).

Quote from: Blondbraid on Thu 11/01/2018 10:33:25
As for the cursor overlapping the text, here is a screenshot of the problem:


Well, before making any fixes to the code, what would be the suitable solution from the design perspective? Do you want the text to be at same position, just above the item? Or moved aside?

Blondbraid

Quote from: Crimson Wizard on Thu 11/01/2018 10:54:26
Well, before making any fixes to the code, what would be the suitable solution from the design perspective? Do you want the text to be at same position, just above the item? Or moved aside?
I'd like the text to move aside from the cursor, the main priority is to have the text be clearly readable.
Quote
Oh, duh, I forgot the second parameter to GetTextWidth. Also I said "gGui1.Text", while it should have been label's text:  GetTextWidth(lblHotspotName.Text, lblHotspotName.Font).
I tried changing the last line of gGui1.Width = width; to GetTextWidth(lblHotspotName.Text, lblHotspotName.Font) = width; but then I got this message:
GlobalScript.asc(28): Error (line 28): undefined symbol 'lblHotspotName'


Snarky

Obviously you replace "lblHotspotName" with the name of the label that you use to display the hotspot name.

Also, your assignment should be the other way around, the way CW did it.

Crimson Wizard

#12
Quote from: Blondbraid on Thu 11/01/2018 16:56:30
I tried changing the last line of gGui1.Width = width; to ;

I think there is some misunderstanding here. You must not remove "gGui1.Width = width", that line should stay, because it sets GUI's width.
Line "width = GetTextWidth(lblHotspotName.Text, lblHotspotName.Font);" calculates width of text and stores that value in variable "width".

And yes, I used lblHotspotName as a placeholder name, because I did not know how you called your label.

Blondbraid

Alright, I changed the code:
Code: ags
int width = GetTextWidth(hotspottext.Text, hotspottext.Font) + 1; // replace X with small number (1,2,..) just for safety
hotspottext.Width = width;
gGui1.Width = width;

The game doesn't crash, but I see no visual difference from before either. What have I missed?


Khris

Just move up the GUI if the cursor mode is eModeUseinv:
Right after
Code: ags
int y = mouse.y + 10;

insert
Code: ags
if (mouse.Mode == eModeUseinv) y -= 20;

Blondbraid

Quote from: Khris on Thu 11/01/2018 22:24:00
Just move up the GUI if the cursor mode is eModeUseinv:
Right after
Code: ags
int y = mouse.y + 10;

insert
Code: ags
if (mouse.Mode == eModeUseinv) y -= 20;

Thanks, that solved the overlapping cursor!


Crimson Wizard

Quote from: Blondbraid on Thu 11/01/2018 22:16:59
Alright, I changed the code:
Code: ags
int width = GetTextWidth(hotspottext.Text, hotspottext.Font) + 1; // replace X with small number (1,2,..) just for safety
hotspottext.Width = width;
gGui1.Width = width;

The game doesn't crash, but I see no visual difference from before either. What have I missed?


If I recall right, the problem you were having was that
Quote from: Blondbraid on Wed 10/01/2018 21:10:44
everything seems to be working, but the text sometimes appear far away from the cursor if the hotspot is near the right border, so I wonder, can I make the GUI text align in the middle when the cursor is near the right border?


I decided to create a quick test game to be sure we have same thing before our eyes.
This is the script I am using (not necessarily matching yours 100%):

Code: ags

function repeatedly_execute() {
  /*
    /// This part is NOT IMPORTANT for this question
  */
  int x = mouse.x;
  int y = mouse.y;
  Hotspot *h = Hotspot.GetAtScreenXY(x, y);
  Object *o = Object.GetAtScreenXY(x, y);
  Character *c = Character.GetAtScreenXY(x, y);
  
  String text;
  if (h != null && h != hotspot[0])
    text = h.Name;
  else if (o != null)
    text = o.Name;
  else if (c != null)
    text = c.Name;
    
  if (String.IsNullOrEmpty(text)) {
    gGui1.Visible = false;
    return;
  }
    
  gGui1.Visible = true;
  hotspottext.Text = text;
  
  /*
    /// This part is RELATED to this question
  */
  x = mouse.x + 10;
  y = mouse.y + 10;
  if (x < 0)
      x = 0;
  if (y < 0)
      y = 0;
  if (x + gGui1.Width > System.ViewportWidth)
      x = System.ViewportWidth - gGui1.Width;
  if (y + gGui1.Height > System.ViewportHeight)
      y = System.ViewportHeight - gGui1.Height;
  gGui1.X = x;
  gGui1.Y = y;
  int width = GetTextWidth(hotspottext.Text, hotspottext.Font) + 1; // replace X with small number (1,2,..) just for safety
  hotspottext.Width = width;
  gGui1.Width = width;
}


What this code does: it adjusts the label width, which makes hotspot gui smaller, and text appears as close to the hotspot as possible. Or so it seems.

Blondbraid

I tried putting your code in, and it solved the problem with the text position, but now the problem with the overlapping cursor sprite is back,
where am I supposed to put the if (mouse.Mode == eModeUseinv) y -= 20; command?


Crimson Wizard

Quote from: Blondbraid on Fri 12/01/2018 17:25:02
where am I supposed to put the if (mouse.Mode == eModeUseinv) y -= 20; command?
Hmm, good question.
The problem here is that there may be several "overlapping" edge cases.

I think this may work for starters:
Code: ags

  x = mouse.x + 10;
  y = mouse.y + 10;
  if (mouse.Mode == eModeUseinv)
      y -= 20;


But then, if the hotspot is at the screen top, and you move the mouse too close to the screen border, it will be adjusted by the following code and overlap item again.

Blondbraid

Thank you, it seems to work, the sprites are no longer overlapping. However, I'm starting to feel like fore every problem that is solved, a new one pops up,
for the text over the hotspot doesn't disappear immediately after clicking on it, if walking, talking, a room transition or an animation is triggered by
clicking on a hotspot, item or character, the description text stays on the screen until the script has finished running.
How do I make the description text disappear after clicking on something?


SMF spam blocked by CleanTalk