Posted 2018-02-04

After sharing my previous post on the GameDev Mastodon instance, I had a few people reply to me, giving advice along the lines of "pick one engine/framework to start with and go with that option until I encounter a progress-blocking roadblock". This seems much more sensible than trying out every framework or engine I have the slightest interest in until I find something that feels perfect to me. The time I spent shopping around could be instead spent by progressing further with a single option. Since Godot 3 was at the top of my list, that is the option I'm going with.

Getting Godot 3 to build with C# support on Arch Linux proved difficult. I had an issue where Godot would crash upon trying to attach a C# script to a Node. This was solved by making sure GodotSharpTools.dll was copied into the same folder as the Godot binary - /usr/bin in my case. Regardless, a package has appeared on the Arch User Repository (AUR) called godot-mono-bin that makes installing Godot 3 Mono much more straight forward.

The first two tasks on my list were to create & render a small test level, as well as creating and rendering the player character. With Godot, this was pretty easy to accomplish. I'm using the godot-tiled-importer addon to import maps created with the fantastic map editing tool Tiled.

Creating our test level in Tiled
Creating our test level in Tiled

After moving our tilemap to our Godot project folder, it's automatically imported! A few things I ran into during this process:

Select Import(1), then Presets(2) followed by Pixel Art(3)
Select Import(1), then Presets(2) followed by Pixel Art(3)

Importing the tilemap just worked. It was pretty magical! I know Godot 3 has an improved in-engine Tilemap editor but at this point, I'm more comfortable with Tiled. Also, the way you have to slice up tilesets & assign them to Nodes in Godot is very slow and time-consuming.

For our player character, we're going to start with a 32x32 pixel sprite quickly made in GIMP. I wanted to take advantage of the "SpawnLocation" object I created in my Tiled map - this is where I wanted to create & place the player character. Since Godot's C# support is so now & not all the documentation has C# examples, it was a little tricky to translate the GDScript methods to C#. I'm not sure if the way I'm doing it represents any "best practice" but it worked for me.

In the _Ready() method of our test level:

public class Test : Node
    public override void _Ready()
        // instantiate player
        var packedPlayerScene = 
        var player = (Player)packedPlayerScene.Instance();

        // get map spawn point
        var spawnPoint = (StaticBody2D)GetNode("TestMap/Objects/SpawnPoint");
        var spawnPos = spawnPoint.GlobalPosition;
        player.Position = spawnPos;

The first step is to load the scene containing our player - just using new Player() to create our Player node doesn't seem to work1 by itself. This ~PackedScene~ object can be used to create an instance of our player which can then be added as a child node to the Node containing the currently-running script.

A "SpawnPoint" was defined in the Tiled map. In order to get the Godot representation of this object, GetNode() is once again used to reach into the ~TestMap~ instance node (which was attached to the Test scene manually by dragging & dropping in the editor) to get a reference to the desired object. We care about the GlobalPosition over Position in this case since we've manually positioned the camera and want the position of this object relative to the origin of the scene, not the origin of the tilemap itself. Once the camera is set to follow the player, this might change. Finally, the player's position is set to be the spawn position. With that, we have our final result:

Our test level with our beautiful player character
Our test level with our beautiful player character

The player character is successfully spawned at our "SpawnPoint" defined in Tiled! I think the camera zoom is a bit off at the moment as well. The first two steps - render a world & our player - have successfully been done! Next it's time to add some movement, camera adjustment and and world collision! Exciting!!!

  1. This would be nice. As well as the new jQuery-like ~GetNode()~ syntax in C# (e.g.: ~$NodeName~ = ~GetNode("NodeName")~). [return]