Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics


A member registered Mar 30, 2020 · View creator page →

Creator of

Recent community posts

Utilizing social media (Twitter is popular amongst game developers these days) is a pretty good way to keep people updated about your game. Making a few posts every couple of months is enough to prevent people from forgetting that you exist, but not so much they become annoyed and unfollow you. The content of the posts doesn't have to be particularly much, either - a short gif showcasing a few interesting things that you have added since the last post seems to be the standard. Making such a gif won't take you longer than ten minutes, so it isn't going to eat up as much time as some other forms of promotion, such as creating a YouTube video.

If you're on Mac OS you won't be able to run a .exe, since that's the executable format used by Windows. I'm not familiar with Mac OS, but my best guess on the format they use for executables is a custom format based on ELF.

Try running it through an emulator such as Wine. This isn't guaranteed to work, since Wine has a lot of issues running many applications, especially graphical ones, but it's worth a try. Alternatively, you can install a Windows virtual machine using software such as VirtualBox; Performance won't be great but you will be able to verify that it works, at the very least.

Maybe try asking in the FNF community, that way someone who knows about the project can help you.

(1 edit)

If you're talking about unit testing and you're using Visual Studio, use the built-in unit testing feature in Visual Studio for C#.

SDL isn't a game engine.

It's a media library.

(1 edit)

Results look identical if you scale by a multiple of two and if you use nearest interpolation on your textures. It's faster, too.

I ain't able to see a forum anywhere.

It used to be a place to find interesting people working on interesting projects, now the general discussion is roughly equivalent to sorting by new on r/teenagers.

I only recently came back here after about a year of total inactivity. It isn't the community I remember.

Scratch as I understand it is implemented in JavaScript.

As I understand you're wanting to create something similar to OS.js?

It begs the question of why? The way a huge amount of people use an operating system these days is simply to host a web browser, so it doesn't make all that much sense to run another OS inside the browser. A full OS inside a browser would also be extremely slow and memory heavy, due to the bloated nature of JavaScript.

If you're paying for assets, why not simply hire a freelance artist?

(1 edit)

No, HTML is a completely different format to an executable, converting between them is impossible.

The closest thing would be creating an executable with a minimal web browser that simply loads an HTML document, which is similar to what frameworks such as Electron do. I'm against this for a number of reasons, personally, mainly because it introduces an unecessary amount of bloat.

Look at some other games and compare their quality to your game; If you see a game that costs $20 that's in a similar genre to your game and you judge it to be of similar quality, make it $20.

The tutorial expects you to be familiar with basic file management from an API.

It explains the process of appending all the resources required by a game to run (such as textures and scripts) to the game executable and then explains how they can be read back once written.

It is most applicable to be used when creating games without an engine, since most game engines do some form of resource packing already.

It would be nice if you could be more critical in your feedback; That way I can improve my writing in order to be more helpful.

(4 edits)'s formatting doesn't behave itself when it comes to code. Because of this, here it is in plain HTML.

This tutorial outlines the process of packing and unpacking all the resources required for a game (be it textures, scripts or level data) into a single file, to make it easier to distribute, and more importantly easier for people to download and play. Though this method is most applicable to games, it could also be used to pack resources such as icons and fonts for more general-purpose applications. Note that this method is unsuitable for packing dynamic libraries, at least, not without writing custom code to load the libraries.

The method outlined in this tutorial is one of many, and doesn't do anything fancy such as compression, which makes it unsuitable for packing the resources for large games. That said, for the majority of indie games where the resources total a size of about a gigabyte, it works perfectly and is rather fast.

The general gist of it is this:

  • Build the game into an executable.
  • Write a specific sequence of bytes at the end of the executable.
  • Pack all the resources into a single file, with some kind of index that outlines the offsets of each individual file.
  • Append the resource package onto the end of the executable.
  • To read back the data, simply read from the end of the executable file and look for the byte sequence that we wrote earlier. The index can then be used to lookup the data offset for the raw data of each file.

The code examples in this tutorial are written in C, but this method can be utilised in any language that has a somewhat complete file API.

Packing Files

Packing the files is the easier portion of this process, so that's what will be covered first.

The first step is to write a specific sequence of bytes to the end of the built executable. Before doing this, it's a good idea to check if these bytes already exist or not, that way you don't add more when you don't need to. That detail has been omitted from the following example for simplicity. This sequence of bytes should be something that is extremely unlikely to appear anywhere else in the resulting file, either in the executable's code or the game's resources. I normally use a 64-bit integer generated by the ELF-hash algorithm, from a string such as "game data". If all your game is storing is text, simply writing a null character will work just fine - but in most cases games rely on more than just text; it's likely that a texture, for example, will contain some null bytes itself, which will mess with the unpacker.

The code for this generally goes something like this:

FILE* file = fopen("./my_executable", "r+");
fseek(file, 0, SEEK_END);
unsigned long long bs = elf_hash("game data");
fwrite(&bs, sizeof(bs), 1, file);

It's not a bad idea to make a small, stand-alone program to do this part, that way you can invoke it as a post-build command from your build system. If you're using the hashing method of generating the byte sequence, just make sure that your game uses the same hash function for loading in the package.

Now it's time to actually do the packing. I usually combine this with the program that adds the byte sequence, though you could easily build it in to your level export process as well, if you have one.

To do this, first an index of the byte offsets and sizes for all the files needs to be generated. Unfortunately, there's no real clean way to do this other than iterating all the files to be packed, fopen'ing them and using fseek and ftell to calculate their sizes. This index is not dissimilar to a table in Lua or a dictionary in Python, with the file names being the keys, and their offsets being the values. Instead of storing the actual string of the file names, I normally just store hashes of them, which slightly reduces the time it takes to lookup a file in the index.

The code to pack all of the files looks like this:

const unsigned int buffer_size = 2048;
unsigned char buffer[buffer_size];
FILE* output = fopen("./output.res", "w");
unsigned int index_element_size = sizeof(unsigned int) * 3;
/* Calculate and write the size of the index. This will
 * be used to offset the data blob in the read process. */
unsigned int index_size = index_element_size * file_count;
fwrite(&index_size, sizeof(index_size), 1, output);
unsigned int index_offset = sizeof(unsigned int);
unsigned int current_blob_offset = 0; 
/* Write all the files to the output file. */
for (int i = 0; i < file_count; i++) {
    unsigned int file_size;
    unsigned int name_hash;
    name_hash = elf_hash(files[i]);
    FILE* file = fopen(files[i], "r");
    fseek(file, 0, SEEK_END);
    file_size = ftell(file);
    /* Write the file into the index */
    fseek(output, index_element_size * i + index_offset, SEEK_SET);
    fwrite(&name_hash, sizeof(name_hash), 1, output);
    fwrite(& current_blob_offset, sizeof(current_blob_offset), 1, output);
    fwrite(&file_size, sizeof(file_size), 1, output);
    /* Copy the file's data into the data blob */
    fseek(output, current_blob_offset + index_size + index_offset, SEEK_SET);
    fseek(file, 0, SEEK_SET);
    for (unsigned int ii = 0; ii < file_size; ii += buffer_size) {
        unsigned int bytes_read = fread(buffer, 1, buffer_size, file);
        fwrite(buffer, bytes_read, 1, output);
    current_blob_offset += file_size;

Instead of copying the file all at once, a buffer is used to copy 2048 byte portions of it at a time. This is because some resources, such as textures, can be quite large, and it would be slow to load the entire thing into memory at once. For conciseness, error checking has been left out, but you always want to be checking that file handles open successfully in any real world application.

Once you have all of the resources packed into a single file, it's trivial to simply append that file onto the end of the executable. Again, we want to use a buffer to copy the package, since the package could be gigabytes in size.

const unsigned int buffer_size = 2048;
unsigned char buffer[buffer_size];
FILE* exec_file = fopen("./my_executable", "r+");
FILE* package_file = fopen("./output.res", "r");
fseek(exec_file, 0, SEEK_END);
fseek(package_file, 0, SEEK_END);
unsigned int package_size = ftell(package_file);
fseek(package_file, 0, SEEK_SET);
for (unsigned int i = 0; i < package_size; i += buffer_size) {
    unsigned int bytes_read = fread(buffer, 1, buffer_size, package_file);
    fwrite(buffer, bytes_read, 1, exec_file);

And with that, the packing portion of the process is done. If you did everything correctly, you now have a game executable that contains all of its resources.

Reading The Resources

Now for the less trivial part; reading the resources back in from the packed executable. You probably want to set up a system so that only release builds will read from the package, since having the files separate can be advantageous for development, if only because it allows you to edit the resources individually more quickly, without having to repack the executable every time you make an edit.

The first step of the process of reading is for the executable to fopen itself. To do this, you need the path of the executable. On Unix-like systems, this can be done by calling fopen on argv[0] passed from main. On Windows it's generally more involved to get the path of the executable, since running an application through the command line doesn't require you to specify it's extension, so there's a chance that argv[0] won't get the actual path. I usually use the GetModuleFileNameA function from the Win32 API, passing NULL for the hModule parameter.

After the program has opened itself, it needs to look for the byte sequence that was written to it in the first step, as that indicates the end of the executable and the start of the package. Unfortunately, I haven't found a way to do this that's clean and particularly fast other than simply checking every byte in the file until it is found. Luckily, it only needs to be done once at the start of the program.

The following function looks for the byte sequence and returns an offset relative to the start of the file of the 8 bytes after the sequence, which is the start of the index, since the byte sequence was written as a 64-bit integer.

unsigned int find_byte_sequence(const char* file, unsigned long long sequence) {
    FILE* file = fopen(file, "r");
    fseek(file, 0, SEEK_END);
    int file_size = ftell(file);
    for (int i = file_size - 1; i >= 0; i--) {
        unsigned long long u64;
        fseek(file, i, SEEK_SET);
        fread(&u64, sizeof(u64), 1, file);
        if (u64 == sequence) {
            return i + sizeof(u64);
    return 0;

After the byte offset of the package is known, separate files can be read in. As with the packing, error checking has been omitted, but you absolutely want to add it in. Note the use of goto in the following function.

void load_resource(const char* filename, unsigned char** buffer,
        unsigned int* size, unsigned int sequence_offset) {
    unsigned int filename_hash = elf_hash(filename);
    FILE* exec_file = fopen(get_exec_name(), "r");
    fseek(exec_file, sequence_offset, SEEK_SET);
    unsigned int index_size;
    unsigned int index_size_size = sizeof(unsigned int);
    fread(&index_size, sizeof(index_size), 1, exec_file);
    unsigned int index_element_size = sizeof(unsigned int) * 3;
    unsigned int read_offset, read_size;
    for (unsigned int i = 0; i < index_size; i += index_element_size) {
        unsigned int hash, offset, size;
        fread(&hash, sizeof(hash), 1, exec_file);
        fread(&offset, sizeof(offset), 1, exec_file);
        fread(&size, sizeof(size), 1, exec_file);
        if (hash == filename_hash) {
            read_offset = index_size_size + index_size + sequence_offset + offset;
            read_size = size;
            goto read;
    /* The file was not found in the index */
    *buffer = NULL;
    *size = 0;
    /* The file was found, read the data at it's offset */
    *buffer = malloc(read_size);
    *size = read_size;
    fseek(exec_file, read_offset, SEEK_SET);
    fread(*buffer, read_size, 1, exec_file);

It's a good idea to wrap this function in a preprocessor block so that it will only load from the package in release builds, and instead load from separate files in debug builds.

Using version control never hurts.

(1 edit)

Likely related to this: 

Even so, lacks more information.

Two google searches is all it takes.

In case you don't know how to use Google:

(3 edits)

To ensure old computers can't run it:

  • Turn off any kind of culling and add a bunch of random objects out of view
  • Overuse try/catch blocks (web developers will tell you this is good, it isn't)
  • Use Vulkan or DirectX 12, if your engine supports them.
  • If it's still running well, add some random loops somewhere that do nothing. Remember to turn off optimisation on your compiler, otherwise these will be optimised out.
  • You could also use custom allocation and make it randomly set blocks of memory to garbage data to cause random crashes.

To give graphic designers/artists a heart attack:

  • Use comic sans
  • Use colours that buzz against each other
  • Don't use anti-aliasing
  • Draw your art in MS Paint to make sure it isn't transparent.

What language you should learn really depends on your goals.

If your goal is to make a game as quickly as possible, choose a game engine and learn whatever language it uses. If you don't want to use a game engine, you can pick up a language like Python (with Pygame, for example) or Lua and make your game like that.

If you actually want to learn how to program, I'd actually recommend learning C. I know it's not commonly recommended for beginners (due to it being unforgiving at times), but C is a very small language to keep in one's head, and it requires learning how a lot of things that programmers of other languages take for grated work, such as hash tables and dynamic arrays (things that many more modern languages provide as built in features).

About the fact that you're using a Chromebook: if you are willing to learn how to use Linux, you can install Crostini; A virtual machine for Chrome OS which provides a terminal interface as well as a layer for graphical applications. You can install it by going to the settings and scrolling down the menu to the section labelled "Linux" and going through the guided installer. It's pretty slow unless you have a high end Chromebook (and most Chromebooks don't support OpenGL, let alone Vulkan), though, so don't expect to be able to run any kind of 3D game engine - but you can definitely make quite a respectable 2D game.

I usually just scale the model matrix that is used to draw the sprite quad to "resize" sprites.

(1 edit)

*makes a post with literally the word "sus"*

*complains the community isn't that great*


there are two sides to game development.

(1 edit)

There's a list of functions and globals on the main page. You can also take a look at the demos to get an idea of correct usage.

If you have any specific questions you can post them here.

(1 edit)

There seem to be an awful lot of newbies who ask this same question. If you're a complete noob to game development, just choose a well known one; Unity, Unreal or Godot are solid choices because there are lots of resources online. If you're more experienced, just use whatever engine you were using before - unless it has an obvious limitation that will make your game harder to create - don't switch engines unless the current one doesn't do something that you need it to do. If you do need to switch engines, just go with one that's popular - normally they are popular for a reason.

edit: fix spelling should do the trick. Make sure you ain't just blindly copying code, though.

Well, it's not finished yet, but it's certainly getting somewhere!

Here is it's page:

And here is a screenshot (this screenshot is slightly old though, the rendering quality has been improved a little)

I don't think Godot has an Asset Store/Marketplace like Unity and Unreal do. I do believe it has a store of sorts for extensions (correct me if I'm wrong). A good place to find game artwork is and If you need scripts, what I did when I used Godot is browse YouTube tutorials, most of them have a link to the code used in the description, though some like to hide it behind a paywall.

Atom + at least 50 packages, C++, OpenGL and Tiled, sometimes AngelScript. GIMP for pixel art. I do the rest from scratch.

You have to extract it first, then import the images

nah AMD

I didn't have problems with wine, it worked perfect for me on Debian 10...