I have been slowly working on learning video game programming for a while. I learned C# in order to learn the Unity game development platform. Game development platforms provide a lot of code common to different video games, and they provide a graphical user interface for putting together components. Having those tools available makes it easier to program new video games. Since learning C# I have decided to switch which game development platform to use. I decided to learn Godot instead.
Why did I switch? Mainly because of Unity’s corporate behavior. Platforms like Unity and Godot are really useful for independent game developers, and have greatly increased the number of independent games available. Unity’s pricing structure used to be open to that, but they decided to change it in a way that charged small developers more money, apparently just out of greed. There was a major backlash to this, and they walked back the new pricing structure. However, this strikes me as a sign of a corporate culture of greed, and I don’t think that the greed has gone away. Godot, on the other hand, is an open-source game development platform. There is no corporation to have a culture of greed.
Another positive for Godot is the programming language it uses. It can use C#, and I could have used my new C# skills to learn Godot, but it is primarily designed to us GDScript, which is based on Python. I am a big Python fan, and I’ve been programming in Python something like 20 years now. But I don’t regret my time learning C#. For one thing, I enjoy learning. For another thing, anyone who is honest about Python knows it has it’s limitations. I think C# is going to be a viable alternative when I run into those limitations.
While GDScript is inspired by Python, it is not Python. So it was not an insignificant task to get up to speed on the language. Some of the differences were small things, like using null, false, and true instead of None, False, and True (and both languages are case-sensitive, so that capitalization matters). Other things were much more significant, like variables. Variables are very easy and malleable in Python, but in GDScript they need to be declared and they need to be given a type. This wasn’t a huge deal. I’m used to doing this sort of thing in other languages, especially in the C# I recently learned. But I found that the scoping of variable often tripped me up. I’m using to defining a variable for a loop and then using the variable after the loop. If you want to do that in GDScript it takes an extra step.
I think the thing that I never got used to in GDScript is the damn editor. It’s the kind of editor that gives you warnings when it detects problems with your code. Sometimes this is good. Like I said, I was having problems getting used to the scoping of variables in GDScript, and the editor would give me warnings about that. This allowed me to correct things while I was programming, rather than debugging the issues, which would have be harder.
However, the editor will not shut up about conditionals, and it’s driving me nuts. If you’re not a programmer, a conditional is something like:
if condition:
do_something()
Important parts of the syntax (at least in GDScript) are the colon at the end of the first line, and the indentation at the start of the second line. When I’m typing up one these and get to the condition, the editor highlights the line in red and warns you that you need a colon at the end of the line. I know that, give me a chance to type the condition first! Of course, once I finish the condition and type the colon, the red highlight doesn’t go away. It just changes the warning to tell you that you need an indented block of code after the conditional. I know that, too, I just want a second to think out exactly what I want in that indented block. I don’t know, maybe there’s editor settings that would fix this, but I haven’t found them yet.
But using Godot is much more than just coding in GDScript. You are also building game objects in a GUI editor. Then you attach code to these objects so they know what to do in the game. The objects are built with things called nodes. A card in a game might have a node for the card itself, with a node for the image of the card, and a node for the “shape” of the card so Godot can tell when it is touching another card. A figure that is walking around on the screen might have an animation node instead of a static image. These are pretty simple objects. When I built a window to allow the user to change the game settings, that object became much more complicated. And I’ve barely scratched the surface of game programming, so I wouldn’t be surprised if there were much more complicated objects out there. I expect some of the 3D games I see people making with walking figures with arms, legs, feet, and hands are quite complicated.
All the objects you create for your game are gathered in the node tree, with all the nodes arranged with parent-child relationships. This goes back and constrains how you program the game. When you are coding object named foo it may need to affect object named bar. To do that, foo has to be able to find bar. But there could be a ton of nodes out there, and the nodes are often created on the fly while the program runs.
Godot handles this by making it easy to search down the tree, through the current node’s children. Going up the tree is handled by what is called an observer pattern. Nodes in the tree can send signals, and other nodes can “register” with the observer so those signals get delivered to them, and then they can react to those signals, which may carry information. This is something I am somewhat used to from doing GUI programming, where you have to program your GUI objects (buttons, text fields, and so on) to respond to signals that are generated by the user clicking and typing. I’m just not used to sending signals and registering listeners for those signals.
Now, you don’t have to use the signaling system in Godot. There are ways to find your way up the node tree, and then maybe search down from there. But Godot is really designed to work with the signaling system, and a commonly quoted Godot mantra is “call down, signal up.” Based on my experience programming LISP and SAS, I believe it generally best to use languages the way they are designed to be used. So I have been trying to call down and signal up, but it hasn’t quite clicked for me yet.
So, I read through a lot of the documentation on GDScript, did some experimentation with it, and programmed a simple game from a tutorial where you try to dodge bad guys. As I have mentioned before, whenever I learn a new programming language I try to program the game of FreeCell in that language. Usually that is just a text-only version of FreeCell, but now seemed to be the time to program a full graphical version of the game.
However, even a simple FreeCell game seemed more complicated than anything I had done in a while, at least if it is done as a video game. So I wanted a ticket tracking system to help me keep track of all the different things I needed to do. One test of the game may show four different bugs you need to deal with, and you are going to want to keep a record of what you have done trying to solve those bugs. I have used the ticket tracking on GitHub for other big projects, but I find git to be more trouble than it’s worth on a single program project. And I expect to get a lot of shit for that last comment, but I stand by it. Anyway, I looked around for other ticket tracking applications. They all seemed to have one thing in common: they were way more than I needed. So I wrote my own, which I named Aragorn. I mean, where’s the fun in being a hobby programmer if you can’t reinvent the wheel every now and then constantly.
So I wrote a FreeCell game. Maybe not that well, but I made a game you can play. I ran into some problems with it. One, there is a bug I just cannot solve. One thing you can do in the game is double-click on a card. The game will try to guess what you want to do with that card, and animate the move for you. You can drag the card to where you want yourself, but this is a common short cut to speed up solitaire games. However you move cards around, I programmed it so the cards move over the other cards. But sometimes when you double-click, the cards move under the other cards. This looks rather weird, and at the default I have set for the animation speed, it is subtly weird, which makes it look weirder. It seems to be a conflict between z-indexing and y-sorting, but I have not been able to track it down, and none of the solutions to similar bugs I found online are working. I can’t even replicate it in a simpler case, which would be the first step in asking for help online. At this point I’m just tired of beating my head against this bug for a program I’m only doing to try and learn the system.
The other thing is that there is a lot more to do in a video game than in a text only game. I need to write some more animations. I need some sound effects for shuffling decks and dealing cards. I need better art for the cards and the surface you’re playing on. There’s probably something else it needs that I’m not even aware of. So there’s a lot more work to be done on the details of the game. Normally I would probably push through and do those parts, even though this is just a test project. But I’m just so frustrated with the card movement bug that I want to move on.
While I am certainly no master of Godot at this point, I think I understand it well enough to move on to the next phase in my grand plan for learning video game programming. A long time ago I was reading about video game programming, and some famous-at-the-time video game programmer said something like “if you want to learn to program video games, take six classic video games and reprogram them.” I can’t remember who said it, and I can’t find the quote online anywhere. But that idea stuck in my head, and that’s what I’m going to try to do. First, I have an idea for a Breakout clone using Tetris pieces. From there I’m not sure, but stuff inspired by games like Asteroids, Galaga, Frogger, Q*bert, Donkey Kong, Pole Position, and Super Mario Brothers.