A little more on “2D” in Godot

Tom Leys
3 min readOct 16, 2019

--

Had some confusion from a reader in Reddit about what I meant:

The Recall Singularity (my game) renders a flat 2D world using 1x1 3D models which all have their Y set to 0. Basically it’s a very flexible way to do a GridMap. But it looks far better.

Once that is working, you can play around with Y for animation and so on.
- Tom (/u/RecallSingularity)

What I meant can best be summarized with a picture:

Any visible object I click in this scene (floor, conveyors, walls) will have a Y of 0

Y is “up” in Godot. But I want a 2D game. So I don’t want lots of different Y values when manipulating the visible parts of my game (the origin of the meshes created in Blender).

In Blender, my models are obviously 3D. For instance a cube will have 4 vertices which are “up” and 4 which are “down.” Those vertices are going to have different Z values in Blender (z up) and so different Y values in Godot). That’s OK.

However, the origin of the cube in Godot (when you click on it and choose “transform” and look at translation) is going to always have Y = 0. I’m not moving that cube up or down generally. So in blender it is important that I put the model’s “origin” in the middle of the bottom of the model, so all models render at the same vertical position in the game. The same is true for all my tiles — the floors, the walls, conveyors and refineries.

Origin is in the middle, bottom of any tile. Tiles are 1x1 (between -0.5 and +0.5) on X and Y/Z

There are also a number of non-visible nodes such as lights and camera. For the camera I create a node for instance at 0,0,0 which I call “LookAt” and then I create a child camera. This child camera node is positioned above and to one side (I use translation 32,34,32 rotation -35,45,0). I’m using a perspective camera with a narrow FOV (20 degrees) for reasons I’ll go into in a later blog. Then all my UI code can move the “LookAt” on X and Z and ignore Y. All the lights are currently a fixed distance above the Y so I just use a constant for that and adjust X and Z again.

In Godot what I do is have a list of “modules” which all have an X and a Z location which are whole numbers (-1, 0, 1, 2, 3, 4, …). I just position each module with the same X and Z location and set Y to 0. This way the “game” is 2d (because the internal representation of the world is) but I use 3D stuff to render it.

Because using X and Z in my game logic is confusing I rename Z to Y for my 2D logic. This is kind of a little detail you can ignore if you like.

Once you have everything on a 2D Grid but rendered in 3D, you start to realise that some stuff needs Y > 0 so it sits “on top” of something. For instance the cursor, or something to be built, or items on my conveyors all have Y > 0. But it is getting started which is the hardest part.

So you can see that most of the complexity of managing the Y value happens in the godot editor (where 3D is easy to see and understand) and in my scripts I try to use constants for Y — mostly 0.0.

/u/golddotasksquestions/ (who raised this) summarized it thus:

Since Godot does feature both, I think it would be worthwhile to clearly state that you are rendering in 3D objects in the 3D engine, use 3D lights but that you treat positioning as it was all done in the 2D engine, effectively making the 3D Y axis what is Y Offset in the 2D engine.

Thanks for the comment, I appreciate that you so clearly identified what was missing from the previous article.

--

--