SOLVED Out of curiosity, Is there a better way of doing this?

flyinian

Member
Out of curiosity, Is there a better way of doing this?

This is for a mouse hover highlight for a button.

I was trying to get my navigation system for my game to not execute the button highlighting per step.

This took me awhile to figure this out, a different version of this was executing the code per step. Didn't realize it until I added a debug message for testing.


GML:
_SpriteBackgroundSubImage = 0: // no highlight
_SpriteBackgroundSubImage = 1: //  highlight

if (position_meeting(mouse_x, mouse_y, _Object) && _SpriteBackgroundSubImage == 0) // If mouse is over menu button and isn't highlighted
{   
    
    _SpriteBackgroundSubImage = 1;        // Sprite's border will be highlighted on mouse hover
    show_debug_message("Menu Type 2 Button Mouse Over Highlight");
    
};

if (!position_meeting(mouse_x, mouse_y, _Object) && _SpriteBackgroundSubImage == 1) // If mouse is over menu button and is highlighted
{   
    
    _SpriteBackgroundSubImage = 0;        // Sprite's border will not be highlighted on mouse hover
    show_debug_message("Menu Type 2 Button Mouse Over no Highlight");
    
};
Thank You.
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
You could at least do:
Code:
_SpriteBackgroundSubImage = 0: // no highlight
_SpriteBackgroundSubImage = 1: //  highlight

if (position_meeting(mouse_x, mouse_y, _Object)) // If mouse is over menu button
{   
    if (_SpriteBackgroundSubImage == 0) // ... and isn't highlighted
    {
        _SpriteBackgroundSubImage = 1;        // Sprite's border will be highlighted on mouse hover
        show_debug_message("Menu Type 2 Button Mouse Over Highlight");
    };
};
else
{
    if (_SpriteBackgroundSubImage == 1) // If mouse is over menu button and is highlighted
    {
        _SpriteBackgroundSubImage = 0;        // Sprite's border will not be highlighted on mouse hover
       show_debug_message("Menu Type 2 Button Mouse Over no Highlight");
    }
};
You could also only execute the code if the mouse cursor position has changed, but I would suggest to first see if this is causing you any real trouble (via Profiler)
 

NightFrost

Member
This took me awhile to figure this out, a different version of this was executing the code per step
Well yes, but it still needs to run something every step. You're just seeing the debug messages on some of your code execution, not all of it. This is micro optimization, so not something much or any time should be spent early on, but when you do this:
Code:
if(meeting){
    subimage = 1;
} else {
    subimage = 0;
}
You are checking for collision AND setting the variable to some value every step. When you do this:
Code:
if(meeting){
   if(image == 0){
      image = 1;
   }
} else {
   if(image == 1){
      image = 0;
   }
}
You are checking for collision AND comparing the variable every step (and setting it sometimes). Retrieveing the variable value and comparing it against some other value is probably sliiiiightly slower than just setting it regardless of previous value. You are spending time to check the value to decide whether or not spend time to set the value. In situations where previous value bears no relevance to code, I just set and go.
 

TailBit

Member
You are pretty much turning it into the same value as position_meeting returns:

So you could maybe just do it in one line?
GML:
_SpriteBackgroundSubImage = position_meeting(mouse_x, mouse_y, _Object);
 

Bart

WiseBart
Why not just do this:
GML:
_SpriteBackgroundSubImage = position_meeting(mouse_x, mouse_y, _Object);           // Rely on implicit conversion of boolean to real
You need to do that position_meeting check once per step anyway.

Or you can use the ternary operator for improved readability:
GML:
_SpriteBackgroundSubImage = position_meeting(mouse_x, mouse_y, _Object) ? 1 : 0;    // Clearly state which value we're assigning

For the debug message you can do it like this:
GML:
var msg; msg[0] = "no"; msg[1] = "";
var no = msg[_SpriteBackgroundSubImage];
show_debug_message("Menu Type 2 Button Mouse Over " + no + " Highlight");

This way you don't need a single if in your code.
 

flyinian

Member
So, when it comes down to code executing every step, I should examine the profiler and see if the code in question is an issue?

Just because code is executing every step, doesn't necessary mean its bad and I should investigate with the debugger/profiler?

edit:

Could the fps dropping from 6k to 4k then down to 3k and less fps be a sign of code being executed per step?

The original button highlight code I had(not the one in the op) is tanking my performance. So, i'll being changing that and looking through my code and changing any code being executed per step that shouldn't be.

Thanks for the help, everyone.
 
Last edited:
It's generally fine to ignore FPS drops when it's roughly over the 500 mark, as small changes in actual execution speed can lead to rather large drops in FPS because of the way GMS is structured (that doesn't mean there's literally no point in paying attention to it, but don't worry about optimisations like that until it's actually negatively affecting player experience, and in terms of player experience there is no difference between 500 and 6k fps).

Executing code per step is -entirely- necessary and I think too many amateur users worry about FPS drop unnecessarily. It is totally fine to run many large chunks of code per step. Once the game actually starts to chug on your test machine/s, THEN think about optimisation and dive into the profiler and start examining what sections of code are causing the slow down and figuring out ways to streamline it. Always remember, your development time is more limited than CPU cycles nowadays, so letting the CPU work a bit harder so you have more time to actually finish your project is more important than micro-optimisations.

Knuth's Law
“Premature optimization is the root of all evil (or at least most of it) in programming.” This law - or I should say one of the most famous quotes from Donald Knuth - reminds us that you should never try to optimize the code of an application too early, or until it is actually necessary.
Whether it is a "law" or not, it is good advice for finishing projects.
 

flyinian

Member
It's generally fine to ignore FPS drops when it's roughly over the 500 mark, as small changes in actual execution speed can lead to rather large drops in FPS because of the way GMS is structured (that doesn't mean there's literally no point in paying attention to it, but don't worry about optimisations like that until it's actually negatively affecting player experience, and in terms of player experience there is no difference between 500 and 6k fps).

Executing code per step is -entirely- necessary and I think too many amateur users worry about FPS drop unnecessarily. It is totally fine to run many large chunks of code per step. Once the game actually starts to chug on your test machine/s, THEN think about optimisation and dive into the profiler and start examining what sections of code are causing the slow down and figuring out ways to streamline it. Always remember, your development time is more limited than CPU cycles nowadays, so letting the CPU work a bit harder so you have more time to actually finish your project is more important than micro-optimisations.

Whether it is a "law" or not, it is good advice for finishing projects.
Sounds good, Thank You for the clarification.
 

flyinian

Member
It's generally fine to ignore FPS drops when it's roughly over the 500 mark, as small changes in actual execution speed can lead to rather large drops in FPS because of the way GMS is structured (that doesn't mean there's literally no point in paying attention to it, but don't worry about optimisations like that until it's actually negatively affecting player experience, and in terms of player experience there is no difference between 500 and 6k fps).

Executing code per step is -entirely- necessary and I think too many amateur users worry about FPS drop unnecessarily. It is totally fine to run many large chunks of code per step. Once the game actually starts to chug on your test machine/s, THEN think about optimisation and dive into the profiler and start examining what sections of code are causing the slow down and figuring out ways to streamline it. Always remember, your development time is more limited than CPU cycles nowadays, so letting the CPU work a bit harder so you have more time to actually finish your project is more important than micro-optimisations.

Whether it is a "law" or not, it is good advice for finishing projects.
For clarification,

When you said,

"Executing code per step is -entirely- necessary and I think too many amateur users worry about FPS drop unnecessarily. "

Do you mean the start of a function?

or the code that goes into a function?

Correct me if I'm wrong... VVV

GML:
if(check)    // This line of code is ran per step, if it does not return "true" it will not execute its following code. This is what you meant by, "Executing code per step is -entirely- necessary and I think too many amateur users worry about FPS drop unnecessarily. "
{
// This is where the performance drops if this is ran per step and this should be avoided. This is not what you meant by, "Executing code per step is -entirely- necessary and I think too many amateur users worry about FPS drop unnecessarily. "

Variable = obj_object.id;        // The performance drops depending on what code is executing and how much.


}
 
No, I mean it's entirely dependent on the code you want to execute. Sometimes, people seem afraid of running a code block every step. They should not be. If you need that code to run every step, run it every step. Of course, if you want it ONLY to run if a certain condition is met, then check that condition each step with an if statement and execute the code when that condition is met.
 

flyinian

Member
No, I mean it's entirely dependent on the code you want to execute. Sometimes, people seem afraid of running a code block every step. They should not be. If you need that code to run every step, run it every step. Of course, if you want it ONLY to run if a certain condition is met, then check that condition each step with an if statement and execute the code when that condition is met.
Ah, thank you.
 
Top