GMStruct - extending GML with code generators

GML, or the GameMaker language has regularly been a little awkward for me to use due the lack of a core feature. That would of course be structures, a programming language staple allowing you to group together values under a single variable.


In the past, I would have recommended using arrays to act as structures, as described in my youtube video, and this is probably still good advice today (Or at least until YYG implement lightweight objects). However tired of messing around with arrays in my projects, I have decided to let robots take over, and generate all that code for me.

This is how I started creating GMStruct. A tool and language to bring structs to Game Maker.
Introducing code generation allows for numerous upgrades over 'array structs', allowing for inheritance, and even some polymorphism, all handled behind the scenes.

View the GMC Thread


The GMS Language

"So how does it work?" I hear you ask. Well it's pretty simple:
The first step is to define the structures using the accompanying language, GMS. Don't worry, the syntax is simple, and should be pretty familiar to any C developers.

This simple example shows how a simple person struct, with a name, age and height attribute can be defined.

Where GMS is quite different from GML, is that values can be typed. This means that throughout the lifetime of the variable, the attribute or variable will have the same type.
There are a few basic types in GMS, including:
  • real: a real valued number
  • string: a series of characters
  • boolean: either true or false
However, there is also the 'wild type'. This type is basically a super type of all other types. This means it can hold any value, but means you cannot do many operations on it that require its type to be known. Typing an attribute means that when you assign a value to it, the type of the value will first be checked against the type defined. It also allows the GMStruct static analyser to make sure your code is safe and will behave as expected.

In the person example above, all of the attributes are of the 'wild type'. If you want to restrict the type of an attribute, you simply precede it with the name of the type:

This example shows a car structure, with typed attributes. What is interesting to note, is that attributes can have the type of any defined structs, such as the owner attribute, which is of the type of the previously defined person struct. This allows you to build complex compositions and is required to access the attributes of stored structures in GMS functions.

So these are the basic features of GMS; simple struct definition.
Of course, GMS is already capable of a lot more, like inheritance, functions, and defining namespaces, but those will have to wait for a later post, as I think its time to explain how you can use your GMS code.

Generating GML

GMStruct is not only the GMS language but also a code transpiler. You can get the transpiler (written in Java) over on Itch.io, and if you are interested, I am hosting the project source over on Github for your enjoyment.

Once you have written up your GMS and saved the file as a .gms file, you can go ahead and launch the GMStruct jar.
This should prompt you to select a first file, which should be your GMS source.
It will then ask for a directory to save the generated source in.
After selecting the two files, your destination directories should be filled with a bunch of generated GML files, otherwise, it is an indication that there may be an error with your GMS file.
In that case, I recommend you launch the jar using the command line so that you can view the errors.

I know what you are thinking, it is a pretty rudimentary interface, and I am well aware of that. But I am planning on building some proper UI for the tool.

Once your source is generated, You can simply drag and drop the files into your GameMaker 2 project and your structs are ready to be used.

Using the Source

The generated GML is also rather straight forwards to use.
You can create a new structure using the new_* functions.
For example, create an instance of the person structure we defined earlier would go as follows:
As you can see, when creating a struct, you must provide the values the attributes should start with in the same order you defined them in the GMS file.  (Unless you provided default values, but again, this will be described in another post).
Once you have created your struct, you can retrieve or set the values stored in it as follows:
As you can see, the script name is comprised of the structure's name, followed by the name of the attribute to access. The scripts to get and set the attribute of a structure are one and the same. But its behaviour changes depending on the number of arguments.
This cuts down on the number of generated scripts and shortens script names a little.
I am aware that GM users are a bunch performance hypochondriacs, but don't worry, these little extra checks do not impact performance much, and I will explain in a later post why it won't matter anyway.
So this is the basic usage of Structures from GMStruct. Cool, but not very exciting right?
Well the real power of GMStruct arises when you start looking at inheritance, and functions. But these really warrant their own posts.
So, for now, I highly encourage you to try out GMStruct for yourself.

It is still very much in early development, and any feedback would be greatly appreciated!

Comments

  1. That's really cool, I like how that system is set up so you can use it like a custom defined function, and create and use all or part of it's variables anytime after it's creation, Nice work and I'm headding over to get and check it out now! I see you mention gms2, I'm assuming it also works with gms1x as well?

    ReplyDelete
    Replies
    1. Actually this currently only works for GMS2. That is because it takes advantage of the array literals GMS2 introduced.
      Perhaps I will add support for GMS1.x, by I troducing an option (iether in the tool or language) to decide compatibility, but that may be a little ways of due to the extra work and maintenance required.

      Delete
    2. Ok no problem, I'll be switching to gms2 sometime in the near future due to gms1 is closing down soon, I've just been putting it off as long as I can mainly because gms1 is so familiar to me and I can now quickly make games and apps with it, but as of late I've been learning a lot of new programming tools such as java, processing, c, and some others.

      Delete

Post a Comment

Popular posts from this blog

GMWolf - Defining States with Objects

GMStruct Inheritance and Types