12 Developing a Community Nanogame
Michael Alexsander edited this page 2021-11-20 12:14:28 -03:00

Developing a Community Nanogame

After having some good time playing Librerama's nanogames, you may start to think: "Hey! I wish I could make some as well!"

Well, good news, you can! Thanks to Librerama being built using the Godot Engine, which is capable of loading external data package (".pck") files at runtime, one just needs to create a properly configured Godot project and export a ".pck" file of it for the game to play it. This guide will show you how!

Note: This tutorial is not intended to teach how to use the Godot Engine, and such, assumes you already have decent knowledge before going forward. If you don't have any experience with it, it's recommended to read Godot's documentation and learn its basics first.

Setting up the Project

First of all, you need to download the Nanogame Template, this repository contains a Godot project that has been tailored to make nanogames, including the basic files, as well as debugger to help test nanogames.

Do not change the file structure, due to how Godot loads ".pck" files and how dependency paths are store within resources, the file locations must be placed at those locations. The project's settings should also not be changed.

Open the project using a stable version of the Godot Engine, and open the scene "main.tscn" found inside the "community_nanogames/insert_uuid_code_here" path. This scene, as the name implies, is the main scene of your nanogame, and the one opened when loaded by Librerama. Everything that your nanogame should do needs to be in here.

The Main Script

The root of the main scene contains the the main script ("main.gd"), you will find that it has 1 signal and 2 methods:

  • Signal ended: When emitted by your nanogame, it tells Librerama that the player has achieved the end state of it, also telling if they were successful or not, depending if the has_won argument is true/false.

    It should be used when the player wins/loses the nanogame, emitting the signal and giving the argument that reflects this. Note that if the nanogame is of type "Survival", it will not be necessary to emit it when winning, as it's done automatically.

  • Method nanogame_prepare(): This method is called when the nanogame's main scene has just been instantiated, giving two pieces of information: difficulty, that tells the current difficulty level the player is in (1 to 3). And debug_code, that tells what is the current debugging code that was set in the Nanogame Debugger (more on that later).

    It should be used to tell the nanogame how to act depending on the arguments given, and maybe storing their values if necessary.

  • Method nanogame_start(): This method is called when the kickoff screen (the one that shows the player the nanogame's input and its kickoff) has finished, and the player is given actual control over the nanogame.

    It should be used if the nanogame has any components that should only activate when the player has full control, for example, enemy spawn.

It's important to know that with the exception of nanogame_start() all the other elements must be present in the script, or otherwise, the game will refuse to play the nanogame.

The Metadata

You will also find another file within the template named "nanogame.json". This file contains the nanogame's metadata, those being the following:

  • name: The nanogame's name.

  • kickoff: The message that is shown in the kickoff screen, giving a basic command as a hint. They're written as all upper letters and ending with an exclamation point. For example: "ATTACK!", "HIT!", "DODGE!"

  • description: The nanogame's description.

  • author: The nanogame's author (that's you! 😉).

  • input: The nanogame's input type. This will be the way that your nanogame will be played, being the following:

    • NAVIGATION: Controlled by pressing the direction keys.
    • ACTION: Controlled by the action key ("Enter"/"Space" on keyboard).
    • NAVIGATION_ACTION: Controlled by both direction and action keys.
    • DRAG_DROP: Controlled by touching the screen on touch-devices, the mouse on desktop, or the joystick when using a joypad.
  • inputModifier: If Librerama is being played in a touch-device, and the nanogame's input type has navigation, a modifier can be set to show only the relevant controls, those modifiers being:

    • NONE: No modifier is set.
    • HORIZONTAL: Only the left and right navigation keys are used.
    • VERTICAL: Only the up and down navigation keys are used.
  • timer: The timer type of the nanogame. Those being:

    • OBJECTIVE: If player fails to achieve the winning state before the timer reaches 0, the player loses.
    • SURVIVAL: If the player doesn't achieve a fail state before the timer reaches 0, the player wins.
  • tags: The nanogame's tags. They help the player search for specific nanogames, and such, should contain what elements and themes are involved with it. It should be set as such: "Car,Explosions,Future,GameJam"

    There's no need to add a tag if the word already appears in the nanogame's name, as the search also takes that into account.

  • licenseCode: The nanogame's overall code license. This is where your set the license of the code you wrote, that should also compatible with the licenses of any third-party code present (in case of copyleft). The available options can be found at the very end of the tutorial.

  • licenseAssets: The nanogame's overall assets license. This is where your set the license of the assets you made, those being things such as images and audio files. The available options can be found at the very end of the tutorial.

  • source: The link as to where to find the nanogame. In case that your nanogame is free software, it should link to its repository.

  • thirdParty: The nanogame's third-party components. This is where all components that were not made by you should be listed. Each piece having that following properties:

    • name: The name of the asset (not as how it's named in your files, but its original name).
    • author: The original author (not you, in this case 😛).
    • name: The third-party's license.
    • source: The link as to where to find it. Once again, the available options can be found at the very end of the tutorial.

    The metadata of the third-parties should be written as follows:

    "thirdParty": [
        {
            "name": "First Example",
            "author": "Alice",
            "license": "CC_BY_SA_4",
            "source": "https://example.org"
        },
        {
            "name": "Second Example",
            "author": "Bob",
            "license": "GPL_3_LATER",
            "source": "https://other_example.org"
        }
    ]
    

Getting Player Input

A nanogame isn't much of a game if one cannot actually play it, but you can't just set its controls to whatever the heck you desire. All nanogames need to follow a specific control set, which depends of what type of input you set in the nanogame's metadata.

The player's input can be get via Godot's is_action_*() set of methods, by checking for the following list of actions already present in the template:

  • "nanogame_action": The action input ("Enter"/"Space" on keyboard).
  • "nanogame_left": The left direction input.
  • "nanogame_right": The right direction input.
  • "nanogame_up": The up direction input.
  • "nanogame_down": The down direction input.

Screen inputs (or the mouse on desktop) can be read by checking events on nodes like Area2D using the overridable method _input_event(). Remember to always check for the mouse, as touch events are automatically translated to it.

You should always stick to listening to those action events, as they insure that your nanogame obeys the current control set, and stays consistent with the others.

Another thing of importance is to only get the player inputs when it's allowed. Times where input should be ignored are the kickoff screen, and the win/lose breaks. It's very easy to avoid such times, by doing your input programming within the overridable _unhandled_input() method, as not only are events only given to it on the allowed times, but events that aren't the same type of your nanogame are ignored. If for some reason this is not possible, remember to only process events after the nanogame_start() method is called, and before emitting the ended signal.

The Icon

The nanogame's icon is the first visual representation of it that the player will see, and as such, should reflect what's your game is about.

The template comes with a placeholder one, named "icon.png", that has the correct dimensions to base your own icon:

  • It must be 128x128 pixels in dimension, no more nor less.
  • It should have 16 pixels of spacing between the borders.

Note that Librerama also accepts a SVG file as an icon. But they still must obey the proper dimensions as naming (in this case, "icon.svg").

Setting Audio Buses

Librerama has options to define the volume level of multiple types of audio: "Master", "Music", and "Effects".

It's important for the audio in your nanogame to also obey those volume levels. Luckily, it's very easy to do so, as the template already comes with the audio buses already created, so it's just a matter of giving the bus property of the AudioStreamPlayer* nodes the correct bus:

  • "Music": The background tune and other types of jingles.
  • "Effects": The general sound effects, such as the ones played when hitting, moving, crashing, etc.

You should not set bus properties directly to "Master". All audio sources should playback to either the other two.

The Nanogame Debugger

An essential part of making not just a nanogame, but also any game at all, is testing and debugging it. The template comes with the Nanogame Debugger, that can be accessed by simply running the project. Once done so, you will be presented with the following screen:

The Nanogame Debugger's elements.

  1. The timer, including the type (orange for OBJECTIVE and green for SURVIVAL), the time left, and a lock button to prevent it from going down.

  2. The current difficulty and speed, which can be changed as well as locked, so winning/losing won't affect them.

  3. The start/stop and pause buttons. Use them to control the active state of the nanogame.

  4. The nanogame selecting area, including the file picker button, the current nanogame's name, and the reload button, useful for when making small changes.

  5. The debug code setter, it can be used to pass a integer value to the nanogame, which can act differently depending on what the value is and if the nanogame is programmed to do so.

  6. The miscellaneous area, which has the reference toggle button, that toggles the visibility references from Librerama's HUD elements (so you can avoid placing important elements below them), and the auto-hide toggle button, which hides the interface when playing a nanogame and when the mouse isn't above it.

To start testing your nanogame, click in the file picker button, which will bring the file dialog, then navigate the directories until you find the "nanogame.json", select it, and if the nanogame doesn't contain errors, it will be ready for testing.

UUID Code

By now, you must already have noticed that your nanogame files are stored in a directory named "insert_uuid_code_here". That's because it's required for this directory to be named using an UUID code, so it doesn't clash with other community nanogames that the player may also have loaded on their device. The are numerous ways of generating them, one being via the web searcher DuckDuckGo, by searching the term "UUID".

It's very important to remind that you should rename the directory using the Godot Engine itself. Otherwise, the engine will complain about not being able to find file dependencies.

Translating Your Nanogame

A tradução de uma peça de mídia é algo que, mesmo sendo negligenciada por muitos, é ainda assim extremamente importante!
Didn't understand a single thing in the previous phrase? Well, that's how players of different languages will feel if your nanogame isn't translated!

Translations are done via ".po" files. Explaining how they function is beyond the scope of this tutorial, as there are plenty of resources online on how to work with them. This is more of a hint that Librerama can make use of them for translations.

The file contents should have the translation of your nanogame's metadata, as well as any text that appears in-game. The files themselves should be stored in a directory named "translations" which should be created inside the UUID directory.

Exporting Your Nanogame

After all is said and done, when your nanogame is finally complete, it's time to export the ".pck" file! Go to the "Export" dialog, click the Android preset, and then click in "Export PCK/Zip", select the place where you want to export it and name it something that ends with the extension ".pck". Don't worry about the Android preset, the package files are cross-platform, and will be able to be loaded in device that runs Librerama.

When the exporting is finished, it's all done! It can just be placed in Librerama's "community_nanogames" directory within the player's user data directory, and the game will be able to pick it right up at the start. Now you can play it by yourself, or even better: share it with others!

License Values

The license values available to be set in the metadata is large, which is why they're being shown at the very end of this tutorial. Here they are: