Diatris is a Tetris-like falling stack game by Rob van Saaze. Released earlier this year and developed in GameMaker Studio.
I had the good fortune of catching a work-in-progress screenshot tweet, and messaged Rob, and ended up being a playtester for his game.
I like the interesting twist he put on the classic Tetris. This game is really different from its inspiration. The shapes are different, the falling pieces slide down the slopes of the stack, and the angle factor really changes the way the game feels. It’s quite challenging, and fun.
The graphical style is clean and polished, but juicy, and it looks as great as it plays. Rob has a great eye for graphical design, and it shows in his work. The attention to detail in animation and motion is
I am most excited about lightweight objects and chained accessors, which will make it much easier to work with nested data structures.
Lightweight objects are more like what developers who are used to other languages think of as “objects”. In GameMaker, an “Object” had a number of built-in properties and behaviors, which enabled GameMaker Objects to be used in an intuitive way by users working with GameMaker’s engine. A “Lightweight object” is simply a named instance that can hold data, as defined by the user, without the overhead of GameMaker’s built-in properties and Event handlers. Before Lightweight Objects, developers had little choice but to create a traditional GameMaker Object, and make it invisible and use it to store whatever instance variables the game needed to store “somewhere”. This was suboptimal for performance, as these objects didn’t need to have x, y position, or a sprite, or collision mask, or most of the other features that are built-in by default for a traditional GameMaker object. With a lot of data-holder objects in the game, they could impose a enough unnecessary overhead that it could be detrimental to runtime performance.
If you’ve worked with GML’s data structures, and ever wanted to be able to store a List inside of a Map, well now you can a lot more easily, thanks to chained accessors. This enhancement to GML’s syntax makes it easier to reference a structure stored inside another structure. Previously, it was a pain to manage nested data structures, requiring convoluted syntax and multiple lines of code.
Other new features
GML will also receive Garbage Collection and an Exception handling system. I don’t know that I’ve ever actually needed either of these. I certainly haven’t missed them in my own GameMaker projects. But they are features of most object-oriented languages, and programmers who are used to having these features will appreciate being able to use them in GML now.
Overall, it’s very good to see the GML language adding these language features.
My latest asset for the GameMaker Marketplace is a Tetris demo. Fully-featured, and configurable, it requires only sound files to be added to complete the project.
It’s meticulously researched, beautifully coded, fully documented, and rigorously tested, and represents approximately 150 developer hours of work, for only $4.99. It’s playable as is, right out of the box. It’s easy to understand the code, easy to configure with simple changes to the code, and modding is encouraged.
YoYoGames released GameMaker Studio 1.4.9999 today, the last planned release for the 1.x branch. With GMS2 out for almost two yers, it’s time, right?
No. It’s really not.
When YYG released GameMaker Studio, they continued to support their old product, GameMaker 8, for about six years. Supporting a “professional” tool for only two years after a new version is released is not good enough. Businesses expect long-term support, plain and simple. No matter when they end-of-life GMS1, there will be complaints, but two years is far too soon.
Transitioning from GMS1 to GMS2 was supposed to be easy. Project conversion was a dream, it worked beautifully. Just import your GMS1 project into GMS2, and it would handle any obsolete code by generating conversion scripts, and for most projects, they worked without any further work needed. Import, compile, and it runs. Brilliant.
But the stability problems and project corruption problems that I’ve had with GMS2 make it too unreliable for everyday use. And for all the improvements introduced to the product, there are numerous usability issues with the new IDE, some minor, some major.
Looking back at GMS1.x, YoYoGames delivered a great, but not perfect, product, introduced many new features, and made the product worth the price hike. When I started using GM8, it cost just $20, later $35 for the full version, but there was a free edition also, which lacked certain features but was still useful for students and hobbyists. It was a no-brainer to pay for the full featured version, as cheap as it was.
GMS was much more expensive, starting at $200 for the basic Professional, but it delivered. YYG introduced some great new features. Building to HTML5, Mac OS X, Android, iOS, Linux, and other platforms. Box2D Physics, Shaders, language improvements, the Marketplace, and more. And they were delivered quickly. New major features arrived, regularly.
Then the PlayTech acquisition happened. YoYoGames CEO Sandy Duncan left. And I think that marked a major change in the way the product was managed and developed. Sandy Duncan had been talking about porting GameMaker to enable development on Linux as well as Mac OS X. With his departure, the Linux port was dropped. The Mac OS X port of GMS2 is currently in beta. The quality of the Windows version of GMS2 is sadly, still beta.
I’ve been using GameMaker since 2010, and it was exciting to see how quickly features and fixes were coming in 2012-15. Since then, it’s been slow, and what has been delivered has been plagued with problems.
I follow numerous communities around GameMaker, and from what I see, adoption of GMS2 is only about 50%, with most of the rest of users still on GMS1, and maybe a tiny number of users still using GM8.1, 8 years after it was released, and 2 years after YoYo officially dropped all support for it. In many forum posts, I see mostly complaints about project corruption, IDE crashes, and complaints about the user experience.
The peak years of the GMS1 era were optimistic, forward-looking, and fun. That feeling has, sadly, mostly gone. I still like working in GMS1, but knowing it will never be updated again, never be improved, and that all remaining issues with remain issues forever, is sad. Knowing that, in time, it will no longer support building to the latest versions the relevant platforms that gamers use, is sad. Knowing that the promised future represented by GMS2 arrived malformed and ridden with defects, and that YoYo hasn’t supported the product well at all since it was released, is sad.
I believed in YoYo, once, and I enjoyed using their product, making games, and fulfilling the dreams of my childhood. I’ll probably continue to use GameMaker for a while longer, and hope that the issues that prevent me from using GMS2 get resolved one day.
But I don’t have a lot of hope or optimism about it any longer, and I’ll be really surprised if someday they do fix the problems that have prevented me from adopting it. And that is perhaps the saddest of all.
GameMaker Studio 2 has been out for almost two years now. I have been using GameMaker since version 8.0, in 2010. I loved the direction YoYoGames took with the product when they introduced GameMaker: Studio, and had been an enthusiastic supporter of the tool, looking past its shortcomings.
When the 2.0 beta hit, I had some issues with it, but I wasn’t worried, because it was a beta. There were many long-standing shortcomings and limitations in old GM:S 1.x, and I was used to working around them as best I could. GMS2 represented a new beginning, a complete re-write of the IDE which was to have fixed many long-standing issues, and put YoYoGames into a position where they could deliver new features more rapidly due to a cleaner, more maintainable codebase.
GMS2 was supposed to be the cure for all that ailed me as a hobbyist wannabe indie game developer. Yet, I still generally prefer to work in GMS1.4, despite the many advances that have been introduced in GMS2.
Put simply, the improvements in GMS2 are eclipsed by some dire showstopping bugs, along with numerous minor gripes.
YoYoGames ended support for GMS1.4 earlier this year, and so its days as a useful tool are short. So, every so often, I try coming back to GMS2 to see if I can work with it. Each time, I’ve found another reason to stay away from it.
For a long time, I’ve been wanting to publish a list of these problems, in order to raise awareness in the hopes that YoYoGames would address the issues and make necessary improvements to their product. I still like GameMaker, and want to be a tool that I can rely on and continue to use. But it’s a lot of different issues, and to properly explain them requires screen captures and video capture that is time consuming to do, so writing this has been something that I’ve repeatedly put off. But, the more I put it off, the more new issues I discover. One would hope that it would be the opposite — that, over time, the issues would become fewer as they are resolved by the vendor.
YoYoGames takes MONTHS to respond to helpdesk inquiries, bug reports
I get that YoYoGames is a relatively small company, with a relatively large number of users. And I also get that a large proportion of those users may be students, non-programmers, or non-professionals who may tax the support department with questions that could have been better handled by reading the manual or going to the community forums. But that doesn’t make me feel any better about the fact that getting a response from the helpdesk when I submit a ticket can take, literally, months. Plural months.
When I have a problem that I can’s solve on my own, and need to submit a ticket with the YYG Helpdesk, the expectation should be that it will be responded to quickly. The exact definition of “quickly” might mean different things to different people, but it most definitely does not mean months, or even weeks.
A few years ago, I might get a response within a couple of days, which was still long enough to be painful. But since GMS2 has been released, it seems to take them several months to respond. I’m sorry, but there’s no way that can be acceptable for a professional user. And to my knowledge, there’s not a premium support option that’s reserved for corporate clients — maybe they do, but if so I have no knowledge of it. But even if that were the case, don’t solo developers deserve and require an acceptable level of support for the product? Of course they do.
Just today (8/8/18 as I’m writing this) I actually got a response to a Helpdesk ticket that I opened up more than a month ago, on 6/22/18, for the IDE crashes when Windows suspends issue that I describe elsewhere in this post. (That wasn’t the first time I’ve reported this issue, only the most recent. The first time would have been in November 2016, when GMS2 was still in its public beta phase.) The response (paraphrased): “Sorry it’s taken us so long to respond, but could you check to see if you’re still experiencing this issue? We’ve released an update since you reported this bug, and will need new log data using the latest version.”
I don’t know why YYG have fallen backwards in this area, but it’s definitely something that they need to improve on.
Other services that I use are able to reply to issues that I submit to them within 24, 48, or 72 hours; among them: itch.io, github, always reply to me quickly, professionally, and in a way that is helpful to resolving my problem. I don’t even pay anything to use itch.io, and they always have responded promptly, because itch understands that making customer support a top priority is paramount to successfully competing in this day and age.
GMS2 projects corrupt themselves when used with version control
To date, most of my experience with GMS2 hasn’t involved any projects that I’ve worked with in version control. I recently decided to start a new project, and wanted to try using GMS2 to make it. I’ve learned the value of version control, and in the last year especially I’ve taken to putting anything and everything that I work on into version control.
In my most recent attempt to work in GMS2, I used git. I created a new repository on github, and started working on my project. After a few hours, I had made several commits. At one point, my program started behaving strangely, so to try to troubleshoot the issue, I exited GMS2, relaunched, and tried to open the project again, only to find that it had become corrupted. No one else worked on this project, it was just me, making commit after commit on a single branch. And somehow GMS2 managed to make a mess of it.
I noticed the problem gradually — at some point, I had a bug in my code that I couldn’t figure out. An object I had placed in my test room wasn’t there. Or it wasn’t drawing. Or it was drawing where it shouldn’t be, somewhere outside of the viewport. I couldn’t figure out why — I only noticed that when I deleted the object and re-added it to my test room, it was offset a great distance from where I dropped it. Why, I couldn’t understand. After messing around with it for almost three hours, I decided to see if exiting GMS2 and restarting it would fix the problem. Instead, the project wouldn’t open.
Aha, corruption! Well, no problem, I’ve been using git after all, I’ll just roll back to the most recent commit, and start over. Losing a little work isn’t great, but sometimes it happens, and version control gives you assurance that you won’t have to throw out more than the most recent commit if something gets messed up. Well… not in this case. Apparently the project corruption was introduced very early into my git commit history, and rolling way back, I still couldn’t open the project. GMS2 gave an error message about a corrupt view. I dug around in the project files, and sure enough there’s a subdirectory called views within the project folder, with a bunch of xml files with weird file names made from long strings of random characters. I found the one that the error message said was corrupt, and tried deleting it, but even after getting rid of the offending view file, GMS2 still couldn’t open up the project.
At this point, I gave up on the project, it was a total loss of about a day’s work for me. Very demoralizing. I returned to GMS1.4 to build the project there.
After posting about it on the Forums, I learned that this is a known issue that was submitted over 4 months ago, and is marked as a “High” priority bug. A potential solution recommended by the bug reporter involves engineering changes to the GMS2 project format, but doesn’t sound particularly difficult. But as the poster commented, “You cannot invite serious professional use of GMS 2 if it does not work with source control, period.”
I’ll be submitting a bug report on this issue, but again, the pace at which they respond to and resolve these problems means that it’s not going to be of any practical help.
[Update — Fixed]: GMS2 IDE crashes when I suspend Windows
This is another showstopper bug, but it apparently doesn’t affect everyone. Only certain combinations of hardware and operating system appear to be affected, and I’m one of the unlucky ones. I happen to be using Windows 7 Professional 64-bit Edition on a Lenovo ThinkPad P50. When I Sleep or Hibernate Windows, if GMS2 was running when I suspended the machine, it will have crashed upon resumption. At first, the program would report a bug, but now as of a few updates ago, it just crashes without any error message.
When I first reported this bug, GMS2 was still in its public beta phase. YYG responded that they were aware of the issue, but replicating it wasn’t easy for them. I learned that it affects certain hardware and OS combinations, and they couldn’t test for every combination. I can appreciate that, but I did send them application crash logs and would expect that they could use that information to determine what causes the crash, and handle it. YYG Support suggested that I try running any application, such as a game, that uses GPU acceleration, and see what happens when it suspends. I did so, and found that the game I tested survived a suspend-resume without crashing.
It’s really not acceptable that I should have to exit GMS2 whenever I decide that I need to close the lid on my laptop. Any time I forget to do this, and it’s very easy to forget, I risk losing work or a corrupted project. Professional tools need to be more reliable than this.
Almost TWO YEARS later, I finally have a solution to my long-standing problem of GMS2 crashes when I hibernate Windows! If you are having this problem, see here:
“What I would suggest is trying the software (mesa) driver. It has far less to try and recover from as everything is CPU based. copy ther opengl32.dll from the “C:\Program Files\GameMaker Studio 2\mesa” folder into “C:\Program Files\GameMaker Studio 2″ folder. This may well give you more stable results.”
Only downside is that your IDE won’t have hardware accelerated graphics anymore, as it will use the CPU instead of the graphics card for rendering. This doesn’t seem to be a big deal so far. (edited)
Workspaces are a UX design fail
The GMS2 IDE consists of modular, dockable window components, and this much is good, and I like it. You can arrange and re-size the components as you see fit, which is how it should be.
The main working area within the IDE window is what GMS2 calls Workspaces. The idea of Workspaces was to allow the user to set up the IDE in a way that suits their workflow. I like the idea of Workspaces, but the way they work in practice is awful. Many users have complained on the forums, and it’s impossible to sum up everything that’s wrong with Workspaces succinctly.
Workspaces are just windows, when you get down to it. However, unlike windows in most other application, within the GMS2 Workspace pane, you have an infinite 2D space that can scroll four ways. Within this space are more windows, as many as you happen to open, which float in this space. These windows are your resource editors: object editors, sprite editors, image editors, room editors, whatever. Each one is opened, maximized, and spread out over the vast Workspace plane.
The result: a very space-inefficient design, with lots and lots of scrolling. Scrolling from one resource editor to another. Close an editor window, and it leaves a gap in the Workspace. If you close an Editor, and no other nearby editor is open within the viewpane area of the Workspace, you have no idea what direction you need to scroll in to find the next open editor. You can scroll in the wrong direction literally forever. There’s no purpose for this endless scrolling — it only serves to make Workspaces a pain to navigate, and I can see no excuse for it to work this way. Most windows, when you get to the end of its content, stop scrolling.
Some users have suggested adding a compass or mini-map to the workspace to aid in navigation when you’re scrolling about. But this is an absurd solution to a problem that shouldn’t exist. Rather than a infinite 2D scrolling region of virtual workspace with more windows floating about within it, a tabbed interface would be so much better. Rather than scrolling from editor to editor in a vast 2D space, simply click on the tab for that editor (or use Ctrl+Tab) to flip through the list of open tabs. Each tab could contain a single open resource Editor, maximized to fill the view pane, and thus give the user the most screen area to the task the user is focused on.
YYG have offered various workarounds, but most of them aren’t very good solutions to problems that should not be there in the first place. The Ctrl+T navigational shortcut can be learned, and it does make navigating about the project much speedier and less awkward than scrolling about a Workspace. But this doesn’t fix the awkward mouse navigation so much as replace it. Some users will prefer to use the mouse, for whatever reason, and they should get a better interface for mouse navigation.
I said I liked the idea of Workspaces, but not the implementation. So what’s the idea that I like? Well, I like the idea that the Project could store a view state of specific resources in the project that the user wants to open frequently. Say you have a large project, being worked on by a team, each team member specializing in some feature of the game. The artist may want a Workspace that opens up all the Sprite resources for all the different animations for each character in the game. One programmer might be working extensively on the Player objects, and needs a Workspace that opens the Object and Sprite editors for all the resources having to do with the Player. One programmer might want to configure a Workspace to organize assets needed for creating levels. Etc.
Rather than having to open up these resources manually, one at a time, every time the user opens the project, they could each define a re-useable, sharable Workspace, set up their Workspace(s) that they need (once), and close them when done working for the time being, and return to any Workspace as needed, and be back up and running with just the editors open that are needed for the task at hand. Each user could set up their own Workspace the way that works for them, and return to it whenever they need to do work on the feature that the Workspace was set up to facilitate. Workspaces could be shared across all users of a Project so that they can all benefit from this setup work. And users could ignore any of the previously set-up Workspaces and create a new one, or just open up resources and work on them one at a time, as normal.
Resource Editor Chain View
My complaints about GMS2 Workspaces are made worse by the desgin of the Object Editor. Depending on your monitor resolution, and how the other dockable window regions in the IDE are configured — the Workspace pane is often too small to show a full view of a resource editor. The Object Editor’s “chain view” expands horizontally as you go from the Object’s basic properties, to the Events, to the Code Editor.
There is a solution, and it is simple enough: In the Preferences>Text Editors. Open [scripts|shaders|object events] in a full screen editor.
Chain view could be easier for non-programmers to understand, since the code window is directly linked to the Object Editor. But the layout wastes a lot of space, and creates a scrolling region (the Code Editor) within a scrolling region (the Workspace), which makes for awkward usability, particularly if the Code Editor overflows the Workspace pane, or if you need to scroll the Workspace horizontally to see whichever end of the Object Editor chain you need to look at.
What I want and need is for the editor I’m using to be maximized, to fill out the pane occupied by the Workspace entirely, or to fill the screen entirely. I don’t want resource editors that float about in an infinite 2D scrolling workspace.
There’s a workaround for this as well, which is to pop out the Workspace into its own window, so it can be maximized to fill the entire screen. But this means you lose the other UI components, which are now in another window beneath the Workspace window. You can flip back and forth between the two, and of course this is what you do. But at this point you’ve essentially abandoned the original concept and design of the GMS2 IDE window and workspaces.
GMS2 IDE UI theme doesn’t follow OS standards
For some reason, YYG loves making the IDE as dark as possible. I guess it’s partly due to their branding. Many programmers prefer to look at code with a dark background and light colored text, because this makes the syntax higlighting easiest to read for most people. I do as well.
And some graphic designers prefer their graphics editors to have a completely desaturated interface, so that their perception of color in the image isn’t influenced by nearby colors in the UI. I do, as well.
GM8 and GMS1 were dark grey, with mostly green accent color. But GMS2 took this even further — too far, in my opinion, making the IDE mostly white on black, with almost no color anywhere.
But I like the window chrome to be not quite so black as YYG have designed their interface, and I like for toolbar icons to be less monochromatic. I find that color helps me recognize the icon I’m looking for. YYG’s UI icons are hard to read, and this slows me down, and makes it harder to enjoy working with the IDE.
This is a relatively minor gripe, and now is largely mitigated by the option of using a custom skin which someone developed that makes GMS2 conform to the default Windows theme colors, giving it a look almost like Microsoft VisualStudio.
However, since custom skins aren’t yet officially supported, any time you update GMS2, the update removes the previous version, and deletes the skin. Then you have to re-install it. And since skinning isn’t officially supported, there’s every possibility that the custom skin you installed today may not work with some future update.
All YYG need to do to make me happy here, is to support alternative skins officially, and allow users to customize their IDE with a skin that won’t break with an update, or need to be reinstalled after an update.
Better would be to offer an official skin that follows the OS desktop theme, and include that among the choices available to the user out of the box.
Better still would be to make this their default, but I just want the choice, and for the choice to be free of inconveniences.
The Code Editor
I am a pretty fast typist — 80wpm or better, sometimes as fast as 110 wpm if I’m sharp and fresh. I don’t like to take my hands off the keyboard when I’m doing heavy typing, it ruins my speed.
Many, many years ago, I learned how to use the keyboard to navigate text documents: in nearly every text editor I’ve used, the arrow keys can be combined with Ctrl and Shift to select text rapidly and accurately, and if you’re good at it, you can do it faster than someone with a mouse can do the same thing.
Add to that the Home and End keys, and Page Up and Page Down, and I can grab a block of text, cut/copy it, and paste it where I decide it needed to go, blindingly fast.
Except in the code editor for GMS2. Here, the usual arrow key behavior isn’t quite the same as it is in nearly every other application I’ve ever used. For some inexplicable reason, when I hit the end of a line in GMS2 with my selection, it doesn’t wrap down to the next line if I hit the Right Arrow. It just stops at the end of the line. Why doesn’t it wrap? Instead I have to hit the Down Arrow, but this isn’t the same — instead of the cursor advancing one word, wrapping to the start of the next line, the cursor drops down a line, appearing in the middle of the line wherever the cursor happened to be.
The effect of this is that I can’t quickly or easily select text in the code editor. I select to the end of the line, stall; my mental focus interrupts while my brain processes what happened and I recognize why the text selection is stalled: GMS2 text editor doesn’t work like every other text editor I’ve used. I switch from Right Arrow to Down Arrow, and continue selecting my block of text. Now too much text is selected, and I have to back it up with the Left Arrow for a few keystrokes.
This probably sounds minor, but if you’re a heavy keyboard user doing a lot of cursor navigation with the keyboard, it’s very annoying.
If you’re going to go through all the effort to build your own IDE for a commercial software product intended for professionals, you really need to make the text editor part of the IDE good, and a big part of that is following conventions.
AutoSave is poorly designed
In GMS1, and previous versions, and in most other applications where you make changes to files, Save was a deliberate action. If you didn’t do it, the program didn’t do it for you. If you wanted to close the file without saving, the program would ask if you wanted to discard your changes made during the current session, or save them. This is a long-established convention and is the way the vast majority of software has worked for decades.
Of course, things can happen. Applications and computers crash. Power goes out unexpectedly. About 20 years ago, better programs started to introduce auto-save, which periodically saves any changes made to the file since the last deliberate save was initiated by the user. In the event of an unexpected exit, the autosave file was saved, as a separate file, and on next application launch the user would be alerted to the existence of these files, and have the opportunity to review them to see if they recovered anything that they would have wanted to keep.
This was a great feature. It absolved the user of having to remember to hit save every few seconds as a matter of habit, and relegated the task to the computer. It also didn’t overwrite anything that the user didn’t explicitly want overwritten.
The way GMS2 works is very different. Whatever state your open code file or editor is in, it’s saved. When you close a file, you’re not prompted to save any unsaved changes. Every time you make so much as a keystroke, your file is saved, whether you wanted it saved or not.
If you’ve made some experimental edits that you didn’t want to save, the only thing you can do is Undo, as much as you need to, until the file has been reverted back to the state that you wanted it — if you have enough levels of Undo to go through, and if you can recognize that file state when you get there. Or to pull an old version of the file out of your version control repository.
It’s ridiculous to have to Undo some large number of edits to get back to a prior state, when in the old paradigm, all you had to do is close the editor and say “No” when it asks if you want to save the changes. And it’s not always the case that you’re going to have a check-in for the file in version control.
YoYoGames announced GameMaker Studio 2.1.5 was released today.
This release focuses on bugfixes and stability, but also adds some very useful new functions:
New collision_*_list() functions that return a list storing the id’s of all instances in collision, not just a single id of the first instance detected. There have been implementations of this in GML scripts since forever, but finally having it in the engine is a great thing, since it will be much faster and available to everyone. The new functions even allow you to sort the list by position order, which is useful in many situations, such as when you need to know which collision would have occurred first in a collision_line situation.
Non-axis-aligned bounding boxes for sprites
This is a new collision type that you can configure in the Sprite properties, “rotated rectangle”. This enables tighter bounding boxes for more accurate collision detection for objects with sprites that rotate, and better performance than using precise collisions, but slower than the regular rectangular collision mask.
Mobile device virtual keyboards
Support for the virtual keyboard in iOS and Android. I’ve never built a mobile app version of any of my GameMaker projects, so I’m surprised to learn that this wasn’t always supported.
A few days ago, YoYoGames announced a new game publishing program for games produced with GameMaker Studio.
Not a lot of details are to be found in the announcement. With established, already-existing services such as Steam,Itch.io, Google Play, and Apple’s App Store it’s not yet clear what advantages YoYoGames are able to offer to GameMaker developers over other publishing platforms.
A GameMaker user recently posted an interesting question in one of the communities that I watch:
So, I’ve known for a long time now how helpful it is to go through source code you haven’t written, just to pick up good habits, and generally understand how things work.
I got the source code for several games including Home and Ink from a Humble Bundle deal a while ago, and am just starting to take a look at them now. I’m finding it really difficult to get a grasp of what’s going on/which objects and scripts relate to what though – mainly because I’m having to switch between several windows of code.
Does anyone have tips about how to learn to understand GM projects? I usually have no problem understanding singular sections of code, it’s more getting to grips with how everything fits together, especially in full-length games. And generally, any tips about how you work through other people’s code.
This happened to be a very timely question, as I’ve recently been going through this myself.
I find it very enjoyable to code my own projects from scratch. I know what I’m trying to do, and I know why everything I put into the project is there. Especially when the project is something I’ve recently worked on.
It’s quite a different thing for me to try to look at a project that someone else has coded. I don’t know what the author was trying to do, or why they did anything they way they did it. Oftentimes the code is not well organized, and very frequently the code is done in a style very different from how I code, or the programmer’s approach is very different from my own, or they use math that I don’t understand well without explaining what they’re doing or why or how it works, and so on. This can make it very difficult to get anywhere.
It’s of course vitally important to be able to work with code that other people have developed unless you have no aspirations to be anything more than a solo coder for your entire life. But even if you never work with other people collaboratively, it can be very valuable to look at other people’s code and learn from it.
If the code is well-documented, this shouldn’t be too hard. I like to say it’s the original author’s responsibility to ensure that the code they write is easy to understand. But well-documented code is unfortunately rare. Documentation (ideally) tells you what you need to know in order to understand the code. How does the author know what you need to know to understand their code? No project can afford to be a 101-level tutorial for new programmers. People will come to the project code with all levels of knowledge and from many different backgrounds, and you can’t anticipate everyone’s needs. Nor should you have to — it should be expected that someone reading your code comes prepared. Working code is rarely intended to be a textbook example for neophytes. Most often, the programmer, if they document their code at all, documents it for themselves, and doesn’t care about anyone else’s needs if they should ever read the code.
So it’s quite understandable, it’s still all too common for code to not be well documented, or just not documented in a way that is useful to you.
Getting into big project that you didn’t author can be overwhelming.
What to do:
Before doing anything else, make sure the project builds and runs.
Play it for a while, and try to catch any runtime errors that may already be in the code. Don’t make any changes to the project until you’re satisfied that it is working. But recognize that there may still be bugs that are hidden more deeply than your playtesting was able to reveal. These may not be the fault of the programmer, either; it’s always possible that some update in GameMaker caused a bug.
It can be really frustrating to open an (unknown to you) already-broken project and make changes to it, then try to build it and find that it’s broken. The assumption will be that it’s your changes that broke the project, but if the bug was already there before hand, you’ll waste a lot of time focusing on your changes, not where the problem really is. So to avoid that, test the project first before you do anything else to it.
While you’re running the project, observe it and take note of any objects that seem important. Guess at what these might be called in the project, and look for them when you start exploring the project in the IDE.
Start with the first Room in the project.
Open it, and see what’s in there. In GameMaker, the project always starts with the first room in the resource tree. Start taking notes about what you find in this room. What objects are present in the room editor, or being created in code? These should be the first objects to examine.
Look at how resource groups are used.
The project may use folders to group things together, especially if it’s a large project. If the author used folders to organize their projects, this will give you some insight as to how the author thought about the project and its parts, and how they relate to each other.
Look for parent objects and see how they are organized.
The inheritance structure of objects will reveal a lot about how the game works. The game may have a lot of objects, but if the author organized them effectively, it’s likely that many of them are related to each other through inheritance, so you may have a comparatively smaller number of object families that you’ll need to familiarize yourself with, and understanding the family broadly will convey much of what is needed to be understood to understand the project as a whole.
Look for dead code and other resources that aren’t used.
It’s very common for developers to leave stuff in a project that never gets used at runtime. This is the “cutting room floor” of the project; it represents stuff the developer worked on for a little bit, but for whatever reason never finished and didn’t end up using. Sometimes there can be a lot of it. Identifying the dead code can be helpful because then you can ignore it, and focus on the live code. Once you’re sure the code isn’t used by the project, you may want to move it to a folder of dead code where it is out of the way and can be ignored, or just delete it from the project entirely.
There isn’t really an easy to way to identify dead code. But a few things to look for are code that is commented out, scripts that are never called anywhere in the project (use GMS’s “search in scripts” feature to find everywhere a script is called in the project.) Objects that are not present in any of the rooms, and are not referenced in code anywhere. Logical conditions that can never be satisfied can lead to dead code branches in if or switch statements, also, but these are a little harder to spot.
Look at scripts.
Scripts (often) support objects. Scripts are also (usually) well isolated and self-contained, so as to be reusable. Depending on the project’s size and the programming style, scripts may call other scripts. This can become difficult to follow if you have to jump between a bunch of different codefiles, but at least on your first pass this shouldn’t matter as much — just recognize that a script call is abstracting some detail, and you don’t necessarily need to get into the detail yet.
Look at objects.
First, scan the resource tree for objects that have sprites that you recognized from playing the game. Those are probably a good place to start.
Look at the player object(s), then enemies, and other things like terrain objects, weapons, pickups, or whatever. There may be some important objects that are invisible during gameplay and don’t have sprites. Look at the name for a clue about what the object is for.
As you get into each object in detail, probably the most important Events to understand are the Create, Step, Collision, and Draw events. Start there if the object has these Events defined, and take note of any other events it may use, and what it is doing in them.
You may find GML code, or you may find Drag-and-Drop actions, or a little of both.
As you start looking through the code, it’s going to be very tempting to make small changes, perhaps to conform to your ideas about code style and good practices. But try to resist the temptation to do too much of this at first. Even seemingly simple fixes can have consequences that you don’t realize. And you might find after “cleaning up” a bunch of code that it’s not needed at all, and can just be discarded.
The only thing you should really do on your very first pass through the code is leave comments. I like to prefix my comments with my initials, and what the comment is about: Question, reminder to do something later, explanation, bug, possible bug, etc. This helps me as I go through the whole project and find answers to the questions I initially had when I first started digging into the project. And my initials help me to keep straight whether the comment is mine or the original author’s.
As you review the project code, add comments with your notes, explaining where needed. Comments can be questions, eg “What’s this for?” or notes for things to do later (“This looks interesting, come back later and understand this fully.”
You can (and should) also take notes outside of the project. It depends a bit on the purpose — are you just looking at this project to learn from it, or are you working on the project to maintain or modify it? If you’re conducting a learning exercise, the notes should be the takeaway of what you learned by exploring the project files. If you’re actively working with the project, then the notes can be a guide to accumulate the understanding that you gained as you explored the project, a list of questions you still have, problems you intend to work on, bugs that need to be fixed, or other work to be done.
Focus on the interesting parts.
(The stuff you don’t yet know, but are interested to know/figure out.) Don’t worry about stuff you don’t understand, but aren’t interested in. Don’t worry about the stuff that’s simple/obvious to you.
Don’t assume perfection.
The programmer knew what they were doing. Well, maybe. Programmers make mistakes. Or do experiments. Or half-formed thoughts. Or just don’t know a better way to do something.
Code often has bugs. Code is usually sub-optimal.
As you take ownership of the project, you will need to start being the decision maker who knows what they’re doing. It’s easiest and best to carry forward with a good understanding of the previous author’s thinking, but it’s almost never available to us directly, and we have to infer it from what we do have.
If you’re new to programming and lack experience and are looking at advanced, complex code in a big project, it’s hard to do this. But start with small changes, test constantly, and build confidence as you learn and grow familiar.
Ask questions about the stuff you can’t figure out. Contact the author directly if you can, be respectful and appreciative if they’re open to talking about it, and understand if they’re not interested. If they’re not responsive, or you still have questions, take them to the GMC Forums. Lots of people are there who will take an interest and try to help. Find a friend who is willing and able to mentor you, or even work with you on the project.