Category: games

LD48 #24 picks

There were 1406 games submitted for Ludum Dare 24. I probably won’t get to play more than a tiny fraction of that number before the judging is over.

As a judge, I believe my goal should be to play every game, but given the time window and the number of entries, that’s not very likely to happen. So sadly, I end up picking games somewhat arbitrarliy from among the entrants, usually based on the thumbnail screen shot and/or title being interesting.

One strange thing I’ve noticed about LD’s website is that when browsing through all 1406 entries, I will notice that the ordering seems to be random. I expect this is to shuffle the games up so people will have a better chance of playing games that otherwise would be buried at the bottom of the list. But a side effect of this is that no matter how many times I page through all roughly 50 pages of games, I invariably miss many — it seems the shuffle re-randomizes while I’m paging through, and I end up seeing some games twice and therefore obviously must be seeing some games zero times. This is kindof annoying and I wish I could get all 1406 games on one page somehow.

I’ve just taken a walk through the submissions and grabbed the title and URL of the pages of the entries that looked like they might be interesting. This is a completely arbitrary process and I spend maybe 2 seconds looking at each game before deciding whether to pick it up and play with it, or skip it and move on. So don’t feel slighted if I missed yours — if it was any good, most likely I’ll discover it anyway after the judging is over.

I don’t want to skew the judging by recommending games, but for non-LD participants who can’t judge, there’s no harm in sharing a list of links to games I think look like they might be cool. In all likelihood, probably a lot of these are terrible. I haven’t played them yet and this should not be considered a recommendation or endorsement; it is merely a list. (more…)

D’oh! Game Maker Studio requires a Mac to build an OS X game

So, last night, for the first time I tried building a Game Maker Studio project to OS X. I was a little surprised to discover that apparently GM:Studio needs to connect to a Mac OS X system in order to complete its build process. This makes it a little bit of a problem to build OS X projects.

I guess the upshot of that is that it means that it is impossible to create OS X builds in a dev environment where there is no means to test them. On the other hand, I guess the true cost of Studio is around $2500 since I have to buy a Mac. But hey, I suppose that could be a tax deductible expense if I’m buying it for business purposes. I know they make them cheaper, but I probably wouldn’t buy a mini. Eh, maybe. I’ll have to kick it around and decide, but I’m more into the idea of getting a MacBook Pro.

Random number generation in game programming

Random number generators are extremely useful in game programming. I have found a lot of uses for randomness in my projects.

What can you do with randomness?

Man, all kinds of stuff. Nearly any value that you want to initialize in a game object is a candidate for possible randomization. Randomness fuzzes up your game, making less deterministic and therefore harder to defeat with simple patterns and more replayable.

Pretty much any time I would normally use a literal or a constant number in my code, anymore I step back and ask myself what range of values might work in that place, and then create a random function that will provide me with a number in that range. The only time I don’t do this is when I really do need a precise value, or when performance is too important to sacrifice the computation time needed for the random function to return its result.

Here are just a few ideas for how you can use random numbers to improve your games:

Unit stats

Nothing makes a video game feel more like a video game than when every enemy you encounter is an exact clone of all the other enemies that look like it. You can use randomness to give your enemies some personality by giving them randomized stats. Instead of fixed values for Attack, Defense, Speed, Damage, etc., use a random range of values to generate stronger and weaker versions of your enemies. It takes a little more time to compute these values on the fly, but modern processors can handle this load easily, unless you’re generating a huge number of units.

Sprite generation

Why spend a lot of time hand-drawing every sprite in your game? Create a generator system that randomly puts pieces together, and create random sprites on the fly. If you’ve played around with an avatar generator such as eightbit.me or the Mii generator on Wii or the XBox Live Arcade avatar generator, imagine that kind of model system, but with a random selector in charge of picking the hair, eyes, etc. You can do this to randomly generate other things, such as buildings, procedurally, as well.

Colors

If you’re calling drawing functions, randomizing colors can give your game a lot better visual appeal. If you’re clever in how you pick your random colors, you can come up with color schemes that work nicely, yet are always slightly different each time you play. You can either pre-define a palette of colors and randomly select one, or you can randomly select R, G, B or H, S, V numbers and create a color at runtime. You can experiment with different mathematical tweaks to shape and constrain the randomness.

Map generation

If you can write a good random map generator, you can save yourself from having to hand-design all your maps. GOOD random generation may be very difficult to accomplish, however — especially for more complex games. But even if you can’t guarantee a good random map at runtime, an almost-good random map generator can save you tons of time or spur your creativity by doing most of the work for you, leaving you with something almost good enough, that just needs a little hand-polishing to make shine.

Procedurally generated content in general is a good use for random functions. You can use a random number function to create a deterministic sequence of generated values that is always the same. This is because computer hardware actually does not have a means of creating a truly random number — it fakes it, approximating randomness with a pseudo-random algorithm.

This is used to good effect in one of my favorite Atari 2600 games, Pitfall. A pseudo-random function, using a fixed seed, is used to generate each screen in the game. This achieves a very high information density, since the data that was needed to represent each screen could not be stored on a 4kb ROM, but a generator function that creates that data easily could. This technique is not used very much in modern game development since storage isn’t much of an issue any more, but it is still a very interesting technique and one which merits study.

AI

There are many potential applications of randomness to AI. Whenever your AI needs to make a decision, you potentially can use randomness to make that decision less predictable. Weighted probability is important here, as completely random AI behavior is erratic and seems crazy, while an AI that occasionally does something unexpected will seem tricky or deceptive or clever. Dynamically weighting the probability according to context at runtime will make your AI seem smarter.

GameMaker/GML random functions

These are built in to the Game Maker Language (GML):

  1. random(N): returns a random floating point value between 0 and N, not including N.
  2. random_range(A, B): returns a random a floating point value between A and B, not including B.
  3. irandom(N): returns a random integer value between 0 and N.
  4. irandom_range(A, B): returns a random integer value between A and B.
  5. choose(a,b,c,d,e,f,g,h,i,j,k…): Randomly returns one of the arguments, up to 16 arguments may be passed into a GML function. You can weight the likelihood of one result by repeating it in the arguments list. (e.g., choose(dog, dog, dog, cat) would be 3/4 likely to return dog, 1/4 likely to return cat.)
  6. random_get_seed(): Gets the current seed value for the randomizer.
  7. random_set_seed(): If you need a randomized, but deterministic function, you can set the seed for your random function. (This approach of setting a known seed is how the levels in Pitfall for Atari 2600 were always the same even though they were generated by the Atari’s random number generator.)
  8. randomize(): Sets the seed of the randomizer to a random value.

These are scripts you may import into your project:

  1. gauss(median, deviation): Returns a random value with a gaussian (“normal”) distribution around a median value. From GMLScripts.com.

All programming languages have similar random functions or classes built into them. Whatever tool you happen to be using, it pays to learn about how it can produce random numbers, and how you can use them to do useful and interesting things.

If you have any favorite ways of using random numbers in your programs, post a comment below and share it!

Keeping randomness under control

One of the mistakes most game developers will make when using random functions is to use too wide a range of random values, or failing to control the range of values returned by the random function.

Know your math

Randomness feels most random when the probability distribution is flat. However, this often does not make for the most interesting gameplay mechanics. It’s often more useful to have a weighted function that has a greater probability of returning a value in one part of the range than in another. Understanding probability math is key to getting your randomized functions under control. The other key is to develop your intuition to know what range of values will work best for a given situation.

If you’ve ever played tabletop role playing games, then you know about dice. Dice are good analog randomizers, and can help us understand probability and randomness in a computer program. In classic Dungeons & Dragons, character ability scores are randomly determined by adding the values of three six-sided dice. This results in a bell curve, meaning that the results of a 3d6 roll are distributed in such a way that an “average” score between 9-12 is far more likely than an extreme score of 3 or 18. So one way to directly simulate this type of dice rolling in a computer program would be :

N = 0;
repeat(3){N+=irandom_range(1,6)}; // generates a value between 3-18, distributed around 10.5

In computer programming, there are more efficient ways to achieve a bell curve distribution than this. Calling random() multiple times, and writing loops will make your code slow, so if there’s ways to avoid doing that, it’s a good idea. The gauss() function from gmlscrips.com creates a “normal” distribution around the agrument passed into it, and is fast and efficient.

round(gauss(10.5, 3.5)); //simulates rolling 3d6, approximately

Note that this will not return exactly the same distribution of values as a true 3d6 roll will. But this is because 3d6 is actually an approximation of a gaussian distribution — the gauss() distribution is more accurate to a “standard normal” statistical distribution. If you compared graphs of the bell curves of 3d6 vs. the gauss() function, the gauss curve would be smoother, and would include values outside the 3-18 range (2 and 19 would show up a tiny percent of the time).

There are other types of distibutions that you might want to achieve with your randomized functions, for some purpose. Knowing your math is important here. Learn the graphs of common functions, and understand the relationship between the shape of the graph and the probability distribution of a randomized function modified by each function. For example, random(x), ln(random(x)), and random(x)^2 have very different looking distributions. Knowing this, you can tailor an equation to fit your needs.

Once you get comfortable with the math, it’s actually fun. Play around with a graphic calculator and see what different graphs you can come up with. Each time you discover an interesting or useful shape, make note and file it away for a time when it might be useful.

Testing

Because adding randomness to your functions make the game non-deterministic, it can make things more difficult to test. Certain conditions become hard to duplicate, because you don’t directly control them, and this can make repeatable testing of your game seem impossible.

There are approaches you can take to ensure that your code works, still. First, when you are building up your functions, ensure that the non-random parts of the code work well before you introduce randomness. If necessary, temporarily remove the randomization and replace it with a literal value, a constant, or a variable. Once you are have tested thoroughly and are sure the code is working correctly with a range of controlled values, you may safely replace the controlled values with random values that are constrained to the ranges you tested.

In some cases, you may need to go back and re-test code. It would be a pain to have to find/replace every random() call in your code. Not only would it be time consuming, it would increase the opportunity for errors to creep in. A better approach may be to comment out the equivalent non-random code next to the random code, and leave it in your code file. That way you just have to comment out the randomized function and un-comment the deterministic version.

Even this is time consuming and error prone, however. You may want to create randomized and non-random versions of your functions, and introduce a configuration variable that you can toggle to enable/disable randomness. Then you can pepper your code with things like:

if settings.random {randomized_function()} else {deterministic_function()};

All this extra branching in your code can get ugly and unmangeabeable too, so try to limit this to keep it to a minimum.

You could also use polymorphism to create sibling classes, one which inherits randomized functions, and one which doesn’t, and just spawn the appropriate class instances according to the game configuration at runtime.

The great thing about being able to turn randomness on or off at runtime is that it allows you to very quickly see the difference, reducing the lag time between test runs. This could even turn into a feature of the game, rather than a debug exercise.

With proper care taken during development, randomized functions can be just as reliable as deterministic functions. It just takes a little extra forethought and planning.

Game Maker HTML5 and WordPress

Site traffic on the WordPress portion of csanyk.com is up due to Ludum Dare. According to my Jetpack stats counter, got about double my usual visits on Saturday, mostly as a result of posting my alpha build of Karyote. Traffic yesterday was about at the same level. It’s too early to know whether the increase in traffic will be sustained or not, but I’d expect there might be a small bump with a long tail.

This does not include hits of the actual Karyote game url, which is not hosted within my WordPress site. I haven’t looked at the awstats numbers yet, but I’m kindof curious to know many people are playing the game now.

I’d like to get my Game Maker HTML5 games better integrated to WordPress, but (as of the last time I played with doing that, during the GM:HTML5 beta, at least) it is tricky, and I haven’t gotten it working right yet.

Game Maker Studio auto-generates a basic HTML5 page for your game when you build it, but it’s not a simple matter to cut and paste the necessary code from that page into a WordPress page.

YoYoGames should probably think about providing CMS integrators so that people can have an easier time packaging their games in a way that allows them to integrate with WordPress, Blogger, Drupal, Django, and other CMS frameworks.

While I’m wishing, it’d also be cool if Studio has a feature allowing you to modify the template used to generate their HTML5 page. That feature could exist for all I know, I need to get more familiar with the HTML5 features of Studio.

Hopefully if they don’t, at least the dev community will step forward and address it.

Karyote (Enhanced)

I’ve patched a few bugs and added some enhancements to Karyote, and plan to make several more changes in the next few days as I’m able. There’s a post about it on my Ludum Dare journal.

I thought I’d write up a little postmortem of the enhancement here:

After struggling with the idea and trying to come up with what the game should be all weekend, and being disappointed with what I was able to deliver by the compo deadline, it’s really interesting to me that I’m actually starting to like this game now that I’ve fixed the first two high priority issues.

What I take from that is that I am better at critiquing and improving something that exists than I am at coming up with something new. That’s consistent with how I know myself, too. What’s interesting to me about this is that I somehow am able to switch from being a “whole cloth designer” coming up with a new game design to a “critic” and when I’m in critic mode, I know just what the game needs, while when I’m trying to develop the design that “designer” mode me came up with, I get frustrated and hate what I’m making. Maybe it’s not so weird, though — it could be all I really needed was to play it enough to figure out what it needed.

Comments I’ve received on my game have been generally positive, as well, which surprises me. I wonder whether commenters/raters apply a sliding scale of expectations when it comes to providing feedback. I mean, it’s one thing to compliment someone on an effort that was good relative to their current ability and constraints. It’s another to say that a game stands up relative to other entries, or even among all games of all time. I think it’s safe to assume that the comments I’ve gotten aren’t expecting LD games to be among the all time greats, and that people are generally inclined to deliver positive feedback and encourage the developer, rather than slam it.

I tend to judge myself more along the “all time” basis, though, which is harsher but also a higher standard to aspire to, and pushes me to do better. So it’s surprising to me when people say they enjoyed something I made when I don’t think holds a candle to Pac Man. But it is really nice to know that people have tried my game and that some of them have even enjoyed it. Getting comments, good or bad, is extremely positive for me. Just having the knowledge that people tried it out makes me feel like it was worthwhile to make it.

 

Ludum Dare 24 Postmortem

I’ve posted a postmortem of my LD48 #24 project, over on my ludumdare.com journal.

After poking around for my old journal entries on ludumdare.com, I think they may purge content, so in case that’s true I’m mirroring the post below, after the cut:

(more…)

LD48 24: Evolution. Karyote alpha

It’s not much at all yet, but I have an alpha build of my entry for Ludum Dare 24: Evolution up and running in HTML5.

Karyote

It’s not really playable yet, at the moment I’m just working out some motion and object prototypes. Graphics are all placeholders. You’re always in the center. Move with the arrow keys. Left/Right turns, Up moves forward.

Somehow, I’m doing another game with a microorganism theme. LD#23 was Bactarium, LD#24 will be called Karyote. You control a single celled organism that mutates as you play.

I still need to figure out what exactly you’re doing in the game, but I have some ideas that I haven’t implemented yet, so I’m a little further along than it looks as far as the concept goes. I’m designing as I go, mainly this is design by fiddling around. That’s a dangerous way to go on any project, but when I don’t have much of an idea to begin with, I find it’s one of the most reliable ways of getting me going. Hopefully I’ve learned enough lessons from previous projects to avoid messing up the code architecture, so debugging and feature changes don’t turn into a nightmare toward deadline.

Ludum Dare 24 This Weekend

It wasn’t that long ago (late April, in fact) that I participated in my first Ludum Dare. I really enjoyed that experience, and am really looking forward to Ludum Dare 24 this weekend. I’ll be hanging out this weekend at our Cleveland Game Developers LD48 site, generously hosted at the Shaker Launch House space.

I plan to work solo, and entering my game into the compo, again, but one of these times I’d really like to get into a team and work on something as a group. For the weekend, I’ll be blogging on my page on the LD site, so be sure to check there and see how I’m doing.

I’m trying to think about my goals for the last LD48, and how I’ve grown since then and what my new goals should be.

LD 23 goals:

  1. Finish a solo project in 48 hours. Achievement unlocked!

LD 24 goals:

  1. Blog my progress as I go, self-documenting the development process. Last time I blogged a little bit, this time I want to take that further.
  2. Post playable builds as I go, not just at the very end. Last time I saw other people doing this, and I felt envious as they got feedback from people playing sneak-preview releases of their projects. I was super impressed that they managed to release something playable so quickly, but I have some ideas about how to accomplish that.
  3. Produce builds for Windows, OSX, and HTML5 to reach a wider audience. Last time, I was still using Game Maker 8.1 Professional for my project, which limited me to Windows. This time I’ll be using GM:Studio. This will be my first project targeting multiple platforms, so kindof a new thing.
  4. Use fellow CleGameDevs people for feedback and encouragement. We used IRC for this, and had our first night at a common space, which was good. I just want to do this more.
  5. Play and rate more entries. Last time I did play a lot of games during the rating period, and played even more after the rankings were posted.

Incorporating music into my game will probably remain a future goal, for now. I’ve experimented a little with FamiTracker, and may attempt to produce a little music for my game, but I still think becoming a chiptune artist is a far-away goal. I think music is a really important element of videogame design, but it’s probably better to have no music at all, rather than bad music. There are certain game themes which lend themselves to silence, so I can possibly use that, or I can make a game that has an overwhelming amount of sound effects in it, like my last LD48 entry. Or maybe I’ll get lucky and one of our musically talented CleGameDevs people will throw me some resources, and I’ll make it a Jam entry instead of a Compo entry.

Tonight and tomorrow I plan to go over my preparation checklist and make sure I am ready. Gotta make sure all my software is up to date and working properly.

Robotron: 2084 and Zookeeper

Today was the day of Cleveland’s Classic Console and Arcade Gaming Show. This year was especially well attended, and I was very happy to see a higher proportion of female gamers attending. I’ve been going since I heard about it 2005, and every time I go there is always something I have never seen before, and it’s always a good time. In addition to rows of tables with old games to buy and look at, some homebrew and modding fun, and some old school systems set up with games to play, there are drawings and tournaments.

This year, they had two of my favorite 80’s arcade games: Zookeeper and Robotron 2084. Robotron was a tournament game. I thought I might have a chance at winning, but I didn’t come close to the top score — although I did have the second highest score. I played a lot of games to get sharp, but my top score of 214,000-some points was still far from the winner, who posted a score of almost 391,000. It’ll take me a while to get that good.

While the experience is still fresh in my mind, I thought I’d reflect on what makes Zookeeper and Robotron two of my favorite games.

(more…)

Making a Configuration System in Game Maker, part 2: Requirements

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?

  1. I like my imagination. It’s awesome, and using it is fun.
  2. The more I think about things, the better my ideas get.
  3. 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.
  4. 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:

  1. Features: What options do we want the user to be able to configure? What choices do we want each configuration option to have?
  2. Interface/Controls: How do we want to present these options to the user? How will the user interact with the interface to set it?
  3. 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.