|
Assignment 1: Exploring a Game Engine |
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.
Your demonstration will contain a minimum of the following objects:
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.
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.
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.
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.
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.
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.
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.
Godot nodes that may be useful to you for detecting and responding to collisions are:
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.
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: