Why not to use solid (Game Maker)
Skill Level: Experienced user (6)
Hey there. I’ve decided to write an article about why you shouldn’t use the built-in Game Maker solid variable. It’s common among many developers’ early games, and the reason is generally because it handles collision events for you decently well. However, though many developers use it, they generally don’t know how it actually works and therefore may run into problems with it that they can’t solve.
Solid, in case you don’t already know, is controlled by the little checkbox in the object properties next to visible (you can, however, control it through code by using the variable solid) Go to one of your objects which is solid, double click it, find the solid checkbox, and uncheck it now. Why should you do this? Because of wizardry.
(no, not really…)
So you want to know how solid really works? Well, it’s pretty simple actually. When actions or code is placed in a collision event for a solid object, the two objects cannot overlap. So if you have non-solid objPlayer, and solid objBlock, and you add a collision event in objPlayer for objBlock, then whenever objPlayer bumps into objBlock it will be kicked back to the last hopefully non-colliding position. Same thing with the block; if it happened to be moving and the player was stationary, the block still could not enter the player.
Now you may be wondering why I said, “hopefully” above. Well, if your object is moving and touches a solid object, it will be moved out of it. However, if the object starts there or gets placed overlapping the solid object, suddenly, you can’t move at all. And it’s not really your fault (aside from using solid) because you didn’t tell GM to do this; you just told GM to make the wall solid.
Actually, that is the very reason why you should get rid of it. Because you aren’t in control. What if at one point you want the object to go through walls? No good with solid; as long as there’s a collision event, the solid object will be un-passable. What are you to do?
If you turn solid off, all you have to do to keep a functional game is to program the collisions yourself. Take the more difficult path and collect the treasure at the end. Now, you can include conditionals, etc. in your collisions, without the omnipresent don’t-touch-the-wall-ever-mwahaha stuff. For a top-down maze game, you might use this code in the step event:
if (place_meeting(x+hspeed,y,objBlock1)) hspeed=0;
if (place_meeting(x,y+vspeed,objBlock1)) vspeed=0;
Notice we didn’t even have to use a collision event, at all.
One last thing that I feel I should mention. You can’t use the function place_free() when you aren’t using solid objects. Note, if you use actions, place_free() is equivalent to this one:
If a position is collision free
This is a small price to pay, as I will demonstrate, but I want to get it out there now that place_free()/the above action only returns true when there’s a collision with a solid object. If you never use solid, place_free() never returns true.
Anyways, the way to get around this small roadblock is by using place_meeting(), as I did in the code above. Action form:
If there is an object at a position
Anyways, place_meeting(), or the action shown above, is an alternate form of place_free() in that it also requires you to tell it the object to check for collisions with. But that means, if you have 15 different wall objects you have to use this function 15 different times, right? Right?!
Um, no. When have I ever steered you down such an annoying path? In fact, with a little creativity, you only have to use it once. The way you do this, is to make a new object, and call it objBlockParent.
You guessed it, this object will in fact be a dummy object with no code of its own, only to be used as the parent object of all block objects. Okay, maybe you didn’t guess that…
Once you’ve done that, you just plug that new object into place_meeting() as the final (third) argument (or into the action next to “object:”) and it checks for all objects which have objBlockParent as their parent. That is, a single function/action checks every single block object. Yay. The code example above could replace objBlock1 with objBlockParent and work in just this way.
You’ve just written your very own custom, functional wall collision code, and now you don’t have to worry that solid will mess you up later. Now that you have turned off solid, you can even make things like one-way platforms. I can’t possibly know how far you are in your current project, so it may or may not be feasible to go through and revamp your current wall collision engine to stop using solid. But be sure to remember this for future games.
If you have a technical question, such as “How do I do this” or “this is not working right” (relative to something with your Game Maker game after reading this tutorial), please head over to the Game Maker Community and ask there. I can’t answer any such questions in this blog and the members at the GMC will be more than capable to help you. For more info, go to this blog’s FAQ page. To discuss this article in particular, you can view it on the Game Maker Community.