• Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

 feature request - draw_mask()

csanyk

Member
Back in the GMS1.x days, I had made a feature request in the old Suggestion Box forum to add a draw function that would draw the collision mask of the calling object. I thought that it would be a wonderful aid in debugging collisions, if the collision masks could be drawn visible so I could verify that they were the size and shape and position that I thought they were.

Since the old forum is hidden, I can't go back easily and recall what the response was, but I believe that I was told "we're not going to consider it for 1.x, and we're not taking suggestions here for 2.x", or something to that effect.

So, if it's OK to ask for it now, I'd like to.
 

rwkay

GameMaker Staff
GameMaker Dev.
Well this is trickier than it sounds as the collision mask is not stored in a way that can be rendered easily, it is not stored on a texture but in a CPU addressable manner as all the collision happens on the CPU.

It's not impossible just trickier than it may appear at first.

Russell
 

Mike

nobody important
GMC Elder
The mask does not exist as an image, so we can't draw it.

Would therefore have to be an IDE option to create an image for it, then you'd have to have a resource name for it - as all resources have a name/id so you can address it. Not a quick thing to add.
Not a no.... but very low on the list.

EDIT: Ninja'd!
 

csanyk

Member
The mask does not exist as an image, so we can't draw it.

Would therefore have to be an IDE option to create an image for it, then you'd have to have a resource name for it - as all resources have a name/id so you can address it. Not a quick thing to add.
Not a no.... but very low on the list.

EDIT: Ninja'd!
Hmm, I would think it'd be possible for the CPU to turn the mask data into an image, at run time, and then this image could then be drawn using a draw_mask() function. I don't understand GMS under the hood to know why that's not a feasible way to do it... I do take you at your word, though. Thanks for considering the suggestion, and I hope that it can be included at some point. :)
 
R

renex

Guest
I would think it'd be possible for the CPU to turn the mask data into an image, at run time
Hundreds upon hundreds of position_meeting and writing to a buffer. Throw buffer at surface, draw surface!

Just mind the long pause :p
 

Hyomoto

Member
I may be misunderstanding you, but if your collision mask is a sprite, but that should be as simple as drawing the sprite to the screen with the current rotation. If it's not, you can still draw it if you know the points and shape of the bounding box using any number of methods including draw_rectangle, draw_circle or draw_primitive.
 

csanyk

Member
I may be misunderstanding you, but if your collision mask is a sprite, but that should be as simple as drawing the sprite to the screen with the current rotation. If it's not, you can still draw it if you know the points and shape of the bounding box using any number of methods including draw_rectangle, draw_circle or draw_primitive.
I suppose I could just always use sprites for collision masks, and then I could draw them with confidence, but that's sure a lot of extra work to do, for each and every object in each and every project. A built in function would be a vastly more preferable solution.

I'm talking about having a way to visually render the mask when the mask is not a sprite, though.

I *could* write my own functions, to draw what I think is the correct collision mask, and it will only be as accurate as my understanding of how GMS2 determines the mask, and my ability to code it correctly. That's not as reliable and therefore not as useful. I'm not confident that I have the understanding to do it.

Is the bounding box of a sprite synonymous with the sprite's collision mask? I didn't think it was.
 

Jobo

Member
GMC Elder
You don't have access to the necessary information at runtime to generate accurate collision mask representations (tolerance + bbox mode).
 

Hyomoto

Member
It depends on the sprite. By default, all sprites use precision collisions which is pixel perfect. GM2 allows you to set the alpha tolerance, which means your collisions may not match the sprite perfectly as some pixels are discarded, but generally this should be a very minor issue since you are in control of that. That is to say, if yo For the other types of collisions it's a bit more complicated once you start using rotation, but even in those cases you could simplify it by drawing your own mask, setting that as the collision mask for the sprite and then drawing that.

It's a bit more difficult to draw the others since you have to maths and that could induce human error, but if you are only using sprite-based collisions, drawing the sprite should be accurate enough. While seeing specifically what the CPU is using could be useful, it's supposed to be based on what you gave it in the first place and therefore the source material should be fine as a reference.
 

Cpaz

Member
The mask does not exist as an image, so we can't draw it.

Would therefore have to be an IDE option to create an image for it, then you'd have to have a resource name for it - as all resources have a name/id so you can address it. Not a quick thing to add.
Not a no.... but very low on the list.

EDIT: Ninja'd!
Interesting. Though, I thought it was a given that the collision mask isn't a sprite. Even when you set it to a sprite. It would be more along the lines of a polygon... Right? A shape with points based off of the given image.

You don't have access to the necessary information at runtime to generate accurate collision mask representations (tolerance + bbox mode).
I also find the fact interesting. If this is the case, then how does GM get the information, and use it for that matter? This begs many odd questions about the inner workings of GM...
Or i'm just looking too much into it. Either way.
 

Hyomoto

Member
As I mentioned, it gets that information from the sprite itself. Which means that while you do not have access to specifically what's being used in memory, you do have the template that was used. Barring any major bugs in GM2 itself, it should be sufficient to draw conclusions from that.
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
As I mentioned, it gets that information from the sprite itself. Which means that while you do not have access to specifically what's being used in memory, you do have the template that was used. Barring any major bugs in GM2 itself, it should be sufficient to draw conclusions from that.
As @Jobo has already mentioned, you do not have access to "alpha tolerance" nor "mask type" at runtime - in fact, these are not even stored - the only things that are stored are whether it's a rectangle mask or a price mask, and the mask(s) themselves. Therefore any such workarounds would rely on writing an exact replica of algorithm used by GMS (not too simple for ellipses/diamonds and can change in future) and filling out data for all your sprites somehow (hopefully, not manually). Not very desirable.

I also find the fact interesting. If this is the case, then how does GM get the information, and use it for that matter? This begs many odd questions about the inner workings of GM...
Or i'm just looking too much into it. Either way.
In "game data" file, masks are stored as nicely packed 1-bit sequences, padded at pixel row endings.
At runtime, they are likely stored as boolean/byte 2d arrays (for performance).
Neither of those is suitable for drawing as-is.
However, you could make either of two suitable for drawing by creating sprites/surfaces for them at runtime.
And, a little-known fact, your game is permitted to read it's own "data file", meaning that you have access to all asset information that the runtime can use, provided that you can figure out the format.
I whipped up a demo that reads it's own file to retrieve mask data and generate surfaces for them:
https://www.dropbox.com/s/8qwoktkfscwgkcx/draw_mask_ext.zip?dl=0

As a funny coincidence, while doing so, I found a bug in mask generation algorithm (4th image of "bock!" sprite gets a mask of the "cloud" sprite for mysterious reason - both in data and when checked with position_meeting), which could have gone unnoticed for some time due to lack of this exact thing.

If functions were to be added, these would need to be not the functions to draw the mask, but to get the mask bit of given image at given XY. Then you could do whatever you want with that and at a minimal overhead.
If not, you can always use smart (pictured) or straightforward (position_meeting) tricks to generate mask images at game start.
 

Attachments

Last edited:

Hyomoto

Member
I love you @YellowAfterlife. You are clearly very intelligent, but at the same time you blow my mind with your examples. Yes, you don't have access to that information at runtime, but you build the resources the game uses. You know whether or not a sprite is making use of a particular bounding box or alpha tolerance. In fact, building something to read the program data at runtime, while impressive, is like trying to solve an open window by building another house. You know the window is open, you just have to close it. GML doesn't have to know about this because you you already do. I mean, yes, you can do it your way and I have no doubts the man who wrote a GML interpreter in GML would be able to, but like your other suggestions I have to ask: is that really the best, simplest or even most useful solution to the problem? Is it not easier to simply draw the sprite, know your alpha tolerance and draw conclusions from that? I'm guessing based on your answer that you say no, but like our previous discussion I can't see eye-to-eye with you on this.

It's either create an elaborate system to visualize a pixel perfect representation or draw the sprite and use your own knowledge of how you set up your game to draw conclusions. If you need the other bounding box types, it is more difficult to draw an correct ellipse or rectangle for representation sure, but in those cases you could literally draw the bounding box you wanted as another sprite and use that as your mask. That's a lot simpler, especially if the only purpose for this code is testing. You are truly my favorite person posting. I know that feeling is hardly mutual, but it's like watching the world's smartest man suggest the best way to figure out if your car is in the garage is to build a network of sensors rather than just, you know, look in the garage. I well and truly love reading your posts.

Then again, I'm the only person who suggested this so maybe I've been doing it wrong.
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
I love you @YellowAfterlife. You are clearly very intelligent, but at the same time you blow my mind with your examples. Yes, you don't have access to that information at runtime, but you build the resources the game uses. You know whether or not a sprite is making use of a particular bounding box or alpha tolerance. In fact, building something to read the program data at runtime, while impressive, is like trying to solve an open window by building another house. You know the window is open, you just have to close it. GML doesn't have to know about this because you you already do. I mean, yes, you can do it your way and I have no doubts the man who wrote a GML interpreter in GML would be able to, but like your other suggestions I have to ask: is that really the best, simplest or even most useful solution to the problem? Is it not easier to simply draw the sprite, know your alpha tolerance and draw conclusions from that? I'm guessing based on your answer that you say no, but like our previous discussion I can't see eye-to-eye with you on this.

It's either create an elaborate system to visualize a pixel perfect representation or draw the sprite and use your own knowledge of how you set up your game to draw conclusions. If you need the other bounding box types, it is more difficult to draw an correct ellipse or rectangle for representation sure, but in those cases you could literally draw the bounding box you wanted as another sprite and use that as your mask. That's a lot simpler, especially if the only purpose for this code is testing. You are truly my favorite person posting. I know that feeling is hardly mutual, but it's like watching the world's smartest man suggest the best way to figure out if your car is in the garage is to build a network of sensors rather than just, you know, look in the garage. I well and truly love reading your posts.

Then again, I'm the only person who suggested this so maybe I've been doing it wrong.
As topic author has mentioned, the reasoning behind the suggestion is debugging, therefore it is desired that the setup is as simple as possible.

If you are the person that is adding the sprites and you are sure that you did not do anything unusual with alpha tolerance settings, shapes, or mask-sprites, then yes, you can just draw those and judge by that. But then you probably don't have a problem that requires debugging this in the first place.

If working on a project with multiple people, you might not be sure that all is well with sprites.
Similar goes for contract work - often there are situations where no one can answer you why something works the way it does because it was done years ago.
In larger games there is often a point where you can no longer be sure that everything is made correctly by plain chance of human error. For example, Nuclear Throne has 2000+ sprites total. Hyper Light Drifter has over 3000.

So it is valuable to have a couple of scripts that can be inserted into any project when needed and would do the job no matter the circumstances.
 
Top