CS354R Assignment 1

Ball in Room

Assignment 1: Exploring a Game Engine



Project Description

You will familiarize yourself with the Godot game engine itself, and use C++ bindings via GDExtension by making a small demonstration. This demonstration will show several balls bouncing within a room. The balls must bounce against each other and the walls of the room in a perfect elastic collision. The game objects must have textures and lighting.

Basic Requirements

Your demonstration will contain a minimum of the following objects:

  1. A cubic room made of 6 textured walls.
  2. 3 textured spherical balls moving within the room.
  3. GDExtension scripts and all additional files required for integrating them into Godot that control ball and wall functionality.
Remember that while you can use the Godot editor for composing nodes in scenes, the scripting functionality should be done primarily through GDExtension scripts (the C++ bindings) rather than C# (the in-editor scripting language). For example, if you want to move a ball, you could create a Node3D node containing your ball mesh and collision volume via the editor, then extend the Node3D class in GDExtensions to add movement within the _process() function. While you're working, you might notice some interesting behaviors, such as GDExtension runs in the editor and not just at runtime (because it it designed to extend both runtime functionality and editor functionality). Use this project as a way to explore its features and behaviors.

Room Requirements

You can light the room in simple ways, but the lighting cannot be solely ambient. At minimum, there should be at least one point light, and one directional light. The observer must also be able to see the shape of the ball, and the discontinuities where the room's walls meet, at all times. All objects are presumed opaque and three dimensional. These features can be built in the editor. Use thoughtful scene tree design.

Ball Requirements

The ball will travel in a random direction at a randomly chosen speed. The range of ball velocities is up to you, but try to make it look reasonable.

For the purposes of this assignment, you will not be using physics to update the ball or check for collisions. Instead, on every frame, you will move the ball along its current trajectory. The distance the ball travels is determined by its speed, which can remain constant throughout the demonstration.

You will need to check if the ball has hit a wall or another ball. If a collision occurs, you will adjust the ball's direction such that it bounces off as if in a perfect elastic collision with no loss of energy. Note that this is a geometric computation to update ball direction rather than physically-based, so you will need to find the vector of reflection. This can be done using the following equation, where I is the ball's current direction, N is the normal of the surface at the point of intersection, R is the reflected direction, and I, N, and R are all 3D vectors:
R = I - 2N(N·I)

If two balls or more balls hit each other, you can assume all will bounce in a perfect elastic collision as well, so you may need to calculate more than one ball reflection during the same frame. You can handle corner cases (such as a ball colliding with 2 other balls at the same time) in any way you see fit, so long as it looks reasonable. It's okay to have some "physics" issues in these cases.

Since you cannot use Godot's built-in CharacterBody, you will be recreating this functionality using Area nodes and creating the necessary callbacks in your C++ implementations of the Ball and Wall classes. You will want to check through the Godot API for more information on how to implement this as well as potentially look through the Godot source code to get an understanding of how they implemented it/use it. Look for some additional tips in the "Getting Started" sections.

Extra Credit

The are several opportunities for extra credit in this assignment if you'd like to add the features below, but note that extra credit points will only be available after completing the minimum requirements.

Camera Controls

Allow the user to reposition the camera through keyboard or mouse controls. If you're feeling particularly saucy, try attaching the camera to the ball for a "third person over the shoulder" perspective. You'll get additional credit if it looks nice! This should use GDExtension.

Sound Effects

Add sound effects that are synchronized with the impact of the ball against the walls/other balls. You should have one sound effect for balls colliding with walls, and another sound effect for balls colliding with balls. This can be done through C# scripting.

User Interaction and Interface

Add some sort of user controls and interaction. The player should be able to accumulate "points" when things happen (e.g. blowing up a ball via a mouse click), while the program keeps track of their score. Create a GUI to display this score. This can be done through C# scripting.

Getting Started

For this project, you will want to have the latest stable Godot game engine version source available even if you chose to use the binary on your development machine. The lab machines have the engine built and aliased to "godot" so typing godot into a terminal should successfully launch the application, but mono is not supported as of yet. If you want to build it on your own machines, the guides for building to Linux, Windows, and Mac are all here. You will need Python 3 and SCons 4 to successfully build, and you may need to take additional steps if you'd like to work with an IDE such as Visual Studio or XCode.

I would recommend looking through their documentation on starting in Godot, even though much of this content is intended for working within Godot rather than linking to GDExtensions. You may also want to look through their information on engine development as this explains a little more about how their engine is set up under the hood.

Since we will be working in GDExtensions to bring our own C++ libraries into Godot, you will want to work through this tutorial to build a basic GDExtension. This will involve writing several files beyond the actual scripts that implement ball and wall functionality, but observe how you will need to register class information to build up your GDExtension. You may use the SConstruct file included in this demo for building, or create your own.

Since GDExtension is not well documented, nor are there many tutorials available, you will want to check through the source code quite a bit while working on this assignment. godot-cpp connects GDExtension to the godot engine functionality. Useful folders to look through are gen, include, and src. The bulk of the functionality is still in the godot folder, which contains the source. For the first assignment, focus on the content in scene, and if you're interested, you can look at how the build out the servers in servers, though we won't be modifying those directly.

Build and Programming Caveats

GDExtension was introduced with Godot 4.0, so while Godot 4.1 onward are semi-stable, there are potentially many unexpected issues that will arise as we dive into development. For this reason, be sure to start early if only to leave plenty of time to debug build issues. Below is a list of known issues and programming gotchas (which likely will grow over time)

Godot API Starting Points

Godot nodes that may be useful to you for detecting and responding to collisions are:

  1. Area3D
  2. SphereShape3D
  3. BoxShape3D

You will need to look through the rest of the Godot API for understanding how to use and compose the other necessary pieces of this demonstration, such as the meshes and lights.

Packaging Your Project for the Lab Machines

Please put your project into a private GitLab repository, and add the professor and TA (gitlab accounts will be posted to the Discord). Create a branch called code-freeze within the repository that contains the following:

  1. A README text file that tells the TA exact steps for building the program from what you've turned in. This will likely be the standard build process, but still include it to help the TA efficiently grade your projects.
  2. A Project Report that tells us what functionality you've implemented, any other interesting features of the program (e.g. it's really fast because I did this clever thing), what software it relies on that you didn't write, issues you encountered if there are unresolved problems, and how to use the program once it's built (trivial for the base version of this assignment, but critical for later assignments and any extra credit work). You should also document your code layout and describing the basic implementation of your classes. You can include either code snippets or screenshots of the more interesting features in your code. This will help the TA spot check your implementation in case rebuilding the game is too time-consuming.
  3. A link to video footage (ideally via Youtube or some other easily accessible platform) of your game in action, demonstrating all basic features plus any extra credit features you implemented.
  4. A folder called Assignment1 containing your project and additional libraries. This will include:
    1. The Godot bindings for C++.
    2. The SConstruct file.
    3. A folder called src containing your .cpp and .h files.
    4. A folder called Project containing your Godot project and associated files.
Submit a link to your repo via Canvas.
Last modified: 10/01/24 by Sarah Abraham theshark@cs.utexas.edu