• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Creating instances inside Draw/DrawGUI events: lessons learned

C

candlelight2007

Guest
There is nothing earth shattering in what I am about to say and to many seasoned GM2 devs here it is probably an obvious thing. But perhaps it will be useful to some newcomers like me who stumble into this later.
So after the first two weeks of digging through tutorials, manuals and forums, certain things slowly begin to make sense. One discovery that I made for myself that wasn't obvious to me at all is this. There are objects in my project that need instances of other objects to be drawn on top of them (think buttons inside a panel object). I would usually create them inside Draw (or Draw GUI) event. It all seemed to be working well and I was moving along with the project. Until at some point during debugging I added a show_debug_message to display the id of the instance of one of the objects that I created in Draw event. When I ran the game I suddenly discovered that Draw kept creating new instances continuously without me even realizing it! On the screen everything looked normal but the debug messages kept piling up with dozens of new instance ids. Not what i expected at all! When I checked, DrawGUI turned out to be doing the same thing.

I know I know. When I dug into the documentation, I found out that both Draw and DrawGUI apparently re-draw themselves every frame. What I ended up doing is adding instance_exists check wherever I had objects instantiated inside Draw event. Lesson learned. It may be by design but sure as heck it wasn't intuitive to me. So hopefully someone else might find this helpful. Cheers! ☺
 

Nidoking

Member
Much more helpful to newcomers is that you shouldn't be creating instances in a Draw or Draw GUI event. Draw events are for drawing. If you need graphics drawn, draw them with draw functions or create the instances in some other event, such as Create.
 
While I'm glad you learned this, I'm surprised at how much this comes across as something you might think is unique to GM. I mean, that's how rendering works, and not just for games, but for practically everything: draw a frame, then draw another one but slightly different from the last. Have enough frames per second, and you get motion. Otherwise, instead of measuring games by frames per second, we'd be doing it by frames per game :p
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Much more helpful to newcomers is that you shouldn't be creating instances in a Draw or Draw GUI event. Draw events are for drawing. If you need graphics drawn, draw them with draw functions or create the instances in some other event, such as Create.
This! ANd if you want something drawn above or below something else then use the layer system correctly or create it using the depth function and use depth correctly. :)

PS: Not dunking on you @candlelight2007 !!! It's great that you took the time to share this with the community and I'm sure someone will benefit from it! So thanks! Just want to point out to any future users finding this topic the "correct" way to do things. :) Oh, and good job on working out a solution, even if it's not really the "way it should be done"! Now, time to learn about layers and depth, so you can REALLY resolve the issue. Good luck!
 
C

candlelight2007

Guest
you shouldn't be creating instances in a Draw or Draw GUI event. Draw events are for drawing. If you need graphics drawn, draw them with draw functions or create the instances in some other event, such as Create.
Fair enough: more to learn. Appreciate the notions. But now I'm confused: I can create an instance in Create - that's what I tried doing in the first place - but I was unable to show it on top of whatever is drawn in Draw event. It is my understanding that in Draw you can't draw instances, you can only draw sprites. That's where I guess I strayed from what you say is the right path. Perhaps I misunderstand the concept. So what would be the right way?
 

Nidoking

Member
You seem to be confusing the act of creating an instance, which brings into existence an element of game logic, with the act of drawing graphics. Instances perform events. The Draw event is one event that every visible instance performs during every step. During the Draw event, instances can draw sprites, among other graphical elements. You can't draw an "instance" per se, because an instance is not itself a graphical element, but if it has a sprite assigned, it can draw that sprite using its assigned variables by calling draw_self(), for example. The existence of an instance does not inherently draw or not draw any particular graphical elements, except that if you don't define a Draw event at all, it has a default Draw event consisting entirely of draw_self(). During every game step, the screen is wiped (assuming you have a background defined), and then every visible instance performs its various Draw events. Every game frame is drawn afresh.

If you want your instances to draw in a particular order, use depth or layers. You need to read about those in the Manual.
 
C

candlelight2007

Guest
You seem to be confusing the act of creating an instance, which brings into existence an element of game logic, with the act of drawing graphics. Instances perform events. The Draw event is one event that every visible instance performs during every step. During the Draw event, instances can draw sprites, among other graphical elements. You can't draw an "instance" per se, because an instance is not itself a graphical element, but if it has a sprite assigned, it can draw that sprite using its assigned variables by calling draw_self(), for example. The existence of an instance does not inherently draw or not draw any particular graphical elements, except that if you don't define a Draw event at all, it has a default Draw event consisting entirely of draw_self(). During every game step, the screen is wiped (assuming you have a background defined), and then every visible instance performs its various Draw events. Every game frame is drawn afresh.
That's a pretty good lowdown. Appreciated. Yes, I probably am confusing those. I come with years of development experience but I have never done games, so this is new to me. Now I understand where I may have drifted off "the path". I am a big proponent of OOP and modular design so in an attempt to have distinct objects - say, a panel and some buttons that should be linked to (drawn on top of) the panel - so that they could be dynamically placed - I ended up including the instances of the buttons into the draw event of the panel object. Now I'm thinking, I probably should instead link the button objects using owner's id and that way they can be placed on "top" of the panel using depth or layers, while still remaining separate objects. I think that's what you get at. ☺ I'm going to refactor my code and see what comes out on the other end. Thanks again!
 
C

candlelight2007

Guest
Wow! That was easier than I thought. ☺ All I had to do was to move the instance creation code into Create event and this damn thing continued to work like nothing happened! I think now I realize why I was unable to show the objects on top of the another one initially - it was probably the depth/layer issue. Thanks @Nidoking! Things seem much clearer now. Hopefully this discussion itself will be helpful to someone who is just starting with GM2.
 
That exact same code in the step event would have created as much instances of that object.
But yeah, learn the rules before you break them!
 
C

candlelight2007

Guest
That exact same code in the step event would have created as much instances of that object.
Yes, that makes sense! Step event is another beast to me. I see people declare variables in Step event left and right and center and it always makes me wonder, doesn't it mean that the program will keep declaring them on every step over and over and over again? Wouldn't it make more sense to declare them in Create event, since it only runs once per instance? But this is a whole different topic altogether; I don't want to hijack the thread. :)
 
Yes, that makes sense! Step event is another beast to me. I see people declare variables in Step event left and right and center and it always makes me wonder, doesn't it mean that the program will keep declaring them on every step over and over and over again?
There is a concept in programming called Flow of Control. This is basically a bunch of conditions like "If this, then do that. Or else, if that, do this other thing".
There could be a million lines of code in your step event, and if this was in a condition that would never be true, it would never run those million lines of code at all. It would check every frame if the condition has changed, tho.
It really depends how it is all setup.

Wouldn't it make more sense to declare them in Create event, since it only runs once per instance?
Absolutely yes! Even more than that, using a variable that has NOT been declared should result in your game crashing when trying to access it.
 

Nidoking

Member
You've switched from talking about instances to talking about variables. You put things in the Create event if you want them to happen once, when the instance is created. You put them in the Step event if you want them to happen every step. If a variable's value should change every step, you put it in the Step event. You don't generally want to create the same instance every step.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
AHEM... ;)


As for variable declarations, if you see a variable being declared in the step event, the person is probably declaring local variables. These are a kind of "disposable variable" that is only around for the event it's created in then removed from memory. Some further reading for that too!

 

Nidoking

Member
if you see a variable being declared in the step event, the person is probably declaring local variables.
I don't believe this poster is distinguishing "declarations" from setting variables. Game Maker certainly doesn't. They don't appear to understand that there is (generally) no such thing as a reference variable, and that if you want x_plus_five to hold the value of the instance's x variable plus 5, you need to set it to x + 5 every time x changes, potentially every step. That's not going to be a local variable.
 
Top