If you haven’t yet, go back and read Part 1
Design choices
Since we’re starting from (basically) nothing, we have a lot of decisions to make. Therefore, thinking about the design of your configuration system first before you start building things probably is a good idea.
Requirements
First, let’s think of the features that we need. When I brainstorm features, I tend to go crazy. I think about everything I might possibly need. I think about all the things that would be OMG SO AWESOME to have. I find it helpful to do this, but I have learned that while having all these ideas is great and exciting, in the end you have to build everything, so every idea you come up with represents a lot of work and a lot of testing.
I’m only one person, working on these projects in my spare time — not a design house, or even a full-time lone developer, so if I want to ever have a hope of finishing my work, I have to scale back to the essentials. So why think about everything I can imagine?
- I like my imagination. It’s awesome, and using it is fun.
- The more I think about things, the better my ideas get.
- When I think complex, even if I don’t ever build the whole thing, I can at least create a design that will better accommodate further development later if I want to extend the basic implementation. I might do the extending, or someone else might do it later; it doesn’t matter. Building code as a foundation for future code is a good thing if you can manage to do it. Doing so correctly means avoiding having to repeat yourself in future projects.
- Even if I don’t have all the resources or talent that I might need in order to implement a design, having a good design documents makes it that much more likely to inspire others to contribute something to the project.
A very simple Options system might consist only of a single screen. But as we’ll soon see, there may be need to break things up into multiple screens, especially if we have many different options or categories of options.
If we have multiple screens, we’re going to need a means of navigating between them. This can be as simple as a group of rooms with room_goto commands linking them up, or it can be something else.
To design our Configuration Options system, we need to address a few things:
- Features: What options do we want the user to be able to configure? What choices do we want each configuration option to have?
- Interface/Controls: How do we want to present these options to the user? How will the user interact with the interface to set it?
- Implementation/Integration: How do these configuration choices get applied, technically? How will these configuration options interface with the game itself?
Features
Some of these will be fairly standard, common to many games, while some will be highly specific to the specifics of this game. I’ll address the standard ones, but don’t worry — once you see how we implement the standard features, it will be easy to set up config options for the features that are unique to your game.
You don’t need to support all of these options, but the following list is a good start for what you might want to consider:
Graphics
PC hardware very commonly has different graphical capabilities, due to differences in hardware, particularly the video card and monitor. While just about any video card is going to be capable of playing most Game Maker games at full quality, there is still the monitor to contend with.
Display settings
It might be easiest to force a specific display mode, but that’s not a flexible approach and may not work for all players. By far, it’s better to assume that the display mode the game starts up in is the player’s preferred (or only) graphics mode, and leave it as is.
If you want to enable everyone to play your game, it’s a good idea to give them some control over how the graphics of your game will be displayed on their screen.
The easier approach is to allow the player to set the display settings through the computer’s control panel, and just run in whatever mode the display is set to when the game runs.
More professional looking games usually offer the play an in-game configuration menu that allows them to change the same settings without having to leave the game program. It’s a convenience, to be sure, but it does keep the user in your game.
Keep in mind, too, that in GameMaker, there’s a distinction drawn between the Display (the physical hardware), the Window, the Room, and the View. Most of what you might think could be accomplished by forcing a specific display configuration can be better accomplished through Widow, Room, and View settings.
- Fullscreen or Windowed mode?
- Display resolution
- Aspect ratio
- Refresh rate
- Color depth
Fullscreen or windowed mode?
Most games play best in fullscreen mode, but sometimes players like the option of playing inside a window, as it allows them to switch between other applications more easily. The downside of this is that it becomes all too easy to mouse outside of the game window, and lose focus. You can set the game to pause if the window loses focus, but this is still annoying disruption and can mess the player up even with pausing the game.
When to run in a window? As a general rule, I like to develop and debug my game in windowed mode, since it’s easier for me to get at other windows that I’m working in. But for finished games, I usually like the game to run fullscreen. I want the game experience to be distraction-free.
That’s not always the case, though. Casual style games, pausable games, puzzle games, and turn-based games that wait on you to act are good candidates to have a Windowed mode as an option.
Resolution
These days, it’s probably not necessary to change the display resolution. Just about everyone uses LCD displays with fixed resolution. While these screens are capable of emulating other resolutions, they do not look as good when they do. Games for mobile devices of course will play on a device with a specific resolution that cannot be changed.
In any case, the game should never force a specific resolution on the player; you may want to offer the player controls to allow them to change the resolution for themselves within your game interface, though.
If a player wants to set a specific resolution, they can always just use the display settings control panel on their computer. If you want to provide an interface for this to them in your game, you can, but it’s a convenience or luxury feature, not a necessity. Supporting multiple resolutions means a lot of extra work and testing for a developer, so unless you’re a professional studio with the resources for this, it’s probably better to focus on supporting one resolution well.
Don’t worry about supporting every possible display size right away, the amount of work it takes to do it well will kill your project. Instead, focus on making the game as good as it can possibly be in one default resolution, and if your game ends up being popular enough to warrant it, you can build resources (primarily different sized rooms) to support other display resolutions better.
If you do change display resolution in the game, keep in mind a few things:
- Always change it back when you’re done. Use
display_reset()
for this. Keep in mind if the game crashes, this doesn’t get called, though, and may leave the computer in a resolution the player doesn’t want. This can panic a non-technical user. - Don’t change display settings without first testing them. Use
display_test_all()
with the settings you’re about to set, before you actually set them. Be sure to have some fallback code that gracefully handles what takes place if the new settings don’t test OK.
You probably do want to know what resolution display the game is playing on, though. There are a lot of reasons to need to know this. Use display_get_width()
and display_get_height()
to detect the display resolution. Note this will return the current settings for the display, not what the display’s maximum or native resolution is.
You should decide the minimum display resolution you’ll support. GameMaker’s default room resolution is 640×480, which is the old VGA standard resolution. This is a very safe resolution to use, because just about any display will support it, but is also quite tiny these days. It’s still not a bad resolution to start out with, though. The smaller the minimum resolution you support, the more devices your game will run on.
It’s good to support larger resolutions, too, of course. Most people do have larger displays these days, and it’s desirable to utilize all that space effectively. Very large display resolutions can introduce performance issues, though, so test your framerates when running at maximum resolution, and make sure they’re acceptable.
If you’re targeting a specific mobile device, learn what its native resolution is, and use that. Read up on guidelines for Android and iOS development to learn the recommendations other developers follow.
To accomodate other resolutions, there are a variety of approaches. You can create a series of rooms and HUD graphics to provide a tailor-fit screen for every resolution you support. This is a lot of extra work, though. Scaling the game to fill the display can be an OK approach to take, and requires a lot less effort, but will result in a less attractive game with blurry edges due to the way the Game Maker runner handles scaling graphics. Another approach is to letterbox — draw the game in its standard resolution at a fixed 1:1 scale, and leave a black border around the edge of the screen, framing the game window. This can be good, too, but if you have too much black border it can be annoying.
Aspect Ratio
These days, you also have to consider aspect ratios, the ratio of the width and height of the screen. In the old days, computer monitors and TV sets in the United States all used 4:3.
Today, it’s a different story. On the desktop alone, people may have 4:3, 16:9, or 8:5 (16:10) displays. 16:9 is pretty quickly becoming the most common, particularly in 1920×1080 (1080p), and is also the ratio of HDTV, so if you have any desire to port your game to a game console, you may want to start out at 16:9.
And there are still others, albeit less common ones. If you’re planning on targeting a mobile platform, you’ve got even more possibilities.
If you’re building an HTML5 game, keep in mind that the browser window “chrome” (menus, toolbars, etc.) all take up space as well, which should be subtracted from the available display you have to run your game in, and this can change the effective “aspect ratio” of the web page unpredictably.
Enable/disable special effects which may affect performance (such as particles).
There are two main reasons for making these configurable: performance on slower machines, and user preference. Some players don’t like effects-heavy games, and prefer a sparse, cleaner visual experience without all the bells and whistles. Sometimes the screen can become so cluttered with particles that you can’t see the action, and it hurts your game rather than enhances it. So it’s nice to allow the player the option to not have these things in their game.
Refresh Rate and Color Depth
These settings are controllable in GameMaker, but there’s almost no reason for it. Most games shouldn’t have any need to mess with the color depth of the display.
In the 1990’s, it was more common to see variety here, but these days it’s pretty safe to assume that the computer will be running in 32-bit color mode. Oddball machines might be running in 16-bit or 24-bit color, and even more rarely you may encounter a display configured to run in 16-color or 256-color mode, but these are rare, and probably won’t have the necessary hardware to run a GameMaker game adequately anyway.
Refresh rate is probably also safe to leave alone. This setting is more pertinent to CRT displays, which are rapidly disappearing from the desktop computer landscape. Most LCD monitors use a 60Hz refresh rate, although there are LCD HDTVs that use 120Hz or 240Hz refresh rates. Older TVs used 30Hz.
Some people can notice a difference between refresh rates, and can tell you readily just by looking what refresh rate a monitor is using, especially if they are familiar with the display in question, but most people can’t, and don’t even think about such things if they’re even aware of them.
Some game developers will say that it’s a good idea to sync the room_speed
of your game to the refresh rate. Keeping FPS and refresh in sync, or at least in a whole-number ratio, is not a bad idea. But the better way to do this is to set your room_speed
to the display_get_frequency()
or just assume a refresh rate of 60 and use a room_speed
of 30 or 60. Keep in mind that regardless of what the room speed is set to, it’s fps
that is the actual frame rate, and this usually fluctuates a bit.
Sound
-
Master volume
-
Music volume
-
Effects volume
-
Mute
Again, for the most part, these configuration options could be set by the user outside of the program, by using the volume knob on the speaker, or through the Sound and Volume control panel. But it’s a nice convenience to provide an interface to the user so they don’t have to leave your game to make adjustments. The nicest one is the separated music and effects volume. This will allow the player to adjust the mix to their taste.
One important thing to do is to remember the user’s preferred volume settings and automatically set them when the game runs, and set them back when the game exits.
The harder task will be to separate the volumes for the Master, Music, and Effects volume controls. Mute is actually very simple, and there are a few techniques that can be used. One way is to have a global variable called “mute”, and to set up a conditional before each and every sound function call. This is an inferior approach because it means you have to make sure you catch every single sound function call in all your code, whichis a pain to program. The other problem with it is that all those extra if (mute){}
checks take processing power at runtime, albeit a tiny amount, it still adds up and could conceivably hurt performance.
The better way to handle mute is to simply setting the volume to 0. This is done with the sound_global_volume()
function, which we also use for setting the master volume. The sounds still play, but at 0 volume, you don’t hear them. You don’t have to add code for every sound_play
and sound_loop
function in your code. And since the computer doesn’t have to ask every single time whether the game is muted or not, it’s a lot less processing. sound_global_volume(0)
mutes your game, and sound_global_volume(1)
restores the master volume to full. Use a global variable to store the setting for the master volume as well, so instead of restoring the volume to full blast on unmute, you set it back to the master volume value.
globalvar master_volume;
//master_volume is set in the config screen.
mute() {sound_global_volume = 0;}
unmute() {sound_global_volume = master_volume;}
You can put the Mute function into your game configuration menu, or you can make it more readily accessible to the player by creating a control for it that they can access while the game is playing.
Separate volume controls for bgm and sound effects will take a little more work, using the sound_volume()
function to control the volume for each individual sound in your game, so we’ll cover that in detail later.
Note: GameMaker Studio 1.1 introduces an entirely new audio system. The above code samples work with the old system.
Controls
-
Provide the player with a screen showing the current settings, and allow them to set up their own custom settings.
-
Allow the player to save their custom settings as a profile, load from a profile, delete profiles.
-
Allow the player to reset the controls back to their default settings, or to select a custom profile (such as for different keyboard layouts, etc.).
-
Provide the player with options to use various input devices (keyboard? mouse? joystick/gamepad?)
Difficulty/Game Options
-
Difficulty (Easy/Normal/Hard)
-
Starting level
-
Enable/disable (or throttle) specific features
-
Number of lives
-
Text size/speed (if you’re displaying lots of dialogs)
-
etc.
This part is highly dependent upon your game. You can set up an interface to allow the user to set these things, but integrating them into your game will be highly dependent upon your game. Some things (number of lives, starting level) will be trivial to implement and integrate; others will take a great deal of design sense and playtesting.
High Scores/Achievements
An Achievements system, again, will be highly dependent on your game. But we can probably provide some abstractions that make it easier to implement your achievement system in a consistent way, such that the specifics may be different from game to game, but they way they are handled will be the same.
Some features we might like to see:
-
Record more than 10 high scores
-
Record other types of achievements
-
Record achievements per player account
-
Clear achievements
-
Upload scores/achievements to an online “Hall of Fame” server
Localization options
-
Language
-
Keyboard layout – keyboard layout could tie in well with the Controls. A user with a non-QWERTY keyboard could set that here, or have it be auto-detected from a system variable, and automatically update the keyboard controls with default keys appropriate to the layout map of the local keyboard. But then, the user should still be able to override these with their own preferences.
Save States/User Profiles
If your game stores user profiles or save state data, provide an interface to the user to do things with them. Common activities include:
-
Create new
-
Delete
-
Copy
-
Rename
-
Edit info (for user profile data, such as user name, password, and other profile data).
What’s in the save state file will be a bit beyond the scope of this series, and in any case should be highly dependent on your game. While I won’t tell you what to put in your savefile, I can tell you how to set up some file i/o functions that will enable you to read and write your savefile, and maybe some suggestions for how to protect this information, validate it, and format it.
It’s also a good idea to save the configuration settings themselves. Configuration settings (graphics, sounds, etc.) should be separate from game savestate data (My character’s name is XYZ, He is level N, his inventory consists of…, he has visited the following locations… he has achieved the following goals… etc.)
We have a few design choices for how we want to do the config save. The simplest would be to simply revert to defaults every time the game is launched (ie, not save anything, but remember a basic set of options that will definitely work on any system the game is run on.) From a user’s perspective, however, this would become annoying, as they will need to re-configure settings to their taste every time they quit the game. The next simplest approach would be to remember what the settings were the last time the user set them, and to remember the defaults in case the Last config profile gets corrupted.
This is probably as far as you really need to go; but once you are saving profiles, you’re not too far from allowing the player to save multiple configuration profiles, or per-user profiles. We’ll probably implement this later on as an advanced feature.
-
Other stuff
- Network: These days, you may also want to have configurations options for network (TCP/IP settings, firewall/proxy server settings, etc.)
- Social: Or you might want to have some kind of social networking features, such as sharing your game progress with your Facebook and Twitter friends, inviting friends to try out your game, or even send friends in-game items to help them, and so on.
- Hall of Fame/Achievements: Or a “submit high score to server” feature. Or you might have a registration and payment screen.
- Update Checker: Or a “check for updates/download/install” feature.
These things are much more complex to design and implement properly, and as such will be outside the scope of this tutorial for now, but it’s good to think about them!
Personally, I would like to see these type of features built in to Game Maker, and I hope that YoYoGames will incorporate features like this in time. When I say “built into Game Maker, I don’t just mean having a library of available GML functions that one can use to build a configuration system out of. That is, after all, what we are going to do with this project. What I mean is, it would be nice if such a system existed as a ready-made component that you could just drop in to any project, and set up with just a few clicks or lines of code.
These features, and the interface the user will interact with to manage them, will be challenging and time-consuming to implement, and are not really “the game”. A good configuration system and interface is excellent polish for a professional-quality project. Game Maker’s purpose is to make game development easy by doing the hard technical stuff for you. So far, they’ve done that by focusing on the in-game building blocks that a designer would use to produce a play experience. Now that they’re turning Game Maker into a more professional tool, I hope that they’ll start thinking about including these kind of features, too.
Until then, we have to fend for ourselves. The above list of features represents a significant amount of work that we need to do. Setting up a system that is flexible enough to allow us to do this easily is no small task. If I’m lucky, by procrastinating long enough, I may find that they end up doing the work for me:) If I am going to do all this work, then I want to get the most return for that work that I possibly can by making a re-usable system that I can apply easily in any game. This means a de-coupled, generic system that can be adapted easily to a wide variety of projects. This is a good situation to create a Game Maker Extension (.gex). However, an extension will not give us a complete system — an Extension allows us to package a library of useful new GML functions that we write, but our built system will also need room, object, sprite, and sound resources, and a .gex cannot include those resources. Ultimately, this means that we may not be able to realize a dream of a drop-in system. But even providing better building blocks to create such a system would be better than nothing.
To begin, we’ll start small, and implement some basic things, and then iterate and refine our solution until we have something that hopefully works really well for a wide variety of games.
In our next article, we’ll discuss the code needed to make these configuration settings, as well as how to store and retrieve them.
“In our next article, we’ll discuss the code needed to make these configuration settings, as well as how to store and retrieve them.”
I would love to be able to read this next article. Has this been written? I can’t seem to find it. Great information, but now really wanting more!! Hope you are working on it. Thanks for writing these tutorials!
urban
urban, I have a draft that I started some time ago and have been neglecting for longer than I intended, as I kept getting into other interesting stuff. I’ve been pretty busy since I started writing this series and have not put in the time that I need to get the project to where I feel it needs to be. Partly, too, I’ve been watching the ongoing development of Game Maker Studio, half-wondering whether they might be about to make this effort obsolete. I do plan on going farther with this series, though, maybe in the next two weeks I should be able to find the time to finish up the next installment.
I’m glad you’re finding the articles helpful, I love to hear from people who found value in what I do.
Chris Sanyk
Thanks for the reply. I hope you can find the time. Even if things change in gamemaker, I’m sure it would be a great learning tool. This is one daunting section of GML and game design that really hope to understand and get right.
By obsolete, do you think that means they’re getting rid of old functions that would help make this, or they’re developing a better system to make these configurations?
urban
I agree, it’s one of the more difficult things to implement in my GM projects, and I got to where I get annoyed having to re-implement it with each project.
My idea was to come up with some kind of system that worked well generically, that I could export and turn into an Extension which I could then import into projects, call a function or two to set up my configuration system, and have GML in the extension handle creating the whole system, including rooms to house the configuration screen interface, the interface widgets, an external file to store the configuration, a function to read that file and set up the game, and something that would check the configuration to verify that it works, and if it does not, throw it out and reset to safe/reasonable defaults.
All of that is do-able, but requires quite a bit of development effort to perfect. I do want to do it, because I want to get it out of the way and focus on the actual game aspects of GM development, not this “boilerplate” stuff.
The rapid pace at which YoYoGames have been releasing updates has caused me to pause a bit when considering the design and implementation of my configuration manager system, though. It’s a little of both — first, YYG has deprecated a number of functions in GML because they were too specific to Windows, and do not make sense in a cross-platform developer environment. Second, I haven’t seen anything hinting at them doing this, but I am hoping that in time they will create a better system. I’ve suggested it to them, and I would not be surprised if it were somewhere on their roadmap, but as yet I have not seen anything from them announcing anything.
Of course, part of my problem is that inventing a system that works for multiple platforms is even more difficult. I don’t even have the full studio with all bells & whistles, so I’m going to continue development concentrating on a config system that is intended for Windows builds, rather than platform-agnostic. Once I begin development, I will be making the source code available so that developers who want to extend this system can contribute to the project.
I do think that having it built-in to the framework would make it even easier for developers to make games with more sophisticated configuration options, and save many hours for having to design and implement it from scratch.
I agree with you, it’s a challenging exercise to devise a one-size fits all solution, and a worthwhile project for a new developer to gain experience with. The fact that GM leaves some important features like this out, but within the reach of an ambitious developer, is another reason why it’s attractive to beginner programmers as a tool to learn with.
Chris Sanyk
I just played Hot Line Miami, which was a fantastic game built with GM, but noticed it had practically no configuration settings, no volume control, and no keyboard configuration. There was no option for starting where you left off, except for scrolling through the chapters and finding the latest one. While I appreciated the simplicity of the game menus to a degree, I felt this part still fell into the GM cliches.
It would be fantastic if the menu, configs, and saves were more streamlined. I hope you figure out a good system!
On the topic of obsolete functions, I found that with GM studio there are no functions for displaying video. I hope to implement some HD quality cutscenes into my game, but I’m not quite sure where to begin. It’s been difficult finding any information about this. May I ask if you have any insights into playing HD video? Thanks for all of your work!
Eric Urban
I think part of the picture is that there’s a shift in UX philosophy that has been going on in recent years, where configuration options are considered uncool or old fashioned. Newer UX philosophy says the app should know what the settings should be, at least for configuring hardware for optimal experience (weighing eyecandy vs. performance). I still say some config is necessary, for stuff that is more clearly user preference, such as difficulty level, or loading a save state.
And even if the app could perfectly configure itself for optimal UX, it’s still desirable to have usable user control widgets that can be put into the user interface. Things like buttons and pulldowns are potentially handy things to have in certain styles of games (such as RTS or turn based strategy games). Game Maker unfortunately has next to nothing like this out of the box. I’ve seen people re-invent the common user controls (textboxes, buttons, listboxes) but it seems silly to not include some way to include native widgets and make them available to the UI designer.
As to your question on displaying video, I have not done that in any of my game projects. Generally, I don’t like cutscenes as a game design element; I prefer to do non-interactive segments in-engine or not at all. Try the GMC forums, though, I’m sure people have answered that question there. At the least, you may be able to use the GML function which shows a web page, and then embed a video inside the webpage somehow.
Chris Sanyk
Thanks, I’ll keep digging. I do agree that cutscenes can bring you out of the experience in most cases. But from a storytelling perspective you may need more sophisticated animation, which may be better suited as a pre-rendered, compressed video. I’m trying to figure out the hardware limits of calling sprite animations. Say I want to create a closeup where the character’s face fills the screen. It doesn’t seem feasible to draw 30 seconds worth of 1920×1080 sprites. Anyway, getting off topic here.
Thanks so much for your help!
Eric Urban