Category: development

Vote for GameMaker Studio 2 on Linux

I just created a Twitter poll to assess the interest in a Linux port of the GameMaker Studio 2 IDE.

One of my biggest wish list items for GameMaker Studio is to have the IDE on Linux, so I can stop being a Windows user. I’m on Windows 7 currently, and Microsoft will not support this version forever. Already they have stopped selling new computers with Windows 7. After the way Microsoft treated Windows users who were not interested in upgrading to Windows 10, using unethical, underhanded, and very likely illegal tactics to try to force Windows users to upgrade, I am not interested in ever purchasing another product from Microsoft, and my preferred platform to migrate to would be a popular Linux distro such as Ubuntu or Mint. GameMaker is the only Windows software that is holding me back.

I’ve asked on the GMC Forums if YYG intend to release a Linux port for GMS2, and currently there’s no plans to do so, but they are open to considering it if they see sufficient interest.

In 2014, then-YoYoGames CEO Sandy Duncan had teased us with the possibility that GMS2 would bring an IDE that ran on Windows, Mac OS X, and Linux. Obviously things can change, and a lot of things have changed with YoYoGames since then. Whether or not we see a native Linux IDE for GMS2, it’s still my #1 wish list item for GameMaker.

GameMaker Studio 2 announced

Today YoYoGames released an announcement with some details of the impending release of GameMaker Studio 2.

The biggest news in today’s release:

  1. It appears that they are not moving to a subscription model at this time. YoYo will be selling permanent licenses on a per-module basis for $99 each. There will be upgrade discounts for users who hold a paid license for GM:S1.x, for a limited time. This is very good news for casual users of GameMaker, who would be turned off by a subscription for something they don’t use all the time.
  2. At launch, the IDE will only be available for Windows, but a Mac OS X version of the IDE will go into beta shortly after launch.
  3. No word on a Linux IDE. This was something I had very much hoped would be introduced with GMS2, but at this point at least it seems like there is no plan for it. I really hope that it does happen, so I can get off of Windows.
  4. Confirmed that this is the total re-write that we’ve been waiting on for years, which has been known about for some time. Still not a lot of details on what improvements have been made with the IDE, or whether the GML programming language has changed dramatically. Ideally we’d all like old projects to import into GMS2 and just work, and we still don’t yet know whether they will. There are some significant changes to GML that will impact compatibility with old projects. No doubt this will generate a lot of complaints, but we’d also like GML to add new features and modernize so that it will be more powerful, more easy to use, less prone to bad programming, etc. So this is a balance/trade-off kind of thing. There is a porting guide to help projects that were created in 1.4 migrate to 2.0.
  5. The public Beta for GMS2 begins today, but they are limiting the number of users who have access to the beta for now. At the moment there are no slots available, but YoYo will be adding more slots gradually in the near future.

Additional information

More specific details about changes in GMS2 are available at the YoYoGames Help site.

They’ve brought back a product roadmap! I’m extremely happy to see this.

Deeper dive

Over the last few years, I had been an active contributor on the Suggestion Box subforum in the GameMaker Community Forums. Many of my suggestions were denied, because YYG interpreted the forum as being for suggestions for the 1.x line only.

This wasn’t explicitly mentioned in the forum rules, but came out after numerous ideas that I’d suggested had all been shot down with some mention of “Not feasible in 1.x” and I kept replying, “OK but I don’t care what version it gets delivered in, I still want a GM:S that works this way someday.”

It’s nice to see that one of my suggestions, to have an inheritance system for rooms, has been adopted. Reading the article on this new feature, it sounds a bit more complex than I would have expected, but it is powerful and more fine-tunable.

It should be fun to discover what other ideas from my wish list may have been made a reality in this new version.

GameMaker Studio 2 nearing release

In the last couple of days, YoYoGames have released some teasers that seem to be signaling the immanent release of GameMaker: Studio 2.0. This long-awaited release will overhaul the GM:S GUI, which YoYo have been rewriting in modern C++, and usher in a new era for GameMaker. Beyond that, little is known, as YoYo have been pretty secretive about their plans for the future of GameMaker since being acquired by PlayTech in 2015.

My greatest hope is that GM:S2 will have builds for Mac OS X and Linux. Out of all the software I use today, GameMaker is the last product that runs only on Windows, and I am eager to move to Linux full-time.

It remains to be seen what the release will bring.

Recent purchases of GameMaker who picked it up through the Humble Bundle have been speculating about what GM:S2 will cost. Obviously, a major release isn’t going to be free. It’s typical practice for software companies to sell upgrades to existing users at a substantial discount, so I’m expecting no less.

If YYG do extend discounted upgrade pricing to Humble buyers, most of whom paid around $15, they’ll still be getting an incredible value.

iMprOVE_WRAP 2.0 released

My GameMaker extension iMprOVE_WRAP has been updated with a new release to 2.0.0.

iMproVE_WRAP is an extension for GameMaker: Studio that provides a number of new functions that improve upon the built-in GML function move_wrap().

iMproVE_WRAP is an extension for GameMaker: Studio that provides a number of new functions that improve upon the built-in GML function move_wrap(). It allows you to define the range in the room where the wrap takes place, and draw the instance on both edges of the wrap, as well as detect collisions on both edges of the wrap.

Version 2.0.0 adds two new functions:

  • draw_sprite_wrap()
  • draw_sprite_ext_wrap()

And makes improvements to the existing functions as follows:

  • boundary wrap drawing occurs at the corners of the wrap range (8 phantom drawings rather than 4) when do_wrap_h and do_wrap_v are both true.
  • the collision functions iw_collision_wrap() and iw_collision_wrap_map() incorporate do_wrap_h and do_wrap_v parameters, and only perform collision checks where they are needed. The functions still return all potential collision variables so that there is never an undefined value, even where collisions are not checked. (Unchecked collision locations return noone.)

You can get it at the YoYoGames Marketplace or Itch.io.

Full documentation.

GameMaker Humble Bundle – super cheap and source code too!

GameMaker Humble Bundle pay what you want, but for just $15 you can get licenses for GameMaker: Studio Professional and the ability to create games for HTML5, Android, iOS, and Windows UWP, which together normally cost several hundred dollars. The total value of the entire bundle is $1885, making this one of the best value bundles I’ve seen in the history of the Humble store.

Additionally, you can also get a number of commercially released indie games that were built in GameMaker, and for a few of those games, you even get the source code. It’s very exciting to be able to look at source code written by professionals to see how it’s done. Titles offering their source code include: Extreme Burger Defense, Freeway Mutant, Shep Hard, Angry Chicken, Galactic Missile Defense, Uncanny Valley, Ink, 10 Second Ninja X, Cook, Serve, Delicious!, Flop Rocket, Solstice, and Home.

The sheer cheapness of this giveaway leads me to wonder whether the release of GM:S 2.0 may be immanent. Time will tell. In the mean time, this is a spectacular value bundle and well worth buying for the project source alone.

GameMaker Marketplace new checkout system now allows direct downloads!

Yesterday, 9/7, I noticed a big spike in downloads of my GameMaker Marketplace assets. I also happened to notice when looking around on the Marketplace that they’ve changed the checkout so that you can download the .gmex files directly through your web browser, bypassing the My Library interface in the IDE.

As I’ve remarked several times in the past year, My Library is crippled by terrible performance when the user’s purchase manifest exceeds some number that is far too low. Allowing purchases to be downloaded directly through the browser makes a lot of sense, and is probably the simplest solution to the performance issues, which still plague GM:S as of 1.4.1760.

It remains to be seen whether this spike in downloads will be sustained as the new normal, or represents pent-up demand for users who were reluctant to buy due to the poor performance of My Library. Despite the seeming smallness of this change, I’m really excited that YoYoGames have made it, as it alleviates a significant pain point that I’ve been complaining about for well over a year, and means that I’ll likely be making more use of extensions in my projects.

Graph showing sales spike on 9/7/16. Could this be due to the change in delivery method?

On 9/7, 18 downloads. The other spike earlier in August was due to my Ludum Dare 36 sale, when I put my paid assets on sale for $FREE

Update: 9/8 saw another 18 download day.

Tutorial: GameMaker Object with multiple collision zones

GM Version: GameMaker:Studio 1.4 (concept should work in earlier versions)
Target Platform: ALL
Example Download: https://csanyk.com/cs/releases/games/LD48-36_AncientTechnologies/LD48_36_Ancient_Technologies_csanyk.gmz
Links: http://ludumdare.com/compo/ludum-dare-36/?action=preview&uid=10473

Summary:

How to make an object that handles multiple collision zones by using multiple sub-objects

Tutorial:

I used this technique in my recent Ludum Dare game, Ancient Technologies. The project has a TON of extraneous code in it, some of which is pretty messy, so I’ll replace the download link with a cleaner example project of just this technique in coming days.

If you look at the Atari 2600 console in this game, it is actually multiple objects, made to look like a single object. This enables each switch to have its own collision detection and mouse events.

I accomplished this with a few simple techniques that work really well:

The console itself is the main object. Then there are 6 objects for the 6 switches on the console.

I then took the image I wanted to use for the sprite, and cut out all the different clickable regions, putting each into its own subimage by itself. Then once all the subimages were created, I removed each subimage into its own sprite, and set the collision mask to cover just the pixels in the image

Atari 2600 clickmap sheet

As you can see, this approach results in a lot of “wasted” space in the sprite sheet in the form of transparent pixels, but if you’re concerned about this, you could always achieve the same effect by using sprite origin and sprite offset to position the images without all the whitespace in the sprite sheet. I skipped using sprite origin because I didn’t feel like bothering with counting pixels and setting each sprite origin differently. That would have been tedious, and if I had ever needed to change the sprites, could have thrown everything off and required extensive rework to recalculate again. If your sprites are tiny, it probably doesn’t matter too much, but if they’re quite large, then you should probably use sprite origin/offset.

(Note: With the small pieces, you’d need to use origin numbers that are larger than the dimensions of the sprite itself, or possibly negative values for the origin. You’d also need to carefully calculate the distance to set the origin so that the images all line up precisely. The goal is to make all the images align when each instance’s x and y are identical. This makes them easy to move around together as a group, without having to deal with offsets and so on. To make everything align easy, I created sprites that have the same height and width, so that getting them to align takes no extra effort or calculation at all.)

Next, use the “main” object to generate the collision zone objects, in the create event:

Note the example code below isn’t exactly the code in my project, but is cleaned up a bit for easier comprehension.

///oConsole Create Event:
power_switch = instance_create(x, y, oPowerSwitch);
tv_type_switch = instance_create(x, y, oTVTypeSwitch);
left_difficulty_switch = instance_create(x, y, oLeftDifficultySwitch);
right_difficulty_switch = instance_create(x, y, oRightDifficultySwitch);
select_switch = instance_create(x, y, oSelectSwitch);
reset_switch = instance_create(x, y, oResetSwitch);

Since these objects all use sprites that are the same size, they all line up together when their x,y position is the same. Now you have an easy way to place just the main object and have it create all of its collision zone objects, perfectly aligned.

If the main object needs to be able to move, you just need to update the x,y of all the objects whenever you need to.

Another great thing is that each of these instances can have its own animation which is completely separate from the rest of the collection of objects. This means you can do really sophisticated animation rigging.

Also, you can access the instance variables of the collision instances by using the main instance, like so:

oConsole.power_switch.position = UP;

is (essentially) equivalent to:

oPowerSwitch.position = UP;

This allows you to use the collision zone instances’ instance variables like you would use properties of a helper class in another language, which may make accessing these variables easier if you’re used to other programming languages.

As well, if each of these switch instances were of the same object, using the id returned by instance_create() would allow you to differentiate between them. This could be useful for, say, a battleship with multiple turrets that are all of the same object type.

Finally, you’ll want to be mindful that if you destroy the main object, you’ll likely want to destroy all the sub-objects. Perhaps not — maybe you’re doing a spaceship with an escape pod or a rocket with multiple stages that break away. But in that case you’ll wan to be sure that once the main object is gone, you are handling whatever remains somehow.

Managing complexity when implementing complex conditionals

Programming is in large part about managing complexity and imposing structure onto a problem domain in order to make it simple (simple enough for a machine to be able to do the solution, as well as simple enough for human programmers to be able to build it).

Something struck me about a technique that I used when I was developing my game last weekend.

The code that handles the setup of the simulated atari 2600 console is full of conditionals like this:

if PowerPlug.is_plugged_in && (console.switch_power.position == POWER_ON) 
 && (TV.switch_power.position == POWER_ON) && Cartridge.is_plugged_in && 
 Joystick.is_plugged_in 
{
 //simulate the game 
}

So one thing that I had to deal with as I was building this was all the preliminary stuff’ you know, to create all the objects that needed to be checked in the conditional statement above. Rather than do that, all at once, and have a lot of conditions that could have bugs in them, any one of which could make the thing not work, and be hard to figure out since multiple bugs could end up canceling each other out, or mask one another in some way, I opted to simplify things at first:

if true
{
 //simulate the game
}

The advantage here is obvious. It’s simple, and you KNOW that conditional is always going to evaluate to true! So you can get right into working out the code inside the branch, without worrying for now about the conditional logic that would cause it to execute.

Once that was working, I added in stuff:

if PowerPlug.is_plugged_in
{
 //simulate the game
}
else
{
 if PowerPlug.was_plugged_in_previously
 {
 kill_game();
 }
}

Then from there it became easier to elaborate on the conditional:

if PowerPlug.is_plugged_in
{
 if Console.switch_power.position == POWER_ON
 {
 //simulate the game
 }
}
else
{
 if PowerPlug.was_plugged_in_previously
 {
 kill_game();
 }
}

//etc.

(Note, the above isn’t the exact code from my project, which is a bit messy at the moment as I have some refactoring to do, but it illustrates the point.)

I found that by coding it in this way, I could iterate and test each little piece of the logic easily, and make sure it was working before trying the next piece.

I found that doing it this way made it much, much easier to handle the complex nested if business, and as well I found it easier to know which branches of the complex conditional tree the next bit of code needed to belong in.

Now that I did it this way, it seems obvious, nothing of great insight… but 6 years ago I would have tried to code the whole thing out, and then pulled my hair out swearing at myself when it didn’t work as expected, and I had to untangle all the logic to figure out wtf it wasn’t working.

Back then I would have thought that a really superior version of me who I aspired to be would be able to code out all the conditions in one go without making a mistake.

Today a really superior version of me knows better. Start simple, add elaboration through iteration.

This is a good lesson to hang onto. And to pass on.

Of course, there’s also often ways to avoid having to code conditionals at all, but that’s a topic for another post.

GameMaker EULA restricts developer creativity

[Editor’s Note: After a busy year or so of low posting frequency, during which I started but never completed many articles, I’ve been going through my old drafts, working to complete old articles that still hold relevance. So this is an old topic, though not out of date, which I started writing in May of 2015, and I don’t mean to stir up new debate over it, but it’s worth being aware of.]

YoYoGames has restrictions in the EULA for GameMaker which states in essence that users agree to allow YoYo the authority to determine whether a game produced by the user is in line with their moral standards, and the right to terminate your license if they wish should you produce something they deem objectionable, without explicitly spelling out what counts as objectionable.

An April 2015 discussion on the old GameMaker Community forums raised this issue, but is now hidden due to the closure of the Suggestion Box subforum, but still available through the Internet Archive’s Wayback machine.

To summarize the discussion, YYG don’t seem to be actively policing their policy, nor are they specific in explaining their standards for acceptable content in games. They seem to be treating the EULA clause as something they can invoke if they so choose, but not actively evaluating published games to ensure they don’t violate it. And currently they seem to be pretty lenient about what they deem acceptable — for example, they deem Hotline Miami to be clear of violating their standards. Accordingly, I don’t read YYG as bad actors here.

But this does give rise to what one would have to do in order to cross the line with respect to YoYo’s standards, and why have them in the first place. It seems the answer to the latter question is to allow YYG the contractual authority to nix a license more or less arbitrarily, in order to make clear that they do not have any relationship with a developer who they deem too offensive. Which is to say that if a game produced with GameMaker were developed and it generated negative publicity for YoYo, that’s probably ultimately what their standards boil down to.

YoYoGames motivation seems to be that they (understandably) do not wish to be associated in any way with a game that someone else develops, if that game is “deeply offensive” (whatever that means — it varies from person to person what offends them). Considering that many games these days address topics which many might find “controversial”, and thus may be offended by, it gives a developer pause. And even those games that are not exactly controversial routinely depict subject matter which upon a moment’s reflection make us wonder why they’re not considered offensive. A huge proportion of videogames depict violence in a casual, matter of fact, even joyous manner. But most games would be instantly get a Mature Audiences rating if they depicted nudity, even if the context isn’t sexual.

It’s tough to say what the guidelines are for producing a game that is free of these concerns, and YoYo weren’t very interested in stating their guidelines explicitly. “Use common sense” seems to be their question-begging non-answer. Common sense falls down in controversial cases precisely because they are controversial. There’s undoubtedly a whole classification of things that are offensive to marms and nuns but that teenage boys think is fine, but the only answer that matters in this case is, “is what’s considered offensive by YYG?” Debating “what is too offensive?” is an endless quagmire but “What does YYG consider too offensive?” is something that can have a start and an end to it, and is probably a succinct bulleted list, which people may be free to disagree with or not as they choose, but still helpless to change.

I surmise that there are things that are commonly topics addressed by the medium of videogames, such as violence and war and crime that are not included in the “truly offensive” category, but that a game could step over the line by being too explicit in its depictions of these things, or by appearing to advocate for doing these things in real life, or by appealing to the player’s “prurient interests” in such depictions. The “common sense” approach seems to be a way for YoYo to say, “We don’t want to say because it’d probably just give horrible people a to-do list, but if everyone could avoid things such as explicit torture, rape, and so on, that’d be great.”

Still, the fact that someone else can tell me what I can or can’t put into a game that I’ve designed, is inherently offensive to me. I think it unlikely that I’d produce something that would cause YoYo to take notice and strip me of my license, but the fact that they can, and that they think that it’s right for them to have such power, is offensive to me. To me, there is a boundary where their responsibility ends and my responsibility takes over, and I should be responsible for my creations; once the tool they’ve produced is in my hands I don’t need their sense of responsibility for their creations to encroach upon my creativity.

It’s tough to see why YoYoGames would be associated with a game that was developed by someone else, even if they happened to use GameMaker. One reason might be their logo is used as the default splash screen and application icon when a game is built with GameMaker. These are removable by the developer, but are often left as-is by amateur developers. But there, a simpler remedy would be to compel game developers to remove YYG logos from games that they do not wish to be associated with at their request. Or, if YYG wanted to, they could ban games that they deem unfit from being sold or otherwise distributed through their online store, while not taking away the developer’s liberty to release the game through other means, or to continue using GameMaker to develop other games.

YoYo declined to change the policy, taking a “take it or leave it” attitude, and then closed the forum topic to quash further discussion. It seems to be the YoYo forums general policy to kill topics when moderators deem that further discussion is “pointless” since they are firm about not changing their minds. Obviously that’s not the case, as there may be much to discuss whether or not YoYo change their minds, and getting YoYo to change their minds is not always the aim of discussing some topic on the forums. Really, it’s about stopping discussions that may lead to users expressing views deemed critical or negative to YoYoGames, which they (wrongly, in my opinion) feel is harmful or threatens their brand.

Which, since it’s their forum, that’s their prerogative, but I can’t say that I like or agree with the practice. And now that they’ve restricted access to that particular forum, the topic is no longer visible. And this is one of the reasons why I have my own website where I can exercise my right to free speech without censorship.