GameMaker: Beautifying/pretty-printing JSON

Partially related to an earlier blog post about minifying JSON (which I had just updated), but adressing a different problem - sometimes, rather than trying to make your JSON more compact (and, consequently, less readable), you may want to make it more readable - be that for your own debugging purposes, or not to scare players away from files that they are allowed to edit.

Take Nuclear Throne, for example. The save file is a big nested JSON structure, and, needless to say, you aren't getting around passing it through an external JSON beautifier if you want to be able to make sense of it:

With a bit of string processing, however, you can have it printed out nicely readable:

So this post is about that.

Continue reading

GameMaker: Minifying JSON

If you've spent some time working with JSON in GameMaker: Studio, you may have noticed that the built-in functions aren't exactly interested at making output laconic - they always write numbers with 6-digit precision, meaning that 3.5 always becomes 3.500000 even though the extra zeroes serve no purpose whatsoever.

The problem becomes more prominent when encoding data that is largely numbers - say, if writing down a shuffled sequence of numbers,

var map = ds_map_create();
//
var list = ds_list_create();
for (var i = 0; i < 32; i++) ds_list_add(list, i);
ds_list_shuffle(list);
ds_map_add_list(map, "order", list);
//
var json = json_encode(map);
ds_map_destroy(map); // destroys the list in the map as well
show_debug_message(json);

The output is as following:

{ "order": [ 30.000000, 22.000000, 2.000000, 8.000000, 17.000000, 14.000000, 25.000000, 9.000000, 20.000000, 29.000000, 10.000000, 26.000000, 6.000000, 15.000000, 21.000000, 1.000000, 11.000000, 3.000000, 24.000000, 12.000000, 19.000000, 31.000000, 7.000000, 28.000000, 18.000000, 4.000000, 0.000000, 5.000000, 27.000000, 16.000000, 23.000000, 13.000000 ] }

Where, out of 357 bytes, 250 bytes are whitespace or unneeded "precision".
A little inconvenient, if you don't have a compression algorithm on hand.
But, of course, that can be helped with a script.

(post revised in 2018)

Continue reading

Haxe: Simplistic .properties parser

If you have ever been using Java, you may already be familiar with .properties file format. This is a simplistic configuration file format, somewhat similar to INI:

# Comment
key = Value

For ones not liking that, there's also alternative syntax:

! Comment
key: Value

Where leading/trailing spaces are optional and are trimmed in parsing process.

Since I've seen people ask about this kind of thing, and also have seen people invent ridiculous (and non-functional) regular expressions to parse this file format, I thought that I may as well make an implementation that works "just right".

Continue reading

GameMaker: Recursive folder copying

In some situations you may want to copy a folder from your GameMaker game. And it would seem trivial but not that easy. file_copy can only copy files, and folder functions only allow you to create, check, and search folders for files. However, given these standard functions, implementing a folder copying routine is fairly easy.

Idea used here is to find a list of files and folders via file_find_*, and then go through them, checking whether they are files or folders, copying or recursively calling recursively function script accordingly. Sure that poses a potential problem if you were to copy entire disc contents to other location, but you are probably not going to be doing that via GameMaker... right?

Attached example contains the function and brief demonstration of functionality (you have to input source/destination paths as text).

Download GMK

Code follows,

Continue reading

GameMaker: Taking screenshot of area larger than screen


Above: in-game view. Below: taken screenshot of entire room

This is an example that I've actually made a long time ago, but apparently it remains a common unresolved problem.
For multiple cases you may need to take a screenshot (or copy to surface) entire room, while only portion of it can be seen at once (window/screen size limitations).
A perfect work-around for this is to force screen drawing into a surface of chosen size, after adjusting view settings.

Download GMK

GameMaker: Executable “self-destruction”

In some rare cases, you may need executable to 'vanish' (delete itself) upon shutdown.
The most trivial case for such behavior would be updating (when never version of game is downloaded, and there is no reason to keep old one).
Less common cases include removing game under specific conditions (note: this is not an appropriate way of stopping user from playing it) and single-use utilities (which user will never need to run again for sure)
However, as you may noticed, executable's cannot delete themselves while running.

So, some tricks are needed.
The easiest one is to have second executable to run afterwards and delete the first one.
To illustrate source of such 'clean-up' program, I have used language that provides smallest output file size, while still keeping it readable. In this case, it's C++.

#include "windows.h"
#include <tchar.h>
int APIENTRY _tWinMain(HINSTANCE ii, HINSTANCE pi, LPTSTR lpCmdLine, int ncs) {
	for (;;) {
		if (DeleteFile(lpCmdLine)) return 0;
		Sleep(100);
	}
}

(you can download compiled version of this code here)

Structure of code is quite simple, as you could notice - we include two required headers (windows.h for used functions and tchar.h to allow main function definition to be written this way); main function itself consists of a perfectly infinite loop (heard of these?) in which program attempts to delete file given by command line and quits on success, or waits 0.1 second and tries again.

Integration on GameMaker side is simple as well - all you have to do is to run program described above just before game ends with game's executable location as a single argument. Fortunately function parameter_string(0) can be called to retrieve mentioned location, so code can be minimized to

execute_program('DeleteThat.exe', parameter_string(0), false)

Obviously, this way you will have a secondary executable remaining upon success of all operations, which user will have to delete manually (or not delete at all, in case of use in updater).
To save user from potential wondering about purpose of small executable that appeared after game's end, it can be unpacked into game's temporary folder.

Download GMK

Example illustrates typical setup for such game: secondary executable is included inside of game, and is unpacked & launched at game end. To test it, compile game into executable file, run it (in this case it's just a placeholder window) and close it by pressing Escape or window button - executable will vanish in moments after process termination.