An appeal for better YouTube video tutorials

I like people who put up how-to videos on YouTube showing how to do things they enjoy doing, particularly videos about gaming, game design, development, programming, art, criticism, reviews, you name it. But, unfortunately the majority of them are not as well produced as they should be.

The equipment to make videos is cheap, readily available, and increasingly easy to use, but making a good video is still not a simple thing. High quality production values and good content is requires work, but time and again I see a lot of the same amateurish mistakes made, and a lot of them are easy to correct.

Set up

  1. Test your recording and capture setup. Test your setup! Test your setup!
  2. Do a quick sample take, and quality-check your results. If there’s a problem with the quality, bite the bullet and re-do the video. But avoid wasting that time by verifying the setup is right before you start production.
  3. Check your audio levels before recording. I can’t tell you how many videos I can’t hear on my laptop’s speakers. But I have no problem at all hearing audio on my laptop when the recording levels were good.
  4. Make sure that the audio track is audible, that there is no background noise, buzzing, dogs, traffic, airplanes, or anything else that distracts from the audio. Clear and sharp is nice to listen to.
  5. Test your video capture quality. If you’re dropping frames, or getting blurry results, figure out why, and fix it before you post a video. Trying to read code through low-resolution downsampling or mpeg artifacting is awful.

Content

  1. Know what you’re talking about. Take the time to really learn your subject before you go out and publish videos. You don’t need to know it inside and out, but do know the topic you’re going to cover.
  2. Think about what you’re going to say before you say it. Write up an outline or cue cards or a script if you need to. Have an agenda and don’t stray too far from it.
  3. Get right to the point.
  4. It’s fine to re-record the audio track and narrate over the video — it’s really hard to talk and do something that requires skill or thought at the same time. If you’re doing a programming tutorial, much of the video will probably be a still image of the screen, which you can pause and talk over as long as you need to.
  5. Practice and rehearse. Don’t subject your audience to you fumbling about with your words or with the tools. There’s nothing wrong with stopping and doing it over, or at least editing out the mistakes. It’s harder than it looks. If you make a mistake, just keep going back and try again until you get it right, and then edit out the mistakes.
  6. Speak naturally, but clearly and out loud, like you’re talking to a room full of people, rather than mumbling like you’re trying to avoid waking up someone sleeping in the next room. Try to project some vitality and excitement.
  7. Have an intro. Get it out of the way quickly, but have it. Tell people who you are, where people can go to find out more about you and your projects, and what you’re topic you’re going to be talking about today. Say it out loud, put it in print on the screen, and put it in the video description.
  8. Video footage of the working project being demonstrated. Show off all the features. This is the part of the video that will get attention and draw people in.
  9. Now go under the hood. Now that you’ve shown us what your demo can do, take us on a tour of the code and explain how it works. This is the really interesting part of the video.
  10. Iterations. If you build up the project in iterative phases, show that process. It’s very helpful to show new programmers how to break down a problem into smaller parts, and put those parts together and refine the approach toward a well-polished solution. Show the project in its stages of development, but don’t force us to watch the entire process start to finish. Skip to the good parts.
  11. If it’s interesting, talk about alternative approaches, their pros and cons, and why you chose to do things the way you did. Was performance critical here? Flexibility of the solution? Code maintainability? Modular design? If there’s controversy over one approach vs. another, do a side by side demo of each approach, comparing their strengths and weaknesses.
  12. Think about ways to say what you’re saying more simply. Don’t think on camera. You’re supposed to be presenting what you know, not discovering it.

Postproduction

  1. Edit! If you are rambling, or misspeak, go back and edit it out, or do a re-take.
  2. Some people like to appear on camera. Nothing wrong with that. But when it’s time to show what’s on screen, switch to video capture software as your input source. Don’t film the screen over your shoulder. Use your editing software to stitch the shots together. You don’t have to do it all in one take.
  3. Subtitles are appreciated, but if at all possible, don’t do “poor man’s subtitles” by opening up a text editor, setting the font big, and typing what you’re doing. Especially, don’t use this as the only method of conveying what you’re doing, in lieu of voice narration. Watching you type in realtime is extremely boring, especially if you hit backspace a lot.
  4. Unless the video is on the topic of how to use the IDE, try to shorten or eliminate the amount of time devoted to navigating the interface. Most people know how to create a new asset, drag-and-drop a command into the Actions pane of the object editor, or type a file already. What’s interesting is what you’re putting in the asset. If you want to walk people through some code, that’s great, just don’t make us watch you type it. Paste it in, and then go through it line by line, highlighting the line you’re talking about if necessary. Instead of building the project up in front of the camera, walk people through a pre-built project, explaining it in detail.
  5. Make your code style as presentable and readable as possible. Your code should be beautifully formatted with a extra attention paid to readability. Use well-chosen names for assets and variables. Use whitespace and indenting. Don’t code slop with the excuse that you’re doing things quickly because you’re on video. We’re watching the video in order to see how well you can code.
  6. Don’t put a musical soundtrack in your video, or any other sort of filler audio. Narrate. Intro/outro music is fine if you’re shooting for professional polish, but not necessary. If you do use music, make sure a) it doesn’t suck, and b) it doesn’t get your video pulled for violating someone else’s copyright.
  7. Ask yourself: Does the video need this? Cut extraneous bits. If you need to fiddle with your mic, or answer the phone, or whatever, cut it.
  8. Ask yourself: Could I have done it even better? Re-do it.
  9. Don’t post junk. If it didn’t turn out well, you don’t have to post it.
  10. Don’t shoot for absolute perfection. A few minor flaws are excusable. But do try to make the best quality videos that you can.

Essential extras

  1. Host a demo project file somewhere, and link to it from the video description. If you’re sharing your knowledge and techniques, you might as well share your code. You’re already sharing it through the video, but by not including the downloadable project, you’re forcing everyone to waste their time re-typing in your code. There’s really no reason not to just provide it. There are many options for free file hosting services: google drive, dropbox, mediafire, github, sourceforge, the list goes on.

GameMaker Tutorial: String handling and Drawing Text

[Editor’s note: This article was written primarily with GameMaker: Studio 1.x in mind. There have been some changes to the way GameMaker Studio 2 handles strings, mainly dealing with escaping codes, and this article has not yet been updated to reflect that. Refer to the official manual chapter on Strings for all the details.]

Drawing text to the screen is a basic part of most videogames. There are a huge number of useful applications for text. Just a few of the more common applications:

  1. Score
  2. HUD/Dashboard
  3. Menus
  4. Special effects
  5. Messages and dialogs
  6. Instructions/Story
  7. Debugging/diagnostics/benchmarking — it can be incredibly useful to draw the current value of variables to the screen when debugging, or performance metrics.

Things to know about drawing stuff in GameMaker

  1. Draw functions only work in Draw Events:  If you try to use them anywhere else, nothing happens. If you’re drawing in the Draw GUI Event, you’ll want to be familiar with the draw_set_gui_size() function so your Draw GUI stuff will be drawn to the proper scale if you’re using Views.
  2. Drawing directly to the screen (especially text) is slow. Draw a lot of text and performance will suffer.
  3. There are ways to improve performance when drawing text. The most important of these is to use Surfaces. Surfaces are not available in the free edition of GameMaker, and not all hardware may support them. Using surfaces properly is not that difficult once you understand them, but is generally considered to be an “advanced” concept in GameMaker, and is less straightforward than drawing directly to the screen in the “normal” way.
  4. But there are challenges. Setting up a Surface for optimizing text performance is tricky because it can be hard to know in advance how large the surface needs to be to contain the text you are drawing. Fortunately, GameMaker provides some useful functions which can enable you to get the dimensions needed for the surface: string_width() and string_height(), which give you the width and height, respectively, in pixels of a string drawn with draw_text() in the current font. If you’re using draw_text_ext() string_width_ext() and string_height_ext() are the functions to use instead. These functions allow you to create a drawing surface of proper dimensions, provided you know the string and font and can decide on a width prior to creating the surface. Keep in mind that the dimensions of a string depend on the font used to display it, so always use draw_set_font() to set the font to the correct one that you intend to draw the string with before using the measurement functions.
  5. Draw settings (for things such as color, alpha transparency, and font alignment) are global in GameMaker. That means that if you have multiple objects which draw functions, and if any of them changes the color, alpha, or font alignment, all objects will be drawn using those same settings. For this reason, if you are using draw functions in your objects, it’s best to set all the draw settings in the object in order to make sure they are what they need to be. If you never change color, or alpha, or font alignment, then you don’t need to set that property before you use draw functions — but if you do need to change them for one object, it’s best to set them to what they need in the Draw event of every object, immediately before calling the drawing routines.
  6. For serious performance optimization, you need to learn how GameMaker “batches” drawing operations, and organize your code to have the least number of drawing batches as possible.

Fonts

Everyone these days knows what fonts are, right? Fonts are like the clothes that text dresses up in when it wants to go out and be seen. In GameMaker, fonts are game resources, just like sprites, or objects, or other resources, and need to be added to the project — you don’t simply have direct access to the same fonts that are installed on the system, you have to explicitly add a font to your project. If your project has no font resources set up, text drawn to the screen will still render, but oddly and probably not consistently across platforms. So, always define a font resource and make sure that it’s used if you’re drawing text.

To save space, you can define a font resource to include only certain character ranges, such as number digits only, or alphabet characters only, or only the upper case or lower case letters in the alphabet. If you know you won’t be needing certain characters, and are concerned about the size of the game when it is built, go ahead and constrain the range. Otherwise, the default range of 37-128, covering A-z, 0-9, and special characters, is good.

For legal reasons, it’s important to note that fonts are copyrighted, and most need to be licensed for commercial use. There are free fonts out there (google for them) with liberal licensing terms that you may be able to use in your project, if the terms of the license allow.

Of course, you can create your own fonts. Creating your own font is outside the scope of this article, but there are tools you can use to produce your own fonts if you’re crazy enough. It’s probably easier to simply purchase a license for a professionally designed font.

Formatting issues

Alignment

Text alignment is set using the and draw_set_valign() functions. Use GameMaker’s built-in font align constants {fa_left, fa_center, fa_right, fa_top, fa_middle, fa_bottom} as arguments to these functions to keep the code readable.

New Lines

To signify a new line in a GML string, use the pound character (#). The GML code

draw_text(x, y, "Hello#World");

would be drawn like so:

Hello
World

You can also use a literal return in your string, but it’ll make your source code look yucky.

draw_text(x, y, "Hello
World");

Would draw to the screen exactly the same as “Hello#World”.

Escape characters

If you’re familiar with strings in programming languages, you know that it gets tricky when using certain characters that are reserved for program syntax or markup. Most languages allow you to “escape” the markup syntax so that you can still use characters normally reserved for markup purposes as literal characters in a string. GML is no exception.

#

What if you want to use a # in a string, and you don’t want it to signify a new line? Use the “#” escape character.

The string "We're \#1!" would be drawn like so:

We’re #1!

Quotes

A matched pair of quotes, single or double, can be used in GML to begin and end a string. If you want quotes to appear as text within a string, you can use the other type of quote to encapsulate them, like so:

my_string = 'This is a single-quoted string.';
my_string = "This is a double-quoted string.";
my_string = 'This is "an example" of a string including double quotes-as-text.';
my_string = "This is 'an example' of a string including single quotes-as-text.";

It gets tricky when you need to have BOTH types of quotes in the same sentence:

my_string = 'Bob said " We shouldn' + "'" + "t."+ '"' ; // Bob said "We shouldn't."

It looks like a mess, but you just have to do a lot of concatenation and quote your quotes with the other type of quote marks.

String concatenation

As with many languages, you can combine two strings together by adding them with the + operator. With number values + adds them; with strings, + concatenates the two strings together, creating a longer string made of the first one and second one stitched together. You can do this with literal string values, or with variables containing strings:

concatenated_string = string1 + string2;
concatenated_string = "Hello " + "World";

But if you try to add a string and a number, you need to tell the program to convert the number into a string. The string() function will convert numeric values to strings, which allows them to be incorporated into a larger string.

health = 100;
draw_string(x, y, "Player1 Health: " + string(health));

GML String functions

We’ve already introduced a few of the more commonly useful ones, but there are many other useful GML string functions. I’m not going to go into each one in depth, but review the official documentation and keep in mind that they’re out there, and can be useful.

One important thing to be aware of with GML strings is that, unlike most other languages, GML strings are 1-indexed, not 0-indexed. This means that when counting the characters that make up the string, the first character is character 1, not character 0.

GML text drawing functions

Mostly I have used draw_text() and draw_text_ext(), but it’s good to know that there are a few more variations on these basic text drawing functions.

  • draw_text
  • draw_text_color
  • draw_text_ext
  • draw_text_ext_color
  • draw_text_ext_transformed
  • draw_text_ext_transformed_color
  • draw_text_transformed
  • draw_text_transformed_color

It might seem like a lot to keep track of, but it’s pretty easy if you remember the following:

draw_text: basic draw text function.

_ext: allows you control over the line spacing and width of the draw area. This means you don’t have to manually handle line breaks by inserting # or return characters in your text.

_transformed: allows you to scale and rotate the drawn text.

_color: allows you to set a color gradient and alpha to the text.

Again, text is always drawn using the current global drawing color, alpha, halign and valign properties. It’s best to set these before drawing to ensure that they are the expected values, using draw_set_color, draw_set_alpha, draw_set_halign, and draw_set_valign functions.

Keep code clean by storing strings in variables

This is perhaps obvious, but it’s often useful to store a string value in a variable, to keep your code neater and easier to read.

draw_string(x, y, "Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal.##Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battlefield of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this.##But, in a larger sense, we can not dedicate, we can not consecrate, we can not hallow this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us—that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion—that we here highly resolve that these dead shall not have died in vain—that this nation, under God, shall have a new birth of freedom—and that government of the people, by the people, for the people, shall not perish from the earth.");

— is a lot harder to read than:

draw_string(x, y, gettysburg_address);

— and moreover, all that text gets in the way of comprehension of what your code is doing. So use variables to store strings, and keep your code looking clean.

draw_text_ext()

While we’re dealing with a very long string, it’s a good opportunity to talk about a function that makes drawing them much easier.

You could manually set line breaks in a long string by sprinkling #’s every N characters or so, but that is laborious and inflexible. It’s better to use the draw_text_ext() function, which allows you to specify a width for the line, and (optionally) also how many pixels should separate lines.

draw_text_ext(x, y, string, vertical_separation, width);

When drawn, the line will automatically break when it reaches the width provided to the function.

Formatting

GameMaker is rather limited in its typographical capability when drawing text to the screen. GameMaker Font resources, unlike an installed font on the system, are a specific size and style only. There’s no bold or italic or other style options available that you can use to modify the font resource. If you want bold or italic, you have to create a new font resource, and use draw_set_font(font) to that resource in order to use it.

This means that if you want to use bold text in a sentence, you need to create a second font resource for the bold font, draw your normal text, then switch fonts to the bold font, and draw the bold text, somehow positioning the two different drawings so that they look like they’re a single block of text. You have to leave a hole in your normal text where the bold word will appear. This is not easy, nor is it generally recommended. If you really want it, and are masochistic enough to put yourself through the trial and error to do it, go ahead. But before too long you’ll probably realize that it’s not worth the effort.

See this script draw_text_rtf which allows you to draw rich text format, originally written by Miah_84 and improved by me.

Special Effects

Scrolling text

Scrolling text is extremely easy to do. The draw_text function must be called by some object, and includes arguments for the x and y where the text will be drawn. Simply change the x and y over time, add you have moving text. The easiest thing to do is to set the instance that is drawing the text in motion.

Typewriter text

Another easy to implement technique is “typewriter text” — that is, displaying a string one character at a time as though it were being typed out.

First, let’s take a string stored in a variable, my_string.

string_length(my_string) will give you the length of my_string.

draw_text(x, y, my_string) would draw the entire string at once. But we want to draw it one letter at a time.

The GML function string_copy(string, index, length) comes in handy here. We can use this instead of string in our draw_text function:

//In the Create Event
typed_letters = 0;
//In the Draw Event
draw_text(x, y, string_copy(my_string, 0, typed_letters);
if (typed_letters < string_length(my_string)) {typed_letters++};

Note that this will type at room_speed characters per second, which at 30 fps is extremely fast. You may want to type slower, in which case you can slow down the function in one of several ways. You can use an alarm to increment typed_letters every N steps, rather than increment it in the Draw event. Or you don’t want to bother with an Alarm event, you could do something like this:

//In the Draw Event
if typed_letters < length {typed_letters+=0.1;}
draw_text(x, y, string_copy(my_string, 0, ceil(typed_letters)));

This would give a typing speed of room_speed/10, or 1 character roughly every 0.33 seconds for a 30 fps room, or 3 characters/second, which is a bit more reasonable. You can adjust this rate to taste.

If you want the text to reset and type over again when the message is completed, you can do this:

if typed_letters < length {typed_letters+=0.1;} else {typed_letters = 0;}

Additionally, you can optionally add code to play a sound with each letter, or start a sound when the typing starts and stop the sound with the full length string has been reached.

Marquee text

The Typewriter Text technique can be modified slightly to draw a scrolling marquee:

//In the Create Event
/*Hint: you may want to pad the end of your marquee string with extra spaces so it 
will scroll all the way off your marquee.*/
my_string = "Some text for your marquee "
start_letter = 0;
marquee_length = 10; // or however many letters in your marquee
type_rate = 3/room_speed; // 3 char per second
marquee_scrolling = true;
//In the Draw Event
if marquee_scrolling{
 draw_text(x, y, string_copy(my_string, start_letter, ceil(start_letter + marquee_length)));
 start_letter += type_rate;
 if (start_letter > string_length(my_string)) start_letter = 0;
}

Blinking text

Blinking is annoying in web pages, but can be a very useful effect in games. Blinking attracts the eye, and can get attention where it’s needed. Of course, blinking can be done with any graphical element, not just text.

Blinking is just turning on the drawing and then turning it off on a cycle, using a timer, such as an Alarm Event.

//In the Create Event
blink = true; //(or false, if you want the initial state to be off)
blink_steps = room_speed/2; //for a 1 second blink cycle. Set this value to suit.
//In the Alarm[0] Event
blink = !blink; //toggles the blink from on to off or vice versa.
alarm[0] = blink_steps; //re-sets the alarm so it keeps blinking
//In the Draw Event
if blink {/*do the draw stuff*/}

The above code gives a 50% “duty cycle” (the blink is “on” 50% of the time, “off” 50% of the time). It’s possible to vary the duty cycle in a variety of interesting ways…

//In the Create Event
blink = true; //(or false, if you want the initial state to be off)
blink_on_steps = room_speed/2;
blink_off_steps = room_speed/4;
//In Alarm[0]
if blink {alarm[0] = on_steps;} else {alarm[0] = off_steps;}
blink = !blink;

This blink code will result in a blink that stays on for 0.5 seconds, and blinks off for 0.25 seconds.

Even more sophisticated blink periods can be achieved using math functions rather than a static value. Setting alarm[0] = irandom(10) would result in a random flicker. Think of creative ways to use other math functions to create interesting effects. If you come up with a good one, share your code by posting a comment to this article.

Yet another way to flicker or blink text is through varying alpha. Or by switching colors. Or even size.

One last way to blink is to toggle the state of the visible boolean in the instance.

visible = !visible;

One thing to keep in mind, though, is that an instance that is not visible will not be checked for collisions. Also visible applies to the entire object’s Draw event, so it is all or nothing. Still it is a simple way to draw or not draw an object.

What next?

If you’re familiar with other programming languages, you may be disappointed at the limits of the built-in functions for manipulating strings. There are a lot of things you can do more easily in other languages than in GML, unfortunately. Since GML only has two data types, strings are extremely important, but because games tend to focus more on graphics, sound, and interface, the average GameMaker developer can get by with the string functions that do exist, for the most part.

There are a number of useful GML scripts for doing more advanced things with strings that have been collected at gmlscripts.com. Many of the functions built in to more mainstream programming languages can be found there.

GameMaker tutorial: Elegant instance_change() in your state machine

In GameMaker, a commonly used technique is to build a system made up of a several objects to represent an entity in your game, such as the player or enemy, in various states, such as idle, dead, shooting, jumping, running, climbing, and so forth. This is what is known as a Finite State Machine pattern.

When the time is right in the game, we change an instance from one state object to another by using the powerful instance_change() function. Instance_change() takes the instance and transforms it into a new type of object. Its Event behaviors will change to those defined by the new object type, but its old properties (object variables) will remain the same as before, allowing the instance to retain its variables with their current values.

The instance_change() function takes two arguments: object, the object the instance will turn into, and perform_events, a boolean which controls whether the new object’s Create event will be performed or not.

Normally, the Create event is where an object initializes its variables and initiates its default behavior. When we’re dealing with a State Machine comprised of a number of objects, this can become problematic, however. Some code in the Create Event is initialization code that we may only want to execute one time, to set up the instance when a brand new instance is created, while other code in the Create event is behavioral and we may need to execute whenever an existing instance reverts back into that state again. Thus, the perform_events argument in the instance_change() function isn’t adequate for this situation — it’s too all or nothing.

For example, let’s say I have a generic object for an enemy, oEnemy. I want some visual variety to this enemy, so I’ve created a few different sprites for it. In the Create Event, I want to randomly choose one of those sprites to be the sprite for this instance. But if the instance changes into another state object, and then reverts back, if I call the Create Event, it will randomly choose a new sprite. I don’t want this, as it ruins the illusion of continuity — I need that instance to retain its sprite. But I do need the Create Event to run, whenever it re-enters this state, because I’m using it to set the instance in motion.

So, how can I elegantly select which lines of code I want to run in the Create Event?

Conditional blocks

This is the least elegant solution, but you could use if to check whether a variable exists or has a value. For example:

if sprite_index == -1 {sprite_index = choose(sprite1, sprite2, sprite3);}

This is inelegant because it adds lots of lines of code that only need to be run one time (when a brand new instance is created) but need to be checked potentially many times (any time that instance changes back into the object state). It also only checks certain, specific things, case by case. As I continue to build the state machine, I may end up introducing more features which require initialization, which would necessitate more checks, further bloating the code. I always want to write the least amount of code needed, both for reasons of performance and maintainability.

Move one-time code to an init state object.

The more elegant solution is to recognize that initialization is its own state, and we need to separate it out from the other states in the state machine. We can create an oEnemy_init object, put our one-time initialization code into it, and then the final step in the Create Event for the init object would be to change the object into the default state.

None of the other states in the state machine should put the instance back into the init state, thereby guaranteeing that the init code only executes once. Now your code is neatly separated, your states objects in your state machine are as simple as can be.

Radar

I’ve been messing around with mini maps, and after a few different approaches, I have come up with a cool demo that simulates a radar screen. The screen even has a sweeping beam that lights up the blips, which fade over time. Only instances which inherit from an object called oMappable are drawn on the radar. The size of the blips is based on the width of the sprite of the oMappable child, so objects of differing sizes will be shown in scale relative to each other.

radar screenshot

It runs quite well, with up to 4000 simple objects (~30fps on a 2.0GHz Core2 Duo).

Demo (.zip)

Project Source (.gmz)

Vendor Hosting, SaaS, Cloud Computing: What’s the difference?

When talking with non-IT people, it’s amazing (ok, not really) how much confusion there is about concepts and what these terms mean. While the terms are related, they are far from interchangeable. People soemtimes like to throw around “buzzwords” in order to sound like they’re knowlegable or on the cutting edge. If you deal with this stuff, it’s good to understand the differences.

Vendor Hosted

Vendor hosting is a relationship. Vendor == someone you’re paying to do something for you. Hosting == the something you’re paying them to do. You don’t own the hardware, they do.

This can be wonderful if you won’t want the expense and complexity of deploying and maintaining the hardware, and if the vendor is good at doing those things.

But it can suck if your vendor doesn’t provide good service, or shuts down suddenly, leaving you with no access to your data.

Software as a Service

SaaS is a business model. With software as a service, you’re paying like you pay for a utility, based on your usage, or subscription, based on time. Like utilities, if you stop paying, you can’t use it anymore.

Contrast SaaS with Free software and licensed software models.

Free software is, well, free. Often the software itself is free (cost), but you pay for support or for customization, or by devoting resources to maintaining the codebase.

Licenses are typically perpetual, but limited to a major release version and its patches. When the next major release comes out, you have to pay for the upgrade. Usually the vendor compels their customers to upgrade by dropping support for the old version, offering discounts on upgrades for existing licensees, and so on.

Unlike the licensed software model, with SaaS you’re usually entitled to the latest version, not paying for upgrades. Often, but not necessarily limited to, vendor hosted solutions.

This can be wonderful if:

  • You hate managing licenses.
  • The upgrade treadmill gets you down.
  • You’re cool with fixed costs and realize you can either pay the vendor once a year for the next version or the same amount of money over the course of a year for the SaaS model.
  • You don’t use an expensive solution very much, but would be in the market for a solution you can spend a small amount on for what you do need. Like, you’re not going to spend $25000 for CAD software, but if I could pay $25 to use it for a few hours, you’d be able to design that thing you want to build for your hobby.

But it can suck if you want to pay for something once and own it, or if the SaaS vendor goes out of business or decides to stop providing the service, or if for some reason you prefer to remain on a certain version of a product that meets your needs well enough, such that you have no compelling need to upgrade, or if the SaaS vendor’s upgrades take the product in a direction that doesn’t suit your needs.

Cloud computing

Cloud Computing is an architecture. A distributed cluster of redundant, co-located, and load balanced hardware, typically spanning multiple datacenters, which is used to run virtual machines which are not dedicated to specific hardware. The amorphous nature which decouples virtual machines from any specific node in the cluster is what gives rise to the term “cloud” computing.

“The cloud” may often be used as a generic term for “the internet” because on networking diagrams, the internet is symbolized that way, because the specific architecture of the internet is unknown and not really of concern to you. But just because something is on the internet does not mean it is “cloud computing”.

The cloud computing cluster’s capacity is typically shared among many customers. Due to the nature of the cluster, it is possible to scale a customer’s utilization of the cloud very rapidly, growing a virtual machine from a single node on the cluster to several or many. Conversely, the cloud may idle portions of the cluster when demand is low, resulting in great efficiency and flexibility. If a node in the cluster goes offline or experiences hardware failure, the cloud continues chugging along and only the admins will even notice that anything happened.

Cloud computing is also typically vendor hosted, since it requires specialized professionals to set up and maintain the cluster. Very few entities are in need of owning their own cloud, and will buy cloud computing in the SaaS model from a vendor who hosts it. You can pay for a tiny portion of the cloud, and as you grow you can expand your footprint on the cloud, paying more for it but generally not having to deal with many of the usual headache associated with scaling up a rapidly growing enterprise.

This can be wonderful if you can live with not owning your hardware and are comfortable with the idea that your data and processing could be “anywhere” in the cloud, co-mingling with other virtualized instances running on the same node(s) in the cluster.

But it can suck if your vendor decides they don’t need you or gets a request for your data from the government and just rolls over and complies with the request, rather than fighting it like *your* legal team would.

Bottom line

Any time you put your data or services in the hands of someone else, you really are putting a tremendous amount of trust in them. You need to consider not just the benefits of the relationship, but the risks as well.

Outsourcing is attractive because it’s expensive and difficult to do well, and if it’s not the core competency of your business to do enterprise IT, it may make sense to have someone else do it who has that expertise. But you need to make sure that your vendor actually does have that expertise!

The pre-sales people will promise you the moon, but you need to be able to verify that they can back those promises up. One of the great selling points is that you don’t have to worry about all the complexity of maintaining IT infrastructure anymore. But it’s not like that responsibility disappears into nothing — it’s the vendor’s responsibility, and you now need to worry if they’re doing it right. If you’re paying someone else to do it right because you don’t know how to do it right, and you’re trusting them to do it better, or cheaper, than you could, how do you do so with confidence that they’re really that good?

Usually, outsourcing puts up organizational boundaries which can be barriers to transparency — you can audit internal processes much more readily than external ones. But are you any better at auditing IT than you are at running IT? Probably not. There may be third party auditors who you can outsource to… but how do establish that you can trust them? 

So how do you establish trust? This is something you need to figure out before you move into a vendor hosted solution. One approach is to move gradually. Do a pilot project and see how it works over a period of time before jumping in with both feet. Plan for moving off of the vendor’s services so you can do so with short notice if need be. Utilize redundant vendors if that’s feasible, so all of your eggs aren’t in one basket.

Work at establishing trust continuously — trust is not a “set it and forget it” kind of thing. Trust comes from a relationship based on iterative transactions. It is built with each interaction that you have. Despite sales pitches, outsourcing does not mean that you don’t have to worry about things anymore. It means you need to establish a management relationship with people outside of your organization who are assuming responsibilities and risks which still affect you. It pays to maintain a close relationship with them.

If you’re not engaged with your vendors and don’t have good rapport with them, then chances are very good they’re going to ignore you, take you for granted, and fail to understand what your needs are, and when it comes time to deal with problems, you won’t be familiar with each other. Communicating effectively and working together will be a second-order problem that prevents you from fixing the original problem.

Don’t be lulled into a false sense of security, and don’t make the mistake that because something is the vendor’s responsibility, that you don’t have to worry about it. It’s still your enterprise that’s at risk. When everything’s running smoothly, it’s great, but problems may actually become more complicated, due to the vendor relationship and the fact that you don’t have direct access and full control over the systems they are managing for you.

Risk management is incomplete without an answer to the question, if the vendor goes away tomorrow, what do you do? If maintaining control over your data is critical, it’s a good idea to require that you have a local copy stored on hardware that you own. At the very least, the vendor should make it easy for you to export your data, ideally to a documented format which will be useful for you in the event you need to switch vendors.

Stat-Driven Causality: Better than pseudo-randomness!

Watch this video on how the “random” loot drops in the original Legend of Zelda were actually determined:

I found it very interesting. In my game projects, one of the more difficult areas of game design is getting the frequency of the loot drops to feel right.

Let’s look at the ways in which the loot drops in Zelda are not random.

  1. Loot drops happen because of an event, eg defeating an enemy. They don’t happen “randomly” for no apparent reason. This drives a feedback loop of “kill monster, get treasure”.
  2. Which type of item gets dropped is actually not random. However, it’s important for the drop to seem random to the player, so they never can be sure of what they’re going to get. This keeps them guessing and curious: “What will I get if I kill this monster? There’s only one way to find out; better kill it!” invites play much more than “Ho hum, here’s another [enemy]; I know they only drop [type], and I don’t need that right now, so I’ll just walk by it.”
  3. It does seem that certain types of enemies do drop certain types of loot a bit more often. For example, in the overworld Tektites seem to be pretty reliable about dropping rupees, and tend to yield a higher proportion of blue rupees that are worth 5. They do drop other things, bombs and hearts, and fairies, but it does seem like they will drop rupees a bit more than other types of enemies. There may be a similar relationship between other types of enemies and other types of loot. This gives certain areas of the map, where these types of enemies appear, have strategic value for “farming” a given type of resource.
  4. It would make sense that more challenging enemies might yield more/better loot, but I don’t notice this so much when I play LoZ. It seems that as you progress through the game, the difficulty of the monsters ramps up, matching your own power increase, but that the reward remains more or less constant. Still, in many games, there’s a directly relationship between challenge and reward.
  5. By connecting the frequency and type of loot dropped to a complex conditional based on the internal state of the game’s various counts, it’s possible to tune the difficulty of the game to a far more precise degree than could be done through purely random loot drops. For example, if the player is low on hearts, you could use that data to drive a slight increase in the amount of health drops, to make the game easier. Or, to make the game more challenging, you could make health drops rarer when you’re low. This can be tweaked so that “easier” areas of the game have the more generous/forgiving drop rate, while the harder areas have stingy/unforgiving drop rates.

Up until now, I have thought of loot drops as something based on completely random chance, not influenced by various factors being tracked in the game. I had played with various stochastic functions to create what felt like “right” odds to give the game the right “feel”, and wondered why simple random distribution never felt quite right.

But what is “right” is highly subjective, difficult to define, and requires extensive time spent playtesting in order to gauge “feel”. But now, I see a much more interesting potential in tying the frequency and/or item dropped to causal relationships to various stat counters. What’s great about tying the loot drops to in-game stats is that it allows you to directly apply mechanisms to balance the game, based on how the stats reflect the player’s performance, their progress in the game, and the amount of difficulty you want at that point in the game.

Exactly how to do this will still be very subjective, and require extensive play testing, of course, but it will be tune-able and in the control of the developer, rather than purely random chance. I am excited by the possibility of using the stats model to drive feedback loops which can help to govern the game’s challenge level, or to provide certain items when they are more likely to be needed, or just to make the loot drop frequencies seem a little more interesting and less totally random. It seems like a potentially much more elegant way of distributing items in the game.

HTML5 Game Development With GameMaker published

Today Packt Publishing announced the publication of HTML5 Game Development with GameMaker by Jason Lee Elliott. I was involved with the creation of this book as a technical reviewer, and as such I’m intimately familiar with its contents.

While the book title refers to HTML5 games specifically, most of the content is applicable to any development in GameMaker Studio, regardless of your intended build target.

Some of the highlights include:

  • Numerous examples of the “Finite State Machine” pattern implemented as a system of related Objects
  • Building a Box2D physics-based game
  • Creating a particle system
  • Facebook integration
  • Flurry Analytics integration
  • How to publish your game on the web.

If you purchase through the link below, Amazon will compensate me for the referral.

GameMaker Project Rot

My recent project, Genes, had a bug in it which didn’t really matter too much: Male creatures were supposed to seek the nearest available female, re-targeting every few seconds. And so too with females. But for some reason, the males were not re-targeting any longer once all the females had become pregnant.

I spent some hours trying to debug this before I released it, and I suspected something about the instance_change() method, which I used to change a female creature to a pregnant female, was to blame, but when I tried running a few tests to see what was going on in the code, it was apparent that the pregnant females were truly turning back into normal females after birthing, and also that the male’s re-targeting clock was resetting, and that they should have been seeing these females as available but for some reason they just weren’t.

It wasn’t crucial to the Genes demo, since the female homing worked well enough to get the breeding cycle going, so I gave up and posted it as it was. Then, I updated GameMaker Studio on Saturday to 1.1.929, and re-ran the game and all of a sudden the males are exhibiting the correct behavior now.

I started reading through the changelog to see what might have fixed it, and noticed something else that was enticing to me: Blend modes have been added to WebGL!

I haven’t touched the project files for Karyote in since sometime late in September, when I finished working on the post-Ludum Dare compo enhancements for it. My great disappointment with the HTML5 build of Karyote was that the pretty color blends that I’d come up with for the Windows build weren’t able to be rendered.

This had really soured me on building HTML5 games. But now I could see if it would be worth while to release a new build.

I tried opening up the project to rebuild it, and GameMaker said it needed to do something to the files in order to continue, and when it did, the project was corrupted, and all my project assets were missing. :-(

Fortunately, I have backups.

I restored the project folder from a backup and tried opening it again, and this time it worked. That is, it didn’t corrupt the project this time, at least.

But when I ran the game, a number of things were still off. In the Windows build, for some reason, the player’s sprite isn’t drawn correctly. The script that composites the player’s sprite no longer correctly centers everything, so now the body is off-center from the tail and the particle effects. And the HTML5 build no longer renders enemies at all for some reason. You just start out in an empty universe with nothing every appearing apart from the player.

Worse, the player sprite seems to be drawn correctly in the HTML5 build. So, it appears that the runner is not behaving consistently, depending on the build target. Which means that despite promising to allow you to develop projects that you can build to whatever platform, you (still) really can’t, because the behavior will not be identical across all platforms. I can only hope that this inconsistency will be rectified soon. It really sucks to have a tool that advertises itself as giving you the capability to easily develop for multiple platforms with a single project, and not deliver on that.

I’m sure with a little investigation and a bit of time, I might be able to fix these issues. But as a developer it sucks to have to sink my time into tasks like this, rather than doing new development.

This is something I’ll need to look into further, but I have to say that it is dismaying not to have confidence in Game Maker updates. If an update can ruin a project like this, it makes me very nervous about upgrading. Any project that I’ve put serious amounts of work into, I don’t want to introduce bugs into because I updated the development environment. Of course, I also don’t want to be stuck on an old version of my development tools, either.

I don’t know what techniques programmers use to protect their project code from changes to the underlying framework or environment. I imagine a unit test suite would help, but it doesn’t seem feasible for GameMaker projects.

Apart from that, I am not sure what else professional developers who work in GameMaker do. If you have any suggestions, I would love to hear them.

The Space Invaders: In Search of Lost Time

I just watched The Space Invaders: In Search of Lost Time, a documentary about the golden age of video games, and the stories of a few collectors of arcade games who are keeping them alive in basements and garages and museums around the country.

A heavily nostalgic look at the games, people telling their stories and what the games and the arcade experience meant to them. It wasn’t as heavy on history, research, and data as I would have liked, and being an enthusiast who lived through this period I didn’t feel like I really learned anything, but I feel qualified to say that the film is accurate in its treament of what it covers, and it is quite enjoyable to watch if you love the the golden age of arcade videogaming, or if you want to learn about that period.

The film did focus mainly on gamers who grew up in the late 70’s/early 80’s, and did not seem to include any interviews with people from the industry — designers, programmers, company presidents, or anything (although, a number of the collectors they interviewed do work in the computer technology field in some capacity). So it’s very much a gamer/fan oriented story, and not an insider story. But you’ll come away from it with a good feel for what the games meant to the generation who came of age during their heyday, and a lot of cabinet envy, if nothing else, and perhaps a desire for more wall outlets in your basement.

Strangely, the actual game Space Invaders seems to have been largely ignored by the collectors who shared their stories. For serving as the inspiration for the film’s title, it’s a bit odd that they didn’t spend a little more time talking about the game somewhere in there.

It’s available as an Amazon Instant Video, and if you watch it through the link below, I’ll get a little compensation through their affiliate program.

The Space Invaders: In Search of Lost Time

Genes

I’ve created a demo for a genetics mechanic.

This is not a playable game, as it isn’t interactive. It’s just a demo of a breeding mechanic.

To explain what’s going on a bit: (more…)