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.

Continue reading

Binary operations with lists on Twitter web

Binary operations with Twitter lists via web client

For quite a while now, Twitter has lists. Lists are nice - you can include people with them, and then view their posting on a separate page. Or view multiple of these at once if you are using TweetDeck.

The process of managing lists leaves some to be desired, though - if you want to do something like

  • Add all followed users to a list
  • Exclude all followed users from a list
  • Add all followers to a list
  • Add all members from a list to other list
  • Exclude all members of a list from another list

You are apparently expected to do so by using the little context menu on each user, picking "Add or remove from lists...", and then ticking/unticking the checkbox for the according list.

That's no fun. But, of course, this can be helped with a bit of JavaScript.

Continue reading

Introducing: Nuclear Throne Together

Perhaps you've already heard that I've been recently developing a mod for the current version of Nuclear Throne. And not "just" a mod, but quite an impressing one:

  • Adds Steam-based online multiplayer support to the game.
    That means invitations, public game list, and no port forwarding.
  • Replays
    Easily record and review your runs to learn from mistakes.
    Or even attempt to correct them by dropping into the game at any point of a replay.
  • Better coop
    Nuclear Throne never was a coop-centric game, and thus coop mode didn't receive enough attention, remaining ridden with various small bugs. This mod changes that, fixing pretty much every known issue, and giving coop some much-needed polish.
  • Bugfixes
    While fixing coop-related bugs is an obvious choice given the scope of the mod, I didn't stick to just that, and also fixed a handful of other issues with the game. Bugged "crown vaults"? Fixed. Game hanging in certain areas? Fixed. Occasional crashes during an intro to an important boss fight? Also fixed. The full list is long (200+ items) and available in the "readme" document.

So it works, it's nice, and you can download it right now.

Or continue reading on process and potential questions.

Continue reading

Haxe: C-style enum macros

I've recently stumbled upon this little macro by Justo Delgado. It takes an "enum abstract" and sets the values of it's constant-fields incrementally. This brings up an interesting point.

See, in C, you can leave out the values and have them assigned automatically (0, 1, 2, ...), set the values manually, or mix the two, having the values continue "upwards" from the last specified value. So, for example, if I have this,

enum class Op {
	Add = 0x90, Sub,
	Mul = 0xA0, Div, Mod,
};

Op::Div will be equal to 0xA1, which is convenient, and allows grouping enum constants together (in this case storing operator priority in the upper 4 bits).

Haxe doesn't have that "out of box", unfortunately - either you make an actual enum and have the values assigned automatically, or make an @:enum abstract and assign the values manually.

But, of course, that can be fixed with a macro.

Continue reading

Haxe: Shorthand expression matching

This is a small post about a small, useful macro for Haxe.

As you may (or may not) know, Haxe has fancy enums (which are actually algebraic data types). That's nice. And you can do all sorts of fancy value matching on them, which is also nice.

What is less nice, however, is that the only conventional way to extract enum arguments is to "match" it, and thus in some situations you can only do code like this,

var r = switch (expr) {
    case one(k): k;
    default: -1;
};

adding a couple lines of code in place of what feels like it could have been a single operator.

So I wrote a tiny macro which adds just that:

var r = ematch(expr, some(k), k, -1);
Continue reading

GameMaker: Using external version control

Over time, I have witnessed a particular scenario a few too many times:

  1. A person demonstrates complete unwillingness to learn how to use version control, be that due to "lack of need" or delightful claims of their existing approaches (which most often turn out to be manual backups) being sufficient or even superior.
  2. A person loses days, weeks, or even months of work due to human error and/or hardware failure(s).
  3. Noticeably bitter about the situation, a person attempts to continue defending their position.

Having spent far too much time arguing with people and explaining how to use version control, I have decided to make a blog post that would cover a few things on the matter:

  • Explain the advantages of version control over "simpler" backups.
  • Explain (step-by-step) the basics of using a common combination for version control being BitBucket (service) + Git (software) + SourceTree (GUI client).

While this tutorial is oriented on GameMaker: Studio users, it can also be easily applied for other tools.

Continue reading

Understanding isometric grids

Isometric grid coordinate conversion demo
A GIF of the interactive demo seen later in this post.

Questions about the algorithms related to isometric grids are not uncommon. In fact, they are a little more common than you could expect them to be, given the relative simplicity of things.

So I have decided to write a little blog post on the two things important here:

  1. Converting local isometric grid' coordinates to global screen-space coordinates
  2. Converting global/screen-space coordinates to isometric grid' local coordinates
Continue reading

Changing scroll speed in Firefox using CSS

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam fringilla, turpis eget vestibulum vulputate, enim orci tempor enim, vel consectetur ipsum orci sit amet enim. Aliquam nec viverra justo. Pellentesque viverra cursus quam eget maximus. Nullam iaculis mauris leo, et pharetra nisi ultricies in. Mauris varius hendrerit nulla, quis aliquet sapien. Pellentesque eu ultrices nibh. Nunc mollis porta tincidunt. Praesent risus nibh, vestibulum eu gravida et, dignissim eu velit. Mauris quis iaculis mauris.

Nulla facilisi. Suspendisse malesuada tortor sed augue tempor sodales vitae vitae felis. Suspendisse urna nunc, luctus sit amet libero et, vestibulum pellentesque sem. Vivamus mollis felis id nisi ultricies, vitae lacinia est egestas. Pellentesque quis quam non dolor ultricies pulvinar. Nunc sodales diam tristique pharetra vehicula. Fusce consequat eu turpis vitae consequat. Ut aliquet sem felis, vel venenatis mi commodo a. Donec volutpat egestas enim, at vestibulum ligula vestibulum eget. Nunc facilisis ex felis, et fermentum arcu pellentesque sed. In molestie eros nec metus molestie iaculis. Cras eu sem consectetur ex consequat blandit at auctor lacus. In finibus dolor vitae leo dignissim, non egestas dolor consectetur. Vestibulum sit amet sem sit amet nulla dignissim rhoncus sed nec est. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam fringilla, turpis eget vestibulum vulputate, enim orci tempor enim, vel consectetur ipsum orci sit amet enim. Aliquam nec viverra justo. Pellentesque viverra cursus quam eget maximus. Nullam iaculis mauris leo, et pharetra nisi ultricies in. Mauris varius hendrerit nulla, quis aliquet sapien. Pellentesque eu ultrices nibh. Nunc mollis porta tincidunt. Praesent risus nibh, vestibulum eu gravida et, dignissim eu velit. Mauris quis iaculis mauris.

Nulla facilisi. Suspendisse malesuada tortor sed augue tempor sodales vitae vitae felis. Suspendisse urna nunc, luctus sit amet libero et, vestibulum pellentesque sem. Vivamus mollis felis id nisi ultricies, vitae lacinia est egestas. Pellentesque quis quam non dolor ultricies pulvinar. Nunc sodales diam tristique pharetra vehicula. Fusce consequat eu turpis vitae consequat. Ut aliquet sem felis, vel venenatis mi commodo a. Donec volutpat egestas enim, at vestibulum ligula vestibulum eget. Nunc facilisis ex felis, et fermentum arcu pellentesque sed. In molestie eros nec metus molestie iaculis. Cras eu sem consectetur ex consequat blandit at auctor lacus. In finibus dolor vitae leo dignissim, non egestas dolor consectetur. Vestibulum sit amet sem sit amet nulla dignissim rhoncus sed nec est. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

(live demo - compare scrolling speeds in Firefox)

For quite a while now, a thing that bugged me in Firefox was the inconsistent scrolling speeds across the pages. On some it would seem just fine, while on others you could have a list that scrolls at a ridiculously slow pace. My searches on the subject were inconclusive - while, of course, you can regulate the scroll speed via scripting, that definitely wasn't the case on all these pages.

The culprit, as it turns out, was pretty simple - while most of the browsers scroll the elements for an amount of (screen) pixels per key press or mouse wheel change, Firefox scrolls the elements based on the their font size. Which, on one hand, makes sense, but there's a catch - it's based only on the scrolling element's font size. Content' font sizes are ignored.

So that is why you get odd scrolling speeds - people most often set up styles for the actual content (paragraphs\labels\etc.) and not the scroller\container element.

Luckily, this also means that scrolling speeds can be adjusted easily - you change the container font-size to (100*X)%, and then add a rule to change it's child element sizes to (100/X)%:

Continue reading