Project Update #4 – End of CS 462

It’s amazing that this term has flown by so fast. In the span of a few months, our team has gone from having nothing to an “alpha” version of our game. While I’m proud of how much we’ve been able to accomplish, and learn in general, I do want to reflect on the good and bad of our project’s development so far.

Project Reflection

Our game is well over 50% completed.

Considering the few months a small team of 4 has put into learning how to make a game from scratch, I am truly impressed that we’ve been able to reach our current point.

When I suggested Godot for our game engine, I was apprehensive that it would be good for us as new game developers. Unity is the go-to for beginners for its massive support, but Godot appealed so much to me for its open-source nature. I feel Godot has worked out quite nicely for us.

While we’ve run into numerous technical difficulties, the majority stems from a lack of experience.

Towards the beginning of development, we experienced problems setting up our Godot environments so that we could work together. By default, Godot does not have C# support. You have to specifically opt for the C# version when installing it. I advocated for C# support as I’m familiar with the language and preferred that idea to using GDScript, which is Godot’s built-in language.

This turned out to be a bit of a headache for us as we had different versions of .NET installed. We eventually were able to resolve those problems and get on the same page.

While I have used C# a fair bit now, I definitely could’ve gotten used to GDScript instead. GDScript actually has certain advantages over C# that I didn’t realize at first. Looking back, I probably would’ve foregone C# entirely just to save us the few days it took to work through those issues.

Another major thing this project has taught me is that version control can be a nightmare when the entire team is not used to it. I’ve only used version control on solo projects or projects with one other person. This was a complete first for me to be working with a team of 4 and having to maintain a Git repo.

The first half of the term was plagued with many merge conflicts. We would be working on our own features, and when it came time to consolidate, merge conflicts galore. I’ll admit that the first time I dealt with it, I was incredibly frustrated and confused as Git screamed at me with a vague message along the lines of “Cannot merge branches, merge conflict detected.”

That experience taught me that GitHub and GUI tools are vastly inferior to getting deep into the command line to figure out the actual problem. GitHub did not want to tell me what the conflict was, but the CLI pointed me right to it. I’m not one to shy away from the CLI, but I never had a real reason to learn so many git commands until this project. I would 100% recommend learning the Git commands for fixing merge conflicts. It has helped tremendously in recent weeks.

Moving past technical difficulties, I want to touch on how our team has been working together.

I first want to say that I absolutely love how much we all get along and truly help each other. It’s been a common occurrence throughout my life that team projects usually lead to annoying conflicts and headaches trying to get everyone to contribute properly.

That has not been the case at all with our team. There’s been numerous times where someone in our group steps up to get something done. Whether it’s someone being unable to record the presentation and someone else volunteering or Googling to try to figure out someone else’s error, we are always up to help out.

As far as project management goes, I will say that we definitely could’ve been more attentive with getting details figured out earlier.

The first few weeks were mostly technical difficulties and trying to figure out a good workflow. It’s easy to look back knowing what I do now and say we could’ve done more, but I do think there were a few weeks where more progress could’ve been made.

For instance, we didn’t really have our map fully figured out until halfway through the term. While we had a concept for our map in our technical documents from last term, we really only got an ideal setup by talking it out during this term.

I am really proud that we realized the map needed to be finalized ASAP, so we just held a meeting to do that right then and there. We definitely could’ve had that meeting earlier, such as in the first 2 weeks of the term, but it did work out in the end.

Moving Forward onto CS 463!

With CS 462 coming to a close soon, we have only one term left to get everything ready. Most of what we have left to do is the fun, creative work.

There have been a lot of things I’ve learned from this term. Learning a game engine in the span of a few months is not something I ever thought I would do. It’s pretty awesome that I get to use all of this programming knowledge to make something so much larger than what I’ve done before. It’s even better that I get to do it with such an amazing team.

Project Update #3 – Halfway Through CS 462

It’s difficult to believe that we’re already 5 weeks into this term and 4 weeks into development of our project. Progress has been going steady, but we have run into many technical hiccups along the way. Looking back at the technology we decided to use, I’ll share my thoughts on how that’s been working out for us so far.

Our Technology Stack

We’re building our game in the Godot game engine. This was a decision that primarily stems from the open-source nature of Godot. We really wanted to make this project and have that sense of ownership over it. Larger game engines like Unity and Unreal had strings attached that meant we wouldn’t truly have the ability to do anything we wanted with our game.

For programming, I’ve personally been using C# as Godot has that as one of its major options. GDScript is a custom language developed for Godot, which is also available to us when the need arises.

Godot has a built-in code editor, but each of us has external preferences for programming. I use JetBrains Rider for my IDE, as I’m familiar with the entire JetBrains ecosystem. I’m sure some of my team members use Visual Studio instead. The only thing that matters is that it works for the individual to get our project made.

For 3D game assets, aside from what we acquire from 3rd party sources, we’re using Blender for creating 3D models. Blender is another open-source program that aligns with our beliefs, but beyond that, it’s simply a fantastic tool with plenty of support. I’ve had the pleasure of creating assets in Blender for other classes, and it allows us to turn ideas into importable game assets amazingly fast.

For 2D game assets, i.e. textures, we once again each have our own preferences. I stick to GIMP as I use Linux, but any program that lets you create art works. There’s also plenty of 3rd party assets available, so we have tons of options for obtaining the ideal textures.

Last but not least, Git and Github have been our version control tools of choice. We’ve all used them plenty of times by now throughout OSU (and outside of OSU), so it was a no-brainer to choose them.

Godot, Git, Blender, any art program, and any code editor is all we’ve really needed. Godot does the heavy lifting as our game engine, and from there it’s a matter of using other tools to give it the assets it needs. While things have been going relatively smooth, there are some things to mention about quirks we’ve run into.

Godot

I’ll admit that I’m the primary advocate for Godot amongst my team. The go-to for most people looking at game engines is Unity. Unity has always been the king of indie game development, with countless tutorials and free assets at your disposal.

What drove me away from Unity was the debacle a few years back with them demonstrating how they can become heavy-handed at any moment. I knew that I wanted to stick to open-source and maintaining true ownership over what we make. While exciting at first, we have dealt with strange hangups throughout development.

Looking back, many of them were indeed caused by our lack of experience. When we were trying to work through them, it was a lot easier to put the blame on Godot. I believe this boils down to Godot simply not feeling premium coming from the open-source community as opposed to a large company like Unity Technologies or Epic Games.

That’s not a knock at Godot as I still love FOSS, but it did mean that we would need to figure out a lot more on our own, which adds to the already steep learning curve of using an entire game engine.

The biggest problem we’ve had is that C# integration relies on a weird quirk of Godot to function properly. As the only person using C# thus far, I’ve had to help my teammates troubleshoot when the project wouldn’t compile with my scripts. They were unable to get the project to run, only receiving a vague error about C#.

We found out that Godot only builds the C# project when creating a new C# script for the first time. It turned out that my csproj file was never committed to Git, only my sln file. This left my teammates in a state where they had to create a new C# file and immediately delete it just to get the project built. It was ultimately my fault, but it goes to show that Godot wasn’t going to make it easy to figure out what needed to be done.

Git

The second problem we faced was with Git. Our workflow has been to work on separate branches and then create a PR to have them be merged. This has worked plenty well, with a requirement of another team member’s approval on the PR to ensure it’s being checked.

I ran into a particularly nasty merge issue a few days ago that nearly gave me a headache. GitHub was telling me that my branch was perfectly merge-able with main. Once my PR was approved, it then told me that there was a merge conflict.

It took me about 2 hours just to get past that merge conflict. I was so stumped on what the problem could be as it was claiming a debug statement’s removal was causing a conflict with the main branch. While I still don’t understand how it was conflicting, I was able to resolve it through a bit of messing around with the commits on my branch.

After that hassle, I greatly appreciate the CLI for Git. I can’t even begin to imagine how I would resolve that if I didn’t know a bit about the command line tools. GitHub was no help to me with a vague “Merge Conflict found” message.

I would 100% recommend you make sure you can avoid the easy tools like a GUI via GitHub, just for annoying cases like these. The last thing you want is to be completely stuck trying to google Git commands you don’t understand to resolve a problem.

Conclusion

Progress has been pretty great! We have a decent prototype of our map, a working player character, and a nice audio system. The most important thing is that we’ve been able AND willing to help each other out. There’s nothing I’ve appreciated more than feeling comfortable talking about problems I run into, and knowing that my teammates feel the same.

Our technology stack is just the tools by which our project can exist. The real test is if our team can continue to leverage these tools into creating something amazing.

Kicking Off CS462!

Post-Break Excitement

Although Winter break was exciting enough on its own for me, our team is now getting into something real exciting with the development part of the capstone.

After we were assigned to our project, we only had a vague idea of what we wanted the end result to be. It’s super easy to get caught up in 1000 different ideas, only to realize that most of them aren’t realistic given our skills and available time.

I believe for all of us, this is the first full game we’ll be making. That’s equally daunting and exciting to me, as someone that’s always wanted to get into game development. This is a lot more formal compared to random programming projects where I could go at my own pace with no deadlines.

Despite the formalism of the capstone, I’m happy that I have a reason to be so motivated. Aside from the obvious benefits for a resume, I’m passionate about creating something I’m proud of. This is also a great opportunity to really get into a groove of working with a team and collaborative development.

We spent months planning how we’re going to create a great game. I expect there will be hiccups along the way, but I know my team can overcome them.

The first 1/3 of the capstone is down. It’s finally time to put all of that planning into action.

Clean Code and Code Smells

Now that we’re starting development, we need to think about how to keep our code “clean.” Regarding what exactly “clean code” means, I read the first chapter of Clean Code: A Handbook of Agile Software Craftsmanship by Robert “Uncle Bob” Martin.

Aside from some nice, broad ideas on what makes code “clean,” I appreciated reading this for its many viewpoints. Chapter 1 offers perspectives from many well-versed programmers on what it means to write clean code.

The main takeaway for me is that clean code is designed to be purely logical and immediately understandable. This means that no matter who reads that code, whether it’s future you, a newer programmer, or a seasoned veteran, it takes virtually no time to recognize what it’s purpose is.

A bad habit of mine that I’ve picked up on is to go for language-specific, “elegant” solutions when the opportunity presents itself. While this isn’t always necessarily a bad thing, it definitely detracts from the cleanness of code to go overboard with a certain quirk of Python.

A particular example of this where I tend to go overboard is with list comprehensions. Although it is a nice feature to have, it’s also easy to let it become an unreadable mess with bad variable names and odd formatting. I came across this example from my own code on a personal project from awhile ago:

image_layers = [
    i
    for i in [
        self._visual_background_color_image,
        self._visual_background_image,
        self._visual_text_image,
    ]
    if i is not None
]

This is meant to be used to layer a few different elements into a single image, but it’s really not clear how it works from this alone. Refactoring this resulted in:

image_layers = [
    self._visual_background_color_image,
    self._visual_background_image,
    self._visual_text_image,
]

image_layers = [layer for layer in image_layers if layer is not None]

Although functionally the same, I find the refactored version to be much easier to read at first glance. This also has the benefit of avoiding nesting an entire list within a list comprehension, meaning adding extra layers won’t affect any understanding of what the list comprehension does.

In the future, and particularly for our capstone project, I’d love to stay aware of how readable my code is to help my teammates and future self out.

Moving onto code smells, this essentially refers to common problems that can show up while writing code. As with most things that smell bad, it’s typically something you want to avoid to begin with, but do something about when you come across it.

My favorite resource for learning about these is https://refactoring.guru/refactoring/smells, but I also read chapter 3 of Refactoring: Improving the Design of Existing Code by Martin Fowler.

There are many, many different code smells with their own causes and solutions. You can’t truly predict when they’ll appear, but you can take care to avoid the more egregious ones.

Refactoring Guru mentions 5 different types of code smells: Bloaters, Object-Orientation Abusers, Change Preventers, Dispensables, and Couplers. Regardless of the type, they all slow down programming at the end of the day.

A particular code smell that I believe I’ll need to watch out for in this project is too many comments: https://refactoring.guru/smells/comments.

I tend to be someone that almost never comments in code intended for myself, but go overboard in code intended for other people. I definitely need to find a balance of letting my code speak for itself, but highlighting the things that need explanation.

In the capstone project, I’m going to do my best to stick to obvious naming schemes and logically-readable code instead of comments. Comments should be reserved for those complicated pieces of code that can’t be made any clearer, such as heavy math and algorithms.

It is important to note that this does not include documentation, as we should be able to know what a method is meant for!

Conclusion

With Winter break and the Fall term gone, I know these next two terms are going to go by faster than I can blink.

I’m excited to see where our project ends up, but I’m going to do my best to savor the process along the way.