XBox One: Why REAL ownership matters, and will always matter.

On ArsTechnica, today, I read the following in defense of XBox One:

“This is a big change, consumers don’t always love change, and there’s a lot of education we have to provide to make sure that people understand.”

…a lot of the way people have responded to Microsoft’s moves was “kind of as we expected.” But the implication … was that this temporary confusion and discomfort among the audience would be worth it as gamers and consumers adjust to a console world without game discs.

“We’re trying to do something pretty big in terms of moving the industry forward for console gaming into the digital world. We believe the digital world is the future, and we believe digital is better.”

[Microsoft] made a comparison to the world of home movie viewing, where inconvenient trips to Blockbuster Video have been replaced with Netflix streaming on practically any device instantly. On Xbox One, having all games exist as cloud-connected downloads enables new features like being able to access your entire library at a friend’s house with a single login, or loaning games to up to ten “family members” digitally and remotely.

Immediately, I want to point out that Netflix (and Hulu) didn’t replace owning a copy — my copy — of a movie. They replaced movie rental and scheduled broadcast television — with something better and that eliminated inconveniences.

With Netflix and Hulu, you don’t have to program a DVR, or go to a store, or deal with rental returns and late fees. And assuming you only want to watch a thing once or twice, and don’t care to own a copy of it for all time, it’s great.

But online streaming on-demand services cannot replace certain aspects of owning a copy. And those things are very important. Users of these services know already that what is available today may not be available tomorrow. If the copyright owner decides to stop licensing the programming through the service, it will not be available any longer on the service. But a physical copy that you own can always be played, whenever you want to, as long as you own it. So if you want to guarantee availability of something forever, you can only do so if you own your copy.

And the copy you own will remain the edition you bought forever — no 1984-style “memory hole” for the old edition when the producers decide to release a new cut as the canonical version. No forced upgrades pushed over the network, eliminating or changing some scene that some group found objectionable for some reason, and managed to successfully pressure the studio into changing.

Video productions are re-cut and re-edited all the time, and for the most part people don’t notice it, or care. But sometimes the changes can drastically change the meaning. In the 1990’s, singer Sinead O’Connor once made an appearance on Saturday Night Live,  during which she unleashed a storm of controversy by tearing up a photo of Pope John Paul II on live television. NBC and SNL immediately distanced themselves from the incident and claimed to have had nothing to do with it, apologized for the offense it may have caused Catholic viewers, and claimed that it was something that O’Connor did on her own without informing the producers of her plans. This act of protest was never rebroadcast, and to my knowledge cannot be seen in any format today. Today, apart from viewers memories of the incident, it may as well not have happened. Unless someone with a VCR happened to tape that episode and kept it, as I’m sure many may have done, it would be lost forever, imprisoned in NBC’s video archive, if it exists at all. O’Connor’s act was an act of political speech, and whether you agree with her message or not, she had a right to say what she wanted, in the way she wanted. Of course, NBC and SNL own the rights to the video of the event, and have the right to not to make it available if they want, or edit it in whatever way they choose. But it was also broadcast to millions of homes over the public airwaves, and those who witnessed it own their memories of the event. And, for those who have have their own copy, and because you can own and control your own copy, NBC is not able to suppress it completely, or to compel holders of copies to surrender or destroy them. If need be, it could be proved that the incident happened, and, although they haven’t gone so far as to deny that the incident never took place, they certainly don’t like to bring it up, and if NBC wanted to pretend that it never happened, people can contradict the official histories, not just with memories and eyewitness testimony, but with evidence. Owning your own copy can help save The Truth from the memory hole. It gives you the power to own a little bit of the The Truth, outside of your own skull.

If you’re not a political person, you’re probably thinking “Whoa, you’ve gone off the deep end. This is just entertainment we’re talking about. Movies, TV, and videogames. We’re not talking about the news, or matters of public record. Surely this isn’t important stuff, get a grip.” But games do get censored, or pulled from the marketplace, and this can effect people who already own them, if they give up control of the copy that they purchased to DRM. Moreover, wherever DRM technologies make inroads, it tends to result in their becoming more accepted and likely to be used elsewhere. If we accept DRM for television, movies, and games, the technologies are then already in place, and may be used by hard news and official government content providers. Even if they were only used for entertainment, this is our culture — do we really want it to be completely controlled by corporate copyright holders?

Microsoft’s XBox One distribution offers to replace ownership of a physical copy with something worse. It might beat rentals, but it sucks compared to buying. It’s not the digital distribution and decoupling from physical media, it’s the DRM and the licensing vs. owning a copy.

There are pros and cons to decoupling software from physical media, but on the whole I am fine with owning my copy of a computer file, vs. owning a disc or ROM cartridge that came in a box. But de-coupling need not be accompanied by artificial limitations of use imposed by DRM and the need to authenticate a license to a copyrighted work. A license-to-access model is inferior to a model of owning a copy.

Learning from history

I have, in my personal game collection, consoles from Atari, Mattel, Coleco, Nintendo, Sega, Sony, and Microsoft. The oldest of these systems were built in the 1970’s. They are still fully playable, barring hardware failure.

Even back then, there were very early attempts at online play and distribution of games. They were ahead of their time, but from the earliest days the game industry tried to figure out ways to get people to subscribe to a service that would allow them to sell games directly to customers, replacing traditional retail distribution with digital download over a modem connection.

These services are long gone. Any games that were distributed exclusively via these means are exceedingly rare. If they exist at all, it’s only because someone who downloaded the game never erased it from their media (typically an audio cassette tape, or possibly a floppy disk), and because the game didn’t depend on the online service in order to run. This last bit is absolutely crucial. If these games could not be played if they depended on the continued existence of servers which were closed down by the vendor when they were no longer profitable, these games could not be played today.

“Well, who cares? Who cares about these old games?”

It turns out, a lot of people. Everyone who owns them, and would like to continue to be able to enjoy them. Anyone who wants to introduce their favorite games from their childhood to youngsters today. Collectors. Historians. Game designers.

“But popular games get re-packaged and re-sold with each generation!”

I suppose they do. Nothing wrong with that. It’s a good thing.

But what if your favorite game isn’t one of the few lucky popular games that gets chosen to live on? What if you want to play the games on the original hardware? What if you don’t want to have to re-buy games that you already own in order to play them again on your current-generation console?

“But you can’t go out to a retail outlet and buy a traditionally distributed game that isn’t being made anymore. So why should it matter that you can’t buy a digitally distributed game anymore?”

Because, the games that were sold while it was available are still available. They are tangible, transferrable, resellable goods, and as long as they remain physically intact, and someone in the world wants to enjoy them, there is a market for them. It might be garage sales and flea markets and eBay, but it’s possible to find and buy a videogame that was made in 1977. It might not be easy in some cases, but it’s possible, and it’s no more complicated than finding the game, plugging it in, and playing it.

I guess it may be starting to become more difficult now that old-fashioned NTSC CRT TVs are disappearing, along with their antequated analog signal input jacks, but the point is that there’s no need to negotiate the right to play the game with the copyright holder. If you have it, you can play it.

Digitally downloaded games could be just as transferrable — far more transferrable, in fact. Files are easy to share and copy. Compared to making a copy of a printed circuit board and ROM chip, it’s dead simple. The future should be making it easier to do things, not harder.

But if games have dependencies on network-based resources that the player does not control in order to function, this all changes. It seems likely that game companies will sell the client, but not the server. But when the company no longer sees value in maintaining the servers, and decides to take them down rather than sell them to someone who’d become a competitor, or release the source code so that the player community can host their own servers, that will be the end of that game.

The level of dependency may vary considerably, from simple license/subscription validation, to enabling multiplayer features, updates, and downloadable content, to online leaderboard and achievement data. From the gamer’s perspective, the possibilities are rich, but they all disappear when the servers go offline. Nothing can compel a company to release the server software as a product or as a freebie once they decide to end-of-life an obsolete title, but without the server side, the clients are potentially useless, and at the very least are diminished.

Furthermore, servers can be used to killswitch the client, or to force unwanted upgrades. What if you liked the 1.0 version of your favorite game, but hated what they did with 1.1? If you can’t roll back, if you can’t decline an upgrade, there’s not much you can do. Game companies that serve the player’s interests well should design their upgrade systems to allow the player to play the game in an earlier version mode if they desire. And server code should be made available (whether for free or as a product) once the parent company decides it’s time to shut things down, so that players can continue to have full access to the complete experience indefinitely, as long as there’s a community who wants it. Of course, security concerns will mean that any code running on a network node will need to be patched, so it would be best if the source code is available to enable patches to be made.

Obviously, many of those requirements for libre software are too much for most game companies in their current thinking. “Allow our obsolete products to continue to be sold so that we have to continue to compete with ourselves? Release our server source code, are they mad?” While it’s difficult to imagine many companies doing anything like this in today’s market, these are the sort of things that gamers need as consumers, and the culture needs from the vantage point of the historian. Some companies, notably Id Software, have opensourced their older game engines, so it’s not unthinkable that the same could also happen with server technologies, though there are certainly many obstacles, such as software patents, and the fact that many game design studios license third party engines.

Still, even if it’s a highly unlikely ideal, it’s important as a point of comparison, to know just how much you “own” the things that you “buy”, and a target for the consumer to strive to push the market toward. Consumers do have power when they act collectively. It is only for us to realize this, and seize the power that is within our grasp.

Radar demo now in HTML5

I got the Radar demo working in HTML5, finally. In order to do it, absent a better debugging methodology, I created a new project and meticulously re-built the demo line by line. I’m still not entirely sure why this works while the first one doesn’t — I still need to look at it more closely.

The resulting project isn’t feature-complete yet, but the only missing feature is color coding for IFF, and isn’t where the problem was. Once I’ve finished adding that feature, I’ll update the source download.

For now, here’s an in browser preview of what the radar demo looks like in action:

XBOX One: No thanks

Microsoft’s recent announcement of their next-generation console, the XBOX One, has raised a lot of ire in the gamer community.

The two major issues are “digital rights management” and privacy.

Privacy

The Kinect is a motion sensing control interface that was introduced late in the life cycle of the XBox 360 product line, and has been generally accepted by users as a novel method of control by motion, similar in certain respects to the Nintendo Wii’s Wiimote. With XBox One, the Kinect interface is mandatory, and always on. The Kinect isn’t just a motion sensor. Unlike the Wiimote, it uses a camera and microphone to, essentially, bug your living room. This allows the XBox One to respond to voice commands, like the USS Enterprise‘s shipboard computer on Star Trek, and do other things that are pretty neat. But it also allows Microsoft to watch you live at all hours and in all states of undress, all day every day, like the two-way televisions of George Orwell’s 1984. It turns the home into a zone of no expectation of privacy.

Microsoft’s response to these concerns has been weak. They claim that you can control what the XBox is allowed to do, but can you really? It’s always on, always connected to the internet, and running Microsoft’s operating system — how hard is it for someone to gain unauthorized access to the XBox and use it to spy on you? How easy is it to imagine Microsoft rolling over for government requests to use this technology to monitor citizens suspected of “un-American” activities? How often in the past have we seen large technology companies like Yahoo! and Facebook decide to re-set user-configured preferences to defaults that they prefer, and quietly allow the savvy user who pays attention to re-opt out, again and again, until they wear down and accept the service provider’s preferences? It’s a virtual certainty that Microsoft’s click-through EULA and ToS will grant them the ability to do whatever they want with the information they gather through the device, and hold them not harmless and not liable for any damages caused or enabled by the device. And they’ll turn around and claim that they do nothing with the information that you do not authorize, as though you have control. In reality, the only control that you have at all is whether to buy the device or not.

We are already living in an age where the general public has more or less accepted a total erosion of the expectation of privacy. Is this a step too far? For anyone who thinks about it even for a moment, it would seem to be. Yet, almost no one seems to behave as though they think about it at all. We use the services of Google, Facebook, Twitter, and so on, sharing very personal information about ourselves, often in full public view, and certainly in full view of the service provider, their partners, and anyone who eventually buys them out. We willingly pay Verizon, AT&T, and others hundreds of dollars a year for the convenience of carrying tracking devices that monitor our locations, what we read, who we know, what we buy. We send emails un-encrypted, containing sensitive personal information that is easily intercepted and re-transmitted to anyone in the world. The NSA sucks all of it up into giant datacenters, and apart from a few headlines, barely any notice is paid. And for the most part, nothing happens, and we don’t seem to care.

DRM

In a nutshell, DRM, as implemented for XBox One, means that you do not own the game you thought you bought. You don’t even own the copy — the physical media you own, but all the physical media is a transport vessel. The data on the media is intellectual property, owned by the copyright holder, who controls how it can be used. You own the “license” to play the publisher’s intellectual property — under their terms, which they can change at any time, for as long as they continue to exist, or decide to continue allowing their intellectual property to be made available.

You do not retain the ability to transfer your “rights” to someone else, either as a gift, loan, or re-sale — unless the publisher decides to allow it, and then only through some approved process wholly controlled by them.

It is an extremely raw deal for the consumer, and something which no one should allow to stand.

Of course, ridiculous, draconian licensing terms are nothing new to commercial software. It’s been around for decades, from the earliest days of Microsoft and the personal computer. It’s just that, for most of this time, it hasn’t mattered to consumers, because there was no way to enforce many of the terms stipulated in EULAs, and circumvention was trivial.

It’s been all over the internet by now, with virtually every source that I’ve been able to find coming out against Microsoft’s policies. Here are just a few links:

  1. http://news.xbox.com/2013/06/main
  2. http://www.polygon.com/2013/6/7/4406170/xbox-one-internet-trade-policy
  3. http://www.nowgamer.com/features/1955108/xbox_one_its_for_publishers_not_for_you.html
  4. http://www.giantbomb.com/articles/major-publishers-silent-on-xbox-one-used-game-poli/1100-4659/
  5. http://www.bbc.co.uk/news/technology-22812743
  6. http://www.youtube.com/watch?v=9APmJHu8DNs
  7. http://www.youtube.com/watch?v=1StPJgWkN-U
  8. http://techland.time.com/2013/06/07/microsofts-xbox-one-used-games-policies-are-clear-as-mud/
  9. https://blogs.wsj.com/corporate-intelligence/2013/06/07/microsofts-xbox-one-how-things-have-changed/
  10. http://www.neogaf.com/forum/showthread.php?t=580169

Final Thoughts

All of this comes at a time when the game industry is struggling to figure out a business model that works. The internet, digital distribution, piracy, in-game purchase, free-to-play, freemium, lowered barriers to entry enabling indie developers and hobbyist developers, and other rapid changes have made it very difficult for many companies to remain profitable. This response by Microsoft is the most heavy-handed, top-down approach that we’ve seen so far, and cannot be the future of videogaming entertainment.

It is a future with no history — when the publishers DRM servers are shut off, an entire generation of gaming will be lost forever, never to be seen again. And so it must be a future with no future, as well. An informed consumer who understands the issues at play and what’s at stake, could only reject a product offered on these terms. It is up to gamers to educate the general public to stand firm against this.

There are alternatives. The upstart Ouya console is perhaps the best of them in the current generation.

Radar demo update

I’ve made a number of really nice enhancements to my earlier Radar demo.

The improvements:

  • The original demo used collision_line() to detect when the radar sweep collided with the radar blips to refresh them. This meant that the collision detection could skip over smaller objects at great distances from the antenna, since the space between steps is not scanned. The new one uses an approach based on the angle difference between the mappable object and the sweep’s current and previous positions, and is therefore much more accurate.
  • The original radar used a classic looking monochrome green radar screen. The new one implements IFF (Identify Friend or Foe) color coding. This system is flexible in that it allows you to change the value of the color variables used in the color key, or even a unique color if desired. oMappable child objects must have two instance variables, blip_alpha and blip_color. The demo only uses color for IFF, but for colorblind players it would be helpful to modify the routine to use shape as well as color to identify the blips.
  • I’m particularly proud of how understandable and well-commented the code is, so if you’re a developer and want to modify it for your own needs, it should be quite easy to do so.

I still can’t get it to run in HTML5 builds, so a screen shot will have to do.

Radar Demo by csanyk

Download radar_example.gmz

GML draw_text_rtf() script enables drawing of pseudo-rich text strings

When I was working on my recent blog post on string handling and text drawing in GML, I had the idea for a function that would draw formatted text. (You can read a paragraph in that post where I complained about how difficult this is to do using the built-in GML draw_text() functions.)

I posted a feature request to the official GameMaker bug tracking site (which recently closed its submission system and now works differently, by the way). And this spurred a discussion with some of the other users on the bugtracker. A user named Miah_84 came up with a script that very nearly did everything I wanted. I made a few modifications and cleaned up the code, and present it below.

The downside of this script is that it is very slow, as it makes numerous calls to the draw_text() function, which is itself very slow, and iterates over the raw rtf string several times in order to parse it. Running the demo project on my 2.0GHz Core 2 Duo laptop with discrete graphics, it only runs at around 200fps in debug mode. Comment out the call to the draw_text_rtf function, and the frame rate jumps to about 1100fps. The more formatting in the string, the slower the function will draw.

Still, combined with surfaces, this can be an extremely useful function for displaying text to the screen, in ways that was not possible previously using native GML functions.

Discussion thread on this script at http://www.gmlscripts.com/forums/viewtopic.php?pid=3358#p3358 — I expect that in the near future this will end up as an addition on GMLScripts.com, as well.

Download draw_text_rtf.gml.zip

Demo Project RTFDemo.gmz

Latest GameMaker Studio update improves GML arrays implementation

I’m quite happy about this. I’d like even more improvements to the array and string functions to come in time, but this is long overdue. Arrays in GameMaker have been clunky but serviceable forever, and this just made them a good bit easier and more useful.

From the GM:Studio 1.1.1008 release notes:

  • Arrays can now be passed/returned from scripts.
    • NOT pass by reference
    • If array values are set, then the array is copied
  • Arrays are now native on HTML5, making them significantly quicker.
  • Arrays can now be freed!
    • To free an array, simply set the variable to 0 (if MyVar was an array, MyVar=0 would free it)
  • 3 new array functions added
    • is_array()
    • array_length_1d() gives the size of the 1st dimension
    • array_length_2d() gives the size of the 2nd dimension. Arrays are ragged, not grids. so the each element of the 2nd dimension varys in size

GameMaker Studio marks 1st anniversary

YoYoGames is celebrating the release of GameMaker Studio, one year ago today. With all the updates and improvements that have been made to the product since the 1.0 release, it’s surprising that it’s only been a year since it came out of beta.

I myself have not been a GameMaker user for very long, either. I began using it in September 2010, with version 8.0. In that time, I have found it to be the easiest to learn development tools that I have ever used. It has enabled me to make playable games with features that I would not have thought myself capable of building, and then rewarded me as I gained confidence that I could become a better programmer than I had previously dared to dream. And this has allowed me to pursue a long-dormant dream that I’ve had since I was six years old and experienced my first videogame: to design and build fun, playable games. As a result, life is better than ever. For this I have been very grateful.

Happy birthday, GameMaker Studio!

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.