[SOLVED] Custom inventory GUI blinking from SayBackground, hover text not displaying

Started by RootBound, Fri 20/01/2023 22:18:50

Previous topic - Next topic

RootBound

Hey all. Wish I weren't posting for help again so soon after the last time, but here we are. :(

I have been testing out small blocks of code in a mostly empty default template game, and those block work perfectly there. Unfortunately, when I write the same code in my actual game, they don't work anymore.

Here are the issues, which I theorize are related because they both have to do with the custom inventory GUI:

1. I have a speech-based countdown timer running. In the test game it works perfectly. In my real game it causes the inventory GUI to flicker once per second as the timer counts down. I know it's the timer that causes it because when I remove the timer block, the blinking stops. There's no such behavior in the test game, however.

2. There's also a hovering text label that follows the cursor and gives the name of whatever inventory item is under the cursor. It runs perfectly in the test game. In the real game the hover text does not show up at all (the label is marked enabled, visible, and clickable in settings).


I have scanned the code multiple times trying to figure out what the discrepancy is. The settings for the inventory and hovertext GUIs are identical. The code itself, other than character names (cTimer vs. cRoger), inventory item names (iKey vs. iTest1) and GUI label numbers (Label1 vs. Label11), is also nearly identical. The timer is nested within an if statement in the real game (if dying == true), but removing that made no difference.

I then commented out every piece of the room script until I was left with only the relevant code, which still looks identical.

I am well and truly stumped. :(

I honesty can't find where the two rooms are significantly diverging, or what could be causing these issues. Many thanks and a place in the game credits for anyone who can help me solve this.

This is the room script where everything works perfectly:

Code: ags

// room script file

int min;
int sec;
String TimerText;
bool timeout;

function room_load()
{
  min = 2; //set number of minutes before timeout
  sec = 15; // set number of seconds before end of current minute
  timeout = false; //timer has not run out yet
    
  SetGameSpeed(40); // game loops per second
  
  SetTimer(1, 600);  // set minutes timer (seconds * 40) and whether initial minute expires in less than 59 seconds
  SetTimer(2, 40);  // set seconds timer
  
  cRoger.y = 100;
  
  cRoger.AddInventory(iCup);
  InvItemTotal ++;
  cRoger.AddInventory(iKey);
  InvItemTotal++;
}

function repeatedly_execute_always()
{
if (IsTimerExpired(1))                              //check minutes timer
  {
  min -=1;   // decrease counter by 1 minute
  SetTimer(1,  2360); //reset timer for another minute
  
    if (min == -1) // keep minutes from going below 0
    {
    min = 0;
    }
  }
  
  if (IsTimerExpired(2))   // check seconds timer
  {
    sec -=1;
    
    if (sec >=10)
    {
      TimerText = String.Format("%d:%d", min,  sec); // countdown from 60 to 10
      cRoger.SayBackground(TimerText);
      SetTimer(2,  40); //trigger next code block
    }
    else if (sec <10 && sec >-1)
    {
      TimerText = String.Format("%d:0%d", min,  sec);   // count from 9 to 0 and switch format from "9" to "09" etc.
      cRoger.SayBackground(TimerText);
      SetTimer(2,  40);
      if (sec == 0 && min == 0 && timeout == false)
      {
        sec +=1; // cancel out seconds countdown
        timeout = true; // time has run out
        SetTimer(3,  180); // how long to display final second of timer (0:00)
      }
      if (sec == 0 && min == 0 && timeout == true && IsTimerExpired(3) == false)
      {
        sec +=1;
      }
      
    }
    if (sec == -1 && timeout == false)
    {
    sec = 59;  // reset to keep seconds from counting into negative numbers and change format back to 2 digits
    TimerText = String.Format("%d:%d", min,  sec);
    cRoger.SayBackground(TimerText);
    SetTimer(2, 40);
    }
  }
  
}
function room_AfterFadeIn()
{

}

function oHandbag_AnyClick()
{
  if (gInventory.Visible == false)
    {
        gInventory.Visible = true;
        gInventory.Y = oHandbag.Y;
        gInventory.X = (oHandbag.X -1) - (InvItemTotal * 26);
    }
  else if (gInventory.Visible == true) 
      {
        gInventory.Visible = false ;
      }
}

function room_RepExec()
{
  InventoryItem *InvUnderMouse;
  InvUnderMouse = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);

  if (InventoryItem.GetAtScreenXY(mouse.x, mouse.y) == null)
  {
    gInvLabel.Visible = false;
  }
  else
  {
    gInvLabel.Visible = true;
    gInvLabel.X = mouse.x;
    gInvLabel.Y = mouse.y - 20;
    Label1.Text = InvUnderMouse.Name;
  }
}



And this is the code from the room with problems:

Code: ags

// room script file
int min;
int sec;
String TimerText;
bool timeout;

function room_Load()
{
  Mouse.Mode = eModePointer;
  
  min = 1; //set number of minutes before timeout
  sec = 31; // set number of seconds before end of current minute
  timeout = false; //timer has not run out yet
    
  SetTimer(1, 1300);  // set minutes timer (seconds * 40) and whether initial minute expires in less than 59 seconds
  SetTimer(2, 40);  // set seconds timer
  
  cRoomController.AddInventory(iTest1);
  cRoomController.AddInventory(iTest2);
  cRoomController.AddInventory(iTest3);
  InvItemTotal +=3;
}

function repeatedly_execute_always()
{
 
  
    if (IsTimerExpired(1))                              //check minutes timer
    {
      min -=1;   // decrease counter by 1 minute
      SetTimer(1,  2360); //reset timer for another minute
  
      if (min == -1) // keep minutes from going below 0
      {
      min = 0;
      }
    }
  
    if (IsTimerExpired(2))   // check seconds timer
    {
      sec -=1;
    
      if (sec >=10)
      {
      TimerText = String.Format("%d:%d", min,  sec); // countdown from 60 to 10
      cTimer.SayBackground(TimerText);
      SetTimer(2,  40);
      }
      else if (sec <10 && sec >-1)
      {
        TimerText = String.Format("%d:0%d", min,  sec);   // count from 9 to 0 and switch format from "9" to "09" etc.
        cTimer.SayBackground(TimerText);
        SetTimer(2,  40);
      
        if (sec == 0 && min == 0 && timeout == false)
        {
          sec +=1; // cancel out seconds countdown
          timeout = true; // time has run out
          SetTimer(3,  180); // how long to display final second of timer (0:00)
          DisplayAtY(10, "Crap, what is... Feels like I'm falling.");
        }
        if (sec == 0 && min == 0 && timeout == true && IsTimerExpired(3) == false)
        {
        s  ec +=1;
        }
      
      }
      if (sec == -1 && timeout == false)
        {
        sec = 59;  // reset to keep seconds from counting into negative numbers 
        TimerText = String.Format("%d:%d", min,  sec);  //change format back to 2 digits
        cTimer.SayBackground(TimerText);
        SetTimer(2, 40);
        }
   
    }
  
}




function oHandbag_AnyClick()
{
  if (gInventory.Visible == false)
  {
    gInventory.Visible = true;
    gInventory.Y = oHandbag.Y;
    gInventory.X = (oHandbag.X -1) - (InvItemTotal * 28);
  }
  else if (gInventory.Visible == true) 
    {
      gInventory.Visible = false ;
    }
}

function room_RepExec()
{
  InventoryItem *InvUnderMouse;
  InvUnderMouse = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);

  if (InventoryItem.GetAtScreenXY(mouse.x, mouse.y) == null)
  {
    gInvLabel.Visible = false;
  }
  else
  {
    gInvLabel.Visible = true;
    gInvLabel.X = mouse.x;
    gInvLabel.Y = mouse.y - 20;
    Label11.Text = InvUnderMouse.Name;
  }
}
  



What am I missing?  ???
J. They/them. Here are my most recent games:

Snarky

Your first issue could have to do with the General Setting "When player interface is disabled, GUIs should...", if that differs between your test game and real game. Try making sure that it is set to "display normally."

Your second issue, if I understand it correctly (it should display a label over your inventory), might have to do with the z-order of the GUIs. Check that gInvLabel.ZOrder is set to a higher value than that of the inventory GUI itself, or it will be displayed behind it.

Snarky

#2
BTW, the way you're doing the timer is rather more complicated than necessary.

1. Rather than keeping two separate code branches just to add a 0 when the seconds-counter is in single digits, you can use the automatic 0-padding formatting style:

Code: ags
// This will always display sec with two digits
TimerText = String.Format("%d:%02d", min, sec);

2. It would be a lot easier to not keep track of the minutes and seconds separately, but only the actual remaining time, and just convert it into minute and second parts for display:

Code: ags
int totalSec;

function room_load()
{
  int totalSec = 2*60 + 15;
  // ...
}

function repeatedly_execute_always()
{
  // ...
  // Divide by 60 to give the number of minutes,
  // take the remainder to give just seconds within the minute
  TimerText = String.Format("%d:%02d", totalSec/60, totalSec % 60);
}

Then you don't need all the logic for when the minute changes; you only need to test whether the total countdown has reached the end.

3. If you're already keeping manual countdown variables, you don't really need timers at all. At most a single timer to give you a "tick" per second, just for convenience.

So taken all together, the timer code can be simplified to:

Code: ags
// room script file

int totalSec;

function room_Load()
{
  totalSec = 1*60 + 30;
  SetTimer(1, GetGameSpeed());  // set "seconds tick" Timer
}

function repeatedly_execute_always()
{
  // This runs once every second while timeout displayed
  if (IsTimerExpired(1))
  {
    if (totalSec > 0)
      cTimer.SayBackground("%d:02d", totalSec/60, totalSec%60);
    else
      cTimer.SayBackground("0:00");
    if (totalSec == 0)
      DisplayAtY(10, "Crap, what is... Feels like I'm falling.");

    totalSec--; // Count down our timer
    // How long we keep re-displaying 0:00 after the timeout has ended
    // (the time for DisplayAtY to time out comes on top of this)
    if (totalSec > -5)
      SetTimer(1, GetGameSpeed());
  }
}

RootBound

Hi Snarky,

Thanks so much for your response! I changed the general settings as you suggested which fixed the blinking issue. Much appreciated.

Changing the ZOrder on the floating label unfortunately did nothing, but I managed to fix it somehow by moving the code block from rep_exec to rep_exec_always. I have no idea what was blocking it before, but I'm not complaining.

Also, thanks for your code to simplify the timer -- it seems so simple reading it, but my brain goes to needlessly complicated logic before it goes to simple math.   :)    Also I didn't know about the automatic 0-padding which is awesome.

Thanks again for your help! You and the others who've helped me out here will get a mention in the acknowledgements for sure.


J. They/them. Here are my most recent games:

SMF spam blocked by CleanTalk