Skip to content

Introduction

ScaffScript Banner

ScaffScript is a minimal superset of GML (GameMaker Language) that adds a TypeScript-like module system. Write organized, modular GML in .ss files. ScaffScript compiles to GML and can inject it directly into your GameMaker project.

Exports & Module System

ScaffScript Exports Example

Code Generation & Integration

ScaffScript Code Generation Example

Write TypeScript-flavored GML, ship as an actual GML
Section titled “Write TypeScript-flavored GML, ship as an actual GML”

Don’t forget to leave a star on the GitHub repository! ⭐

GML is perfect for fast prototyping with its functional and event-driven nature. But, this paradigm may be limiting when your project grows. Yes, you can split your code into multiple script assets. But, it becomes verbose fast and pollutes your global-scoped code (functions, macros, enums). Like, creating function mylib_create(), function mylib_*, function and function over and over again. And it become the worst nightmare if you want to create “one-gigantic-library-in-one-script” that contains everything, moreover, if you want OOP approach with GML.

ScaffScript exists to fill that gap. It adds a module system to GML, so you can write organized, maintainable GML code. It’s designed to “free” you from the that verbose code, while still keeping the flexibility of GML. You can think of it as a “preprocessor” for GML. It’s not a full-blown language, it’s a minimal superset language to help you write better GML code, especially for creating GML libraries.

  1. ScaffScript scans your source directory for *.ss and *.gml files.
  2. Resolves all export / import / include references across files.
  3. Reads intg statements to know which blocks go to which GameMaker asset.
  4. Generates .gml output.
    • If noIntegration is false, ScaffScript writes and integrates it directly into your GameMaker project.
    • Otherwise, ScaffScript only writes the output to the .out/ directory for you to review and integrate manually.

That’s ScaffScript in a nutshell. It’s designed to be as simple and lightweight as possible, while still providing a powerful module system that you can use to organize your GML code. You’ll learn more about how to use it later in the Your First Script guide.

  1. No AST

    ScaffScript currently uses a regex-based parser for rapid development. It’s not very reliable for complex code structures. For example, it may not work well with nested code blocks, such as nested struct literals in @use directives. It may also not work well with other edge cases. We may change to AST-based parser in the future.

  2. No test for GameMaker 1.x

    ScaffScript is currently designed and tested only for GameMaker 2.3+. It may or may not work with GameMaker 1.x.

Let’s say, we’re going to create a library for handling CSV files easily called EzCSV.

With only using GML, your project structure in the GameMaker IDE may look like this:

  • DirectoryEzCSV/
    • DirectoryFile-System/
      • scrEzCSVFSRead
      • scrEzCSVFSWrite
    • DirectoryGenerate/
      • scrEzCSVGenArray
      • scrEzCSVGenDS
      • scrEzCSVGenPrimitive
      • scrEzCSVGenStruct
    • DirectoryParse/
      • scrEzCSVParseArray
      • scrEzCSVParseDS
      • scrEzCSVParsePrimitive
      • scrEzCSVParseStruct
    • scrEzCSVGet
    • scrEzCSVUtils

All of them are script assets. That’s the simplest way to organize your code in GameMaker IDE. Of course, you can split them again into folders, but, it’s not very maintainable when your project grows, as all of the “modules” are actually just a global functions, enums, and macros.

We will only cover the general logic of some files/modules, not the actual implementation, so you can get the idea of how ScaffScript works.

scrEzCSVRead.gml
function ezcsv_read(file_path) {
var result = "";
// implementation...
return result;
}

As you can see, all of the functions are in the global scope. They are not “connected” to each other in any way. You can “connect” them by calling the functions directly, as shown in the scrEzCSVGet example. But, it may become painful to manage when your project grows.

Yes, what you see is correct! ScaffScript code is longer and more complex than the GML code. It makes sense, because we’re using ScaffScript’s module system to connect the exports from different modules (in this case, functions).

Each export can be used by other modules using import and include statement. So, you have more control over your code organization, such as:

  • What should be “private” and “public”.
  • What should be inlined and what should be called.
  • Where should the code be put.
  • What should be the final output.
  • Etc.

You don’t need to “throwing” everything into the global scope anymore. It’s like an overkill for a simple library like this, but it’s worth it in the long run.

ExtensionDescription
.ssScaffScript source, supports the full module system
.gmlStandard GML, can be included as raw content via include

If you have any questions or feedback, feel free to join the Discord server or open an issue on the GitHub repository.

ScaffScript is licensed under the MIT License.

Contributions are welcome! Please see the Contributing guide for more information.

If ScaffScript is useful to you, please consider sponsoring or supporting this project through Ko-Fi or Trakteer. Your support helps keep the project alive and thriving!