Hello! I've been using GameMaker for about 3 weeks now, and I have fallen in love with it.
However, it does have a bit of a learning curve to really get cozy with it.
So I decided to compile and share some of the not-so-obvious things I've learned. I'm sure most of you that actually read this topic will know much of it already, but I wouldn't be surprised if even advanced users didn't know one or two of these.
First, this entire document assumes Advanced Mode is enabled.
File->Advanced Mode (make sure it is checked).
Second, a few preferences that make life a bit nicer:
File->Preferences
I suggest unchecking "show website button in main window"
I suggest unchecking "show news/tutorials at startup" (news or tutorials depends on your version of GM)
I suggest making sure Backup on Save is enabled, and setting it to something like 5 backups. Quite nifty if you want to revert.
I *strongly suggest* disabling "Hide the designer and wait while game is running" as this option is a bit broken. If your game
crashes, the designer won't come back, and you can't save your changes.
Now, a few tips on Objects:
Add a "Room End" event, which calls the code instance_destroy(). Destructor's don't typically call on exiting a room, this ensures
that they do, making this behaviour a bit more predictable.
Step events are basically "on update" events. The game speed is set in "steps per second".
Drawing code in scripts, such as drawing a rectangle, will only function if it takes place during any object's Draw event. (The script
helper object exists to enable such behaviours without needing a logical object to attach it to).
I suggest, when possible, using Call Script instead of Execute Code - oddly, with a Script Editor open, you can still interact with the
main window, while the Code Editor blocks input to the main window. Also lets you update code without having to fish through objects.
Lastly, in an object's Step End event (or just step, technically), you can use the following snippet:
depth=0-y;
That will give the object "map depth", allowing things to walk behind or in front of other (dynamic) things dynamically.
Now, some neat tips on instances:
First, you can CTRL+RightClick on an object (in the room window) to get a context menu. This context menu has the option Creation
Code, one of the most powerful features of GM (and few people seem to realize it exists o.O).
Creation code runs *before* the object calls its "on Create" event, allowing you to set up local variables that are specific to that exact
instance. For example, objItem could set itemId=5 in its Creation Code -
the actual Create event for objItem would simply switch(itemId){...}.
Map editor tips:
Personally, I always leave Snap to Grid enabled- in the lower left of the window you'll see a list of hotkeys. Learn to use these as
they will greatly expedite the mapping process.
There's a checkbox that says "Delete underlying". This is important - sometimes appropriate, sometimes absolutely not. Let me
point out now, that Delete underlying will delete *any* underlying object, even of a different type. For example, say I want to place
an item atop a table. The table might have collision mask objects present, which I don't want deleted. So I would make sure the
box is unchecked. On the other hand, say I'm painting a collision mask - I want to leave that checked so I don't risk stacking multiple
collision tiles on top of each other.
Speaking of tiles - you *could* create map tiles as objects, and assign them various properties. Personally, I find it much faster to
use collision objects, which have "Visible" unchecked in object properties (but are visible in the editor). This way, I set the map layers
to whatever Depths I want them at, and then make a quick and easy second pass to set the collision. No extra effort required
There will be some notes on tiles below.
Background/Tiles tips:
When you create a new background, and load an image, you have a checkbox that says "Use as tileset". This is an important option,
as tile-based mapping is probably what you're into at this point. Ideally, the tilesize of your grid in the map editor should match this
size. Now, an important note: If you use a background as a tileset, in the map editor, it will no longer be listed under Backgrounds.
Instead, it will be listed under Tiles, and used just like any other sane tile mapping editor.
Script Helper Object:
I often use a "startup" room, consisting of only one object: an object I call the Script Helper Object.
Script Helper is set to Persistent - meaning every room you switch to after startup, it remains unless it destroys itself.
I basically set all the events I am interested in to call my eventHandler scripts. For example, eventHandlerDraw().
The purpose of the Script Helper Object is organization - mine often exists at a negative depth, so that anything I draw with it is drawn
over the level. It lets me call script functions on events, without having to depend on the existence of a visible object.
While not "neccessary", it seems to keep things much cleaner for me.
Game Settings Tips:
You can "disable" the loading image by using a 1x1 image and setting its opacity to 0 (be sure to disable the loading bar too if you do this).
I use Game Information for notes, and therein I disable "Press F1 to view Game Information", as I don't want that visible to the end user.
Rooms Tips:
There is Room Creation code, under the settings tab. This can be used for setting Room variables. For example, say you have your script
helper object draw a gray rect (set to additive blending) over the entire screen. Here in room creation, you could set its color and opacity
for a cheap Screen Tone implementation.
The game *always* starts in the first room in the list. I personally leave this room empty, containing only my script helper object, and use its Game Start callback to switch to any room I like.
The Room Caption is what will show in your window title bar. Don't be afraid to hijack this with GML instead, using the script helper.
GML:
Don't be afraid of GML. There is a GML (script) command for every single one of the drag and drop features, and several more.
Personally, I recommend orienting your project around GML, and using the objects/events/etc to organize your scripts. By doing so,
it's relatively painless to create any kind of 2D engine you can imagine.
Here's a tip: script names are important - because each seperate script acts like a "function" from a traditional programming language. For
example, if I have a script called scrUpdateClock, in any other script I can add the line scrUpdateClock(); to call it.
Scripts have arguments. While you don't declare them, you can pass up to 15 (for example: scrUpdateClock(time, speed, somethingElse)
You can access script arguments using an array called arguments[0-15].
Data types are automatic in GML, you can declare something with the "var" keyword, but its entirely unneccessary.
And obviously, Google is your friend. Seriously, even for the silly stuff. I've written two entire engines in GML, and my search history
is crammed full of stuff like "how to draw a gradient gml" and "gml dynamic depth" and "gml pathfinding tips" and of course "gml
for n00bs". Read, learn, create.
Here's a starter kit covering most of what I've explained so far. See my comments below for the actual features/changelog.
The Download (requires GameMaker 8.1 or later):
http://www.mediafire.com/download/ahcck6e0iycsk4f/starter.gm81
For those of you who don't have GM 8.1+, but would like to take a look, here's the EXE.
http://www.mediafire.com/download/3qdjy ... n/demo.exe
You're free to use it in any way you like, no credit neccessary.
Please replace the title screen and windowskin art - they were grabbed from a public resources site, but as its not an actual project I forgot to check who to credit. I'll do something original for these later.
If anyone has comments, questions, or just wants to say hi, don't be shy.
In closing, I really wish we had a GameMaker subforum.
However, it does have a bit of a learning curve to really get cozy with it.
So I decided to compile and share some of the not-so-obvious things I've learned. I'm sure most of you that actually read this topic will know much of it already, but I wouldn't be surprised if even advanced users didn't know one or two of these.
First, this entire document assumes Advanced Mode is enabled.
File->Advanced Mode (make sure it is checked).
Second, a few preferences that make life a bit nicer:
File->Preferences
I suggest unchecking "show website button in main window"
I suggest unchecking "show news/tutorials at startup" (news or tutorials depends on your version of GM)
I suggest making sure Backup on Save is enabled, and setting it to something like 5 backups. Quite nifty if you want to revert.
I *strongly suggest* disabling "Hide the designer and wait while game is running" as this option is a bit broken. If your game
crashes, the designer won't come back, and you can't save your changes.
Now, a few tips on Objects:
Add a "Room End" event, which calls the code instance_destroy(). Destructor's don't typically call on exiting a room, this ensures
that they do, making this behaviour a bit more predictable.
Step events are basically "on update" events. The game speed is set in "steps per second".
Drawing code in scripts, such as drawing a rectangle, will only function if it takes place during any object's Draw event. (The script
helper object exists to enable such behaviours without needing a logical object to attach it to).
I suggest, when possible, using Call Script instead of Execute Code - oddly, with a Script Editor open, you can still interact with the
main window, while the Code Editor blocks input to the main window. Also lets you update code without having to fish through objects.
Lastly, in an object's Step End event (or just step, technically), you can use the following snippet:
depth=0-y;
That will give the object "map depth", allowing things to walk behind or in front of other (dynamic) things dynamically.
Now, some neat tips on instances:
First, you can CTRL+RightClick on an object (in the room window) to get a context menu. This context menu has the option Creation
Code, one of the most powerful features of GM (and few people seem to realize it exists o.O).
Creation code runs *before* the object calls its "on Create" event, allowing you to set up local variables that are specific to that exact
instance. For example, objItem could set itemId=5 in its Creation Code -
the actual Create event for objItem would simply switch(itemId){...}.
Map editor tips:
Personally, I always leave Snap to Grid enabled- in the lower left of the window you'll see a list of hotkeys. Learn to use these as
they will greatly expedite the mapping process.
There's a checkbox that says "Delete underlying". This is important - sometimes appropriate, sometimes absolutely not. Let me
point out now, that Delete underlying will delete *any* underlying object, even of a different type. For example, say I want to place
an item atop a table. The table might have collision mask objects present, which I don't want deleted. So I would make sure the
box is unchecked. On the other hand, say I'm painting a collision mask - I want to leave that checked so I don't risk stacking multiple
collision tiles on top of each other.
Speaking of tiles - you *could* create map tiles as objects, and assign them various properties. Personally, I find it much faster to
use collision objects, which have "Visible" unchecked in object properties (but are visible in the editor). This way, I set the map layers
to whatever Depths I want them at, and then make a quick and easy second pass to set the collision. No extra effort required
There will be some notes on tiles below.
Background/Tiles tips:
When you create a new background, and load an image, you have a checkbox that says "Use as tileset". This is an important option,
as tile-based mapping is probably what you're into at this point. Ideally, the tilesize of your grid in the map editor should match this
size. Now, an important note: If you use a background as a tileset, in the map editor, it will no longer be listed under Backgrounds.
Instead, it will be listed under Tiles, and used just like any other sane tile mapping editor.
Script Helper Object:
I often use a "startup" room, consisting of only one object: an object I call the Script Helper Object.
Script Helper is set to Persistent - meaning every room you switch to after startup, it remains unless it destroys itself.
I basically set all the events I am interested in to call my eventHandler scripts. For example, eventHandlerDraw().
The purpose of the Script Helper Object is organization - mine often exists at a negative depth, so that anything I draw with it is drawn
over the level. It lets me call script functions on events, without having to depend on the existence of a visible object.
While not "neccessary", it seems to keep things much cleaner for me.
Game Settings Tips:
You can "disable" the loading image by using a 1x1 image and setting its opacity to 0 (be sure to disable the loading bar too if you do this).
I use Game Information for notes, and therein I disable "Press F1 to view Game Information", as I don't want that visible to the end user.
Rooms Tips:
There is Room Creation code, under the settings tab. This can be used for setting Room variables. For example, say you have your script
helper object draw a gray rect (set to additive blending) over the entire screen. Here in room creation, you could set its color and opacity
for a cheap Screen Tone implementation.
The game *always* starts in the first room in the list. I personally leave this room empty, containing only my script helper object, and use its Game Start callback to switch to any room I like.
The Room Caption is what will show in your window title bar. Don't be afraid to hijack this with GML instead, using the script helper.
GML:
Don't be afraid of GML. There is a GML (script) command for every single one of the drag and drop features, and several more.
Personally, I recommend orienting your project around GML, and using the objects/events/etc to organize your scripts. By doing so,
it's relatively painless to create any kind of 2D engine you can imagine.
Here's a tip: script names are important - because each seperate script acts like a "function" from a traditional programming language. For
example, if I have a script called scrUpdateClock, in any other script I can add the line scrUpdateClock(); to call it.
Scripts have arguments. While you don't declare them, you can pass up to 15 (for example: scrUpdateClock(time, speed, somethingElse)
You can access script arguments using an array called arguments[0-15].
Data types are automatic in GML, you can declare something with the "var" keyword, but its entirely unneccessary.
And obviously, Google is your friend. Seriously, even for the silly stuff. I've written two entire engines in GML, and my search history
is crammed full of stuff like "how to draw a gradient gml" and "gml dynamic depth" and "gml pathfinding tips" and of course "gml
for n00bs". Read, learn, create.
Here's a starter kit covering most of what I've explained so far. See my comments below for the actual features/changelog.
The Download (requires GameMaker 8.1 or later):
http://www.mediafire.com/download/ahcck6e0iycsk4f/starter.gm81
For those of you who don't have GM 8.1+, but would like to take a look, here's the EXE.
http://www.mediafire.com/download/3qdjy ... n/demo.exe
You're free to use it in any way you like, no credit neccessary.
Please replace the title screen and windowskin art - they were grabbed from a public resources site, but as its not an actual project I forgot to check who to credit. I'll do something original for these later.
If anyone has comments, questions, or just wants to say hi, don't be shy.
In closing, I really wish we had a GameMaker subforum.