CUGL Engine
The Cornell University Game Library (CUGL) is a custom engine built on top of the cross platform engine SDL. If are familar with SDL, you will know that it is not really a game library. It is more of a hardware abstraction layer to make cross-platform development easier. The difference is similar to that between LibGDX and LWJGL. Like LibGDX, the purpose of CUGL is to make SDL development substantially easier for a student.
It may seem sketchy using our own engine when there are so many other competitors out there (though really, there aren’t). However, we have had two viral successes built on top of this engine in the five years that we have used it. We are now in our seventh year, and have add a lot of tools to make it easier for programmers and designers alike.
Table of Contents
- Download
- History
- Documentation
- The Build System
- Apple Development
- Android Development
- SteamOS Development
- Windows Development
- Third-Party Libraries
Click on the link above to download the latest version of the engine. This engine is provided as source code. There are (almost) no pre-built libraries of any form. This is to maximize cross-platform support, as any pre-prebuilt library would have to have a separate version for each platform. Indeed, Apple alone would require four versions of any given library.
Another advantage of providing you with the sources is that you are welcome to modify the game engine as you wish. Indeed, if you create classes that you feel are of general purpose, you are welcome to contribute them to the engine for future semesters.
One more interesting feature about CUGL is that the engine is both a C++ library and a python program. You use python to link the engine into your game project. For example, if you download HelloCUGL from the demos page, you would link the engine by typing
python cugl HelloCUGL
More details about how this works can be found under the section about the build system.
Additional Features
This engine is feature-locked for the semester. While there are some new features we have been working on that we wanted to integrate this semester (most notably Javascript integration), we ran out of time to properly test them. As we do not like supporting untested software, we did not include them.
The biggest news this year is the networking is officially back. After struggling for a long time to find a suitable network layer, we discovered one at the very last minute last year. We included it as an unofficial release for students that wanted to do a networked game. It worked out so well that it is part of the official release this year.
Bug Fixes
While the engine is feature-locked for the semester, that does not mean it is
perfect. Every semester students find (minor) bugs and we have to post
mid-semester bug fixes. If you think you have found a bug, please post it to
Ed Discussions with [BUG]
in the post
title. If we are able to fix the bug, a patch will be posted in the link above.
History
For years we let students use whatever engine they wanted for this course. It was a support nightmare. In addition, we had to make sure to break people up into Android-only groups and iOS-only groups, which made team formation difficult. We desperately needed a cross-platform solution for this course. We also needed one in which gave students access to the internals for study and experimentation. The latter criteria unfortunately eliminates both Unity and Godot. While Godot is not as closed as Unity is, it is not designed to make working with its internals very easy.
For several years we used Cocos. The results were okay, and the design has several good ideas. However, the compile times were long (as long as an hour on some Windows machines) and the file sizes were huge (over 2 GB). In addition, there were a lot of legacy issues that prevented students from using modern C++ features like smart pointers.
Looking at the projects that students wrote for Cocos, we noticed that they all used a very small core group of classes. Therefore, we decided to do something radical. We made our own game engine, which we call CUGL from just these core classes. If you need anything else, you will need to write it yourself.
While this may seem sketchy, this is the seventh year we are using this engine. We have had two massive viral successes breakout in this time. This engine is more than enough for the games that you want to develop in this course. In addition, creating our own engine means that we have opporunities for many MEng projects. If you are interested in an MEng project for CUGL (which must be distinct from your game), talk to the instructor.
Documentation
The engine consists of three parts: the SDL base layer, Box2D physics, and the CUGL C++ classes. In addition, you have full access to OpenGL on all platforms. While many of you are familiar with OpenGL from CS 4620, you may not have ever used it in C/C++ before. Therefore we have some helpful reading below to help you adjust.
CUGL
The CUGL documentation is a bit sparse, though with the code samples, it has been historically enough for most students. It is currently broken up into two parts.
CUGL Class API
The CUGL C++ classes are the primary classes that you will use to write your game. These classes, plus a little Box2D and maybe some OpenGL should be enough for your to develop any kind of (2D mobile) game you want this semester. The API above is a Javadoc-style web page generated from the class headers.
We do have a few special namespaces (think Java packages), but most classes are
in the top level cugl
namespace. You should quickly peruse all of these
classes to see which ones might be relevant. We highly recommend that all
programmers familiarize themselves with the math class Poly2,
as it is the workhorse of all 2d games.
The most important thing to understand about CUGL is how classes are allocated.
CUGL makes heavy usage of smart-pointers to make memory management easier. We
also have a factory pattern for these smart pointers. You should almost never
use the keyword new
in your code (and only if you know what you are doing).
You should make use of the static allocators to create smart pointers. For
example, instead of
SpriteBatch* batch = new SpriteBatch();
you should write
std::shared_ptr<SpriteBatch> batch = SpriteBatch::alloc();
You should look at the CUGL source code to see how the classes are designed. You will notice that we have taken code that typically goes in a constructor and split it across three different methods.
- A single default constructor, which initializes fields to default values.
- One or more initializers, which initialize the class from user parameters.
- One or more allocators, which use an initializer to make a smart pointer.
The exception to this rule are classes that are intended to go on the stack,
like the math classes Vec2
and Size
. Since those are never to combined
with new
, they do everything in the constructor and have multiple constructor
definitions.
We will see the reason for this architecture later in class. Even though it may violate some C++ style guides on the Internet, it really is the cleanest way to organize a resource-heavy architecture like a game engine.
CUGL Scenegraph Tutorial
CUGL replies upon a scene graph for 2d graphics. We have a tutorial above (created by a former TA) explaining how this scene graph works. In particular, there are tools for your designers to generate scene graphs without doing any coding at all. This allows you to wire-frame up your user interfaces.
This tutorial was written three years ago, and there have been quite a few changes
since then (not the least of which is the movement to the scene2
namespace).
We think we have updated it properly, though some of the hyperlinks to the API
may be dead. Let us know if the documentation does not conform to the latest API.
Box2d
Many of you have experience with Box2d from the introductory course. As you saw
in that course, the document is spread across several places. However, if your
game does not use a lot of physics, you may not need to use these. Furthermore,
physics2
namespace in CUGL is a wrapper around Box2D and provides some basic
functionality, at the level of the CS 3152 physics lab.
Box2d Manual
The Box2d manual is essentially a non-hyperlinked version of the class API. You will notice that it is fairly old. That is because Erin Catto has declared Box2d “done” and has not updated it since 2013. The fact that no one has needed it to be updated since 2013 is a testament to its success.
iForce2d Tutorials
Those of you took the introductory class are familiar with the iForce2d tutorials. The C++ version of Box2d is the native version, so you can follow the tutorials exactly this time. In addition, there is a lot of functionality in the C++ version that was not available in the Java version.
SDL
The SDL base layer is written in pure C with no C++ features at all. SDL requires manual memory management and cannot use smart pointers. In addition, it uses C-style function pointers instead of C++ closures for callback functions. Programming in SDL is very spartan, to say the least.
SDL API
This API consists of all of the functions and structs (classes without methods) provided by SDL. For the most part you should not need to program in SDL. We have wrapped the most important features into CUGL classes for you. However, there are some platform-specific features that are not part of CUGL, such as the JNI interface for Android devices. If you want to use these, you will need to access SDL directly.
SDL Tutorials
These tutorials are old and little rusty. Even though many of them date to 2014, the SDL engine has made significant progress since then. We are not sure if you will find any of these to be valuable, but we do provide the link for reference.
OpenGL
The key thing to understand about OpenGL programming in CUGL is that there is no one version of OpenGL for all platforms. The desktop platforms support OpenGL 4.x (really OpenGL 3.x), while the mobile platforms support OpenGLES 3.x.
OpenGL API
Technically, CUGL supports whatever version of OpenGL is available on the desktop/laptop. For most Windows computers, this is OpenGL 4.x. However, macOS has deprecated OpenGL (in favor of Metal and Vulkan) and stopped updating OpenGL at 4.1. Therefore, it is not safe to target any feature after OpenGL 4.1.
OpenGLES API
OpenGLES is a essentially a limited version of OpenGL used on iOS and Android. Hence as long as you target OpenGLES, you should be fine and your code will run on all platforms. However there are some exceptions, particularly with the shader languages. OpenGLES requires some extra keywords in the shaders that OpenGL does not. You should talk to the instructor if you really need to get into the details of OpenGL and custom shaders (though we will cover this a bit in lecture).
The Build System
Technically CUGL should be able to support any platform that SDL supports, which is a lot of platforms (including both XBox and the Switch). However, we have added a lot extra libraries and have only tested it on the following platforms: Apple (both macOS and iOS), Android, Windows, and Linux (including SteamOS).
Unfortunately, these platforms are all very different and there is no single build system that properly supports all of them. CMake tries to be universal, but it really isn’t. Its support for iOS is limited and it cannot make Android projects by itself. Even on the desktop platforms that it does support, like macOS and Windows, it is much better to use a real IDE like XCode or Visual Studio for debugging.
In the past this meant that we had to distribute multiple project files – XCode, Visual Studio, and Android Studio – with the engine and every demo project that we posted. The result was a brittle mess. Students would often modify one project file, but not another, meaning that their code only built on one platform. If team members had different computers (macOS vs Windows) this often meant that the entire build broke down.
The lastest version of CUGL solves this problem. Instead of requiring students to configure the IDE settings on their own, we do this automatically. In addition to being a C++ library, CUGL is also a python application. Using python, we can automatically generate all of the various project files (XCode, Visual Studio, Android Studio, etc.) for you. These files will be configured correctly and there will be nothing left to do. You only need to focus on creating code and assets for your game.
Configuring Python
In order to use the build system, you will need a version of python on your computer. If you took 1110 here at Cornell, you are already good to go. Otherwise, any version of python will do. However, you will need to use pip to install three additional packages.
The first is necessary to read the configuration files. The second is used to generate the platform-specific icons. The third is necessary for modifying XCode projects.
If you do not know how to use pip to install a python package, please reach out to a TA for help.
Getting Started
To show you how the build system works, you should download the HelloCUGL
project from the demos page. Place cugl
and HelloCUGL
in the same folder, navigate to that folder, and type
python cugl HelloCUGL
This will create a folder inside of HelloCUGL
called build
. Inside build
are project folders for each of the supported platforms: Apple, Android,
Windows, and CMake (Linux/SteamOS). These projects link together HelloCUGL
and CUGL. To use any of these projects read the
platform-specific instructions
below.
This link depends on CUGL remaining where it was at the time you ran python. If
you move or rename the cugl
folder, the projects will break and you will
need to regenerate them. With that said, there was no reason you had to put
cugl
outside of HelloCUGL
. You could also have put it inside of
HelloCUGL
. In that case you would have navigated to HelloCUGL
and typed
python cugl .
The choice is up to you. By putting it outside of HelloCUGL
, you can have one
version of CUGL that you use for multiple projects/demos. This also allows you
to keep CUGL outside of your GitHub repository, if you do not want all those
files there.
Understanding a CUGL Project
The project HelloCUGL
has two folders – one for the source and another for
the game assets. It also has a file called config.yml
. This file is what the
build system uses to create the project files. You should keep this file up to
date at all times.
This is a YAML file. A YAML file is a lot like a JSON file except with a lot less curly braces. In addition, quotes are often implicit and therefore can be dropped when the meaning is clear. YAMLs are not as good for heavily nested information like a scene graph (which is why CUGL uses JSON), but they are great for relatively flat data like a configuration file.
The configuration file is composed of the following keys.
name (REQUIRED)
The name
is the display name of your application. It can be as long as you
want, and even have spaces in it. Note that if it is too long, most mobile
devices will truncate it.
short (optional)
The value short
is the short name of your project, and is used to identify
it in most of the project files. The short name cannot have any spaces and
cannot be more than 32 characters. By default, the short name of your project
is the name
converted to snake case
and truncated as necessary.
appid (REQUIRED)
The appid
is a period-separated sequence of identifiers, which looks exactly
like a Java package. The appid is how mobile devices (iOS and Android) tell
applications apart from each other. A phone can have two applications with the
same name as long as they have the same appid. But it cannot have two
applications with the same appid even if the names are different. In the past
students have submitted their final projects with same as HelloCUGL, causing
serious problems (with equally serious point deductions).
suffix (optional)
The suffix
is an additional suffix to apply to the appid
. The problem with
appid values is that they must be globally unique. If the professor creates
a demo project and uploads it to his iOS developer account, you cannot use the
appid for that project anymore. The solution is to add a random suffix so that
each development team is guaranteed to have a unique appid.
If this value is a string, it will be added to the appid when the project files
are built. However, if this value is true
, then the first time the CUGL
python application is run, it will generate a random suffix. This value will
then be written into the config.yml
so that you can share it with the rest
of your team going forward, or even commit the suffix to your GitHub repository.
build (optional)
The value build
is the location of the build folder, relative to the
config.yml
file. By default it is a folder called build
. This folder will
be deleted an regenerated every time you run the CUGL python application.
icon (optional)
The entry icon
is used to generate the application icon. The icon should be
created as a 1024x1024 PNG file. The python application will convert this to
the appropriate format for each platform. In most cases, the value of icon
should be the location of this file, relative to the config.yml
file.
With that said, there are some important restrictions on icons that may cause
you to want to have more control over your icon image. Mobile devices prohibit
any transparency in the icon image, while transparency is okay for desktop
platforms like macOS and Windows. Similarly, icons have rounded corners by
default on mobile devices, but not necessarily on desktop platforms. For that
reason, the icon
can be broken up into several subentries.
image
: The location of the PNG file, relative to theconfig.yml
.background
: The background color for transparent regions, specified as a stringtransparent
: Whether to allow transparency to remain on desktop platformsrounded
: Whether to cut the corners of the icon to make them look rounded
Look at the custom icons for some of the demos projects to see how to utilize these features.
orientation (optional)
The orientation
is the default/starting orientation of the game on mobile
devices. By default this value is landscape
, maximizing the horizontal width
of your game. The following values are all accepted.
portrait
: Fixed in portrait mode with the home “button” at the bottomlandscape
: Fixed in landscape mode with the home “button” on the rightportrait-flipped
: Fixed in portrait mode with the home “button” at the toplandscape-flipped
: Fixed in landscape mode with the home “button” on the leftportrait-either
: Able to rotate betweenportrait
andportrait-flipped
landscape-either
: Able to rotate betweenlandscape
andlandscape-flipped
multidirectional
: Able to rotate betweenportrait
andlandscape
omnidirectional
: Able to rotate between any of the first four orientations
We highly recommend against multidirectional
and omindirectional
. OpenGL
contexts do not like being resized like that. It is often better to fix your
orientation and use the device orientation (e.g. how the device is held) to
change the graphics.
assets (optional)
The value build
is the location of the assets folder, relative to the
config.yml
file. The assets folder contains all game assets like images,
sounds, and fonts. Unlike the sources, it is not necessary to list assets
individually. Simply specifying the top-level build folder is enough.
source (REQUIRED)
The source
entry is a list of values each indicated with a dash (-
), which
is how YAML specifies lists. The values are the source files for your game.
Wildcards are permitted as an alternative to listing each file individually.
Source code files can and should include headers (.h
files) that you
regularly modify.
includes (optional)
The includes
entry is a list of additional directories containing header
files necessary for your project. This should only be used for includes for
external libraries, and not for header files for your core classes.
targets (REQUIRED)
The targets
entry is the list of all platforms that your game supports.
Without this value, nothing will be put in the build folder. In addition, the
build folder will only be populated with projects for the specified targets.
The following are all valid options.
android
: To create an Android Studio projectapple
: To create an XCode projectwindows
: To create a Visual Studio projectcmake
: To create a CMake source folder for Linux
Apple Development
To develop for macOS and iOS, you must have at least XCode 15. You do not need upgrade to Sonoma (though we recommend it), but you should be running Ventura at the very least. That is because iOS 17 requires XCode 15. In general, every time you upgrade your version of iOS, you must upgrade your version of XCode.
Currently, it is only possible to develop for iOS on a Macintosh. While Windows is pushing some cross-platform tools for iOS, they are not currently compatible with our engine (this is a future MEng project). However, you really only need one MacOS machine on your team to deploy to a device. The cross-platform tools mean that everyone else on your team can develop and test on Windows using Visual Studio.
Working with XCode
Both macOS and iOS will be combined in a single XCode project. When you open the project, it will look like the image below. The important thing to pay attention to are the Build Targets. There are main two targets available: HelloWorld (Mac) and HelloWorld (iOS). You select the current build target from the drop-down menu in the top left, next to the stop button.
When you select a build target, you also choose a device. For Mac it will always be your computer. For iOS you will be given a choice of a simulator or any device currently connected to your computer. That device must be approved for development. You can approve it by choosing Window > Devices. In addition, you must set the build to have proper code signing.
By default, projects are signed as Personal Team. This allows you to build for a device without getting an iOS developer account. There is a limit to the number of apps you can load per month using Personal Team signing, but unless you are a TA, this should not be an issue.
If you want to put your game on the App Store, you will need to properly sign your application. This requires joining the iOS Developer Program, which costs $100 per year.
Android Development
Android devices can be developed on either macOS or Windows. That is because Android Studio is a cross-platform IDE that runs on all devices. With that said, you should not make Android Studio your primary IDE, as it is not good for developing C++ applications. Debugging for Android can be very difficult, as you will not have much more than logging tools (e.g. print statements).
We recommend that you use your desktop platform as a back-up development environment to help with debugging. So if you develop on a Mac, use the Mac desktop build for testing. If you develop on Windows, use the Windows desktop build for testing. This will allow you to use a proper IDE (XCode or Visual Studio) to trace executions and search for memory issues. This is imperfect, as you will not be able to test touch screens or accelerometers on the desktop, but it gives you something to fall back on.
Supposedly, there is some support for Android applications in Visual Studio. Furthermore, Microsoft claims to have a really good simulator. We have not gotten that integration to work properly, however. If you are able to get it to work, let us know.
Setting Up Android Studio
Android Studio is a Google fork of the IntelliJ IDE that several of you used in 3152. However, you will not be using this tool to write code in Java. Instead you will be using the NDK to do C++ development on Android.
Once you download Android Studio, you will need to get the both the correct Android SDK and the Android NDK. The former is necessary to build Android apps in general, while the latter is necessary to develop in C++. You will get these in Android Studio using the SDK Manager
Before you do anything else, you need to access the SDK Manager. Choose Configure > SDK Manager. There are two panels that you need to update. You need SDK Platforms to make sure that you support the right Android OS. You need SDK Tools to integrate the NDK. Our settings are shown below. You probably do not need all of those SDKs; we have just been developing for Android for a while. But you should have at least the SDK for Pie, as that is necessary to support notched phones like the Pixel.
Figure 3: Supported SDK Platforms
Figure 4: SDK Tools Including the NDK
Warning: There is an important issue to be aware of. When Android compiles, it passes the absolute (not the relative) path to each file to the compiler. However the Windows compiler cannot handle path names longer than 260 characters. If your code is nested inside several folders on your computer, this could be a problem. To solve this problem, you will need to enable long paths on your computer.
Configuring the Emulators
Games written in CUGL will have no problem running on modern (released in the past six years) Android devices. But if you want to test on the emulators, you will run into some challenges. By default, the Android emulator uses OpenGLES 2.0. CUGL does not support OpenGLES 2.0. It requires OpenGLES 3.0. Again, all modern devices support OpenGLES 3.0.
Fortunately, this is something that can be solved with a setting change. You need to start an Android emulator (without running a CUGL project on it). To the right you will notice a menu of options, with a power buttons at the top and three dots at the bottom.
Click on the three dots. That will pull up a menu with a lot of options. Choose Settings at the bottom. Then choose Advanced. Upgrade the OpenGLES to 3.1 and use your native hardware acceleration as shown below.
Figure 6: Emulator OpenGLES Settings
To get these settings to commit, you must perform a hard reboot of the emulator. The emulator is finicky and sometimes you think that you rebooted it and it really just went to sleep. The easiest way to do a hard reboot of the emulator is to reboot your entire machine. Once you do that, the emulator should work.
Running an Android Studio Project
The Android Studio project created by the build system is a folder with several
files in it, one of them called build.gradle
. Again, this should be familiar
to students from 3152 that worked with IntelliJ. Open this folder with Android
Studio to load the project. You will see some status messages about gradle
initializing. But eventually you should see a project like the one shown below.
Figure 7: Opening an Android Studio Project
To compile the project, choose Build > Make Project. It will not look like anything is happening unless you select the Build table in the gradle console. This will let you monitor the state of the build.
Figure 8: Building an Android Project
It is important that you do that, since the build is a long process. First, Android Studio invokes CMake to compile all of the C/C++ source files. Then it compiles the main Java application with links to the C++ classes via JNI. We recommend you go get a drink, as it can take up to 15 minutes the first time you compile an application. That is because the CUGL library is quite involved. In subsequent builds it will only compile the changes, and so it will go much faster.
If there is a problem with the C++ files, Android Studio will pull up the file with the error immediately after compilation fails. However, it is not guaranteed to display all of the issues. It may just show the first one it found. That is why we always recommend that you compile for a desktop release (macOS or Window) to catch minor bugs before you try to launch on Android.
If the compilation succeeds, then you are ready to run the program. Plug your Android device into your computer. You will see it in the dropdown to the left of the run button. Alternatively, you can chose an emulator from this menu as well. When you have selected your device, press the run button.
Figure 9: Selecting an Android Device
Once you do this, you should see “Installing APK” at the bottom of the window. Do not unplug your device until this message disappears and the app launches. Again this can take a while, but nowhere as long as compiling. While you are waiting, you should click on the Logcat tab at the bottom. This is where all of the logging (i.e. print) statements will be displayed. his window is basically the extent of your ability to debug Android. Breakpoints and memory dumps, such as are possible in XCode and Visual Studio, are out of the question.
Figure 10: Android Device Logging
SteamOS Development
SteamOS development is a new feature for 2024. Last year we provided Linux support for the first time. And since SteamOS is just a variation of Linux, it was a simple adjustment to support that platform as well. Indeed, the instructions for SteamOS and Linux are the same, except for the last step.
SteamOS is the platform you will target if you want to run on the Steam Deck. While Steam can run Windows apps via WINE, it is always better to target the Steam Deck natively. An important caveat to SteamOS development is that, like iOS development, someone on your team must have a machine capable of deploying to a Steam Deck. That means an Intel/AMD x86 machine runing Linux. Modern Macs no longer have Intel processors and so cannot compile for SteamOS.
The Linux distribution for development does not matter. If you are comfortable with Ubuntu, we have confirmed that this works. However, Valve recommends that you develop using Manjaro. That is because the Manjaro interface is exactly the same as what you will see on the Steam Deck running in desktop mode.
Running CMake
Developing for SteamOS requires two steps. The first step is to compile the executable with CMake. You will need to have CMake 3.12 or higher on your computer to compile CUGL applications.
When you use the build system, it will create a cmake
folder for you. However,
if you understand how CMake works, that is not actually the build directory.
That is the configuration directory, which is used to make a build directory.
Take a look at the
CMake tutorial
if you do not understand the difference.
Technically you can put the build directory anywhere you want. However, we have
suggestion. Inside of the cmake
folder is another cmake
folder. It
will make the rest of this process much simpler if you use that folder as
your build directory.
To do this, go into the second cmake
folder and type
cmake ..
This will run CMake on the parent directory (the configuration directory) and put the results in the current folder as the build directory.
Once the build files are completed, you should type
cmake --build .
This will start the build process. When done, the executable will be stored in
the folder called install
. This is to ensure that the executable will be in
the same folder as the game assets, as well as any necessary dynamic libraries.
Building Flatpak
The second step to building for SteamOS is to create a flatpak app. Flatpak is kind of like Docker, in that it allows you to distribute software as a self-contained package with all of the dependencies included. The difference is that Docker is designed for servers, while Flatpak is designed for graphical applications. Valve’s policy is that Flatpak is the preferred means for installing third-party applications on to your Steam Deck.
to create a flatpak app, you will need flatpak
(and flatpak-builder
)
installed in your Linux distribution. These are provided by most package
managers, and it is installed by default in Manjaro Linux. In addition, the
first time that you create a flatpak app, you will need to install the
dependencies. To do that type
flatpak install flathub org.freedesktop.Platform//23.08 org.freedesktop.Sdk//23.08
You only need to do this the first time. Later builds will already have these dependencies in place.
Flatpak is a wrapper around the executable you created with CMake, and not a
new executable. Once this executable is built, look at the flatpak
subdirectory of the configuration directory. You will see a shell script
named build.sh
. You can run this script from the configuration directory
as follows:
flatpak/build.sh
This will create a new subdirectory of this folder named install
. This
directory will contain the following files:
<appid>.flatpak
: A flatpak bundle of with the app id of your game<game>.exe
: A shortcut for launching the game on the Steam Deckinstall.sh
: A script to install the flatpak bundleuninstall.sh
: A script to uninstall the flatpak bundle
You should ZIP up this entire folder an copy it on a USB drive for transfer to your Steam Deck. You may wish to include some cover art for your Steam Library.
Figure 11: The Flatpak Installation Folder
Installing on the Steam Deck
To install your game on the Steam Deck, you will need to change into desktop mode. To do this, press the Steam button on the left of the Steam Deck and navigate to the Power menu. There will be an option Switch to Desktop. Select that.
Desktop mode is just that. You are running a Linux computer. As such you are expected to have a mouse and keyboard. You can use the touchpads on the Steam Deck as a mouse, but you cannot access the virtual keyboard unless you launch Steam while in desktop mode. If you find your self needing to run the terminal, it is probably a good idea to use a proper keyboard connected by a USB-C cable.
While in desktop mode, launch the Dolphin file manager. Connect your USB containing the installation ZIP from the previous step (this may require a USB hub if you have a keyboard connected as well), and copy it on to your steam desk. We recommend making a new folder in your home directory called Games to store it. Unzip the directory.
You will now need to install the game. This will require use of the command
line. Launch Konsole and navigate to the place you
installed the folder with the installation scripts. Depending up on how you
installed these files, the file install.sh
(and uninstall.sh
) may not have
the execution permissions set properly. You should do that first.
Figure 12: Setting Executable Permissions
You should now run the install.sh
script. This will ask for you permission
to install some files. You should say Y
. Once this is complete, run the file
ending in .exe
. This should launch your game.
An advantage with starting the game from the Konsole is that you will see any error messages or trace statements that your application may print out while it is running. You will never see these when you run the application outside of desktop mode. This is ideal for debugging your application. Note, however, that your application will not receive any game controller inputs unless you have Steam running in desktop mode.
Once that is confirmed to be working, it is time to load your game into Steam.
You can do the next step by running Steam in desktop mode, or by using the
native Steam Deck interface – it does not matter. Navigate to the Games
tab and select Add a Non-Steam Game to My Library …. A new window titled
Add a Game will appear. It will include a list of software, but it is
unlikely to include your game (this will only list software installed from
an official flatpak repository). Instead click Browse, and navigate
to the file ending in .exe
.
Figure 13: Selecting A Third-Party Game
Once you find it, select the file and click Open. However, this does not actually add your game to the library. Instead, it adds your game to the list of applications to select from. Make sure your game is selected and choose Add Selected Programs.
Figure 14: Adding the Game to Steam
This will create your entry in Steam. Test it by pressing Run from the game page in Steam.
Note that you will probably want to make a few changes to the Steam page for
the game. The name of that game will include the .exe
, and you do not want
that. Right click on the Run button and select Properties. This will
allow you to change the name of the game. It will also allow you to add
custom artwork to the Steam page, should you so wish.
Once this is done, it is time to exit desktop mode. Double click on the icon in the top left corner of the desktop. This will reboot the deck and return you to the native interface. One last time, navigate to the page your game and press Run to test it out.
Windows Development
CUGL can create traditional 32-bit and 64-bit applications. However, it cannot create Universal Windows applications (e.g. Surface, XBox). That is because SDL support for UWP is a little dicey, and we have had problems compiling it in the past (especially when OpenGL is involved). If anyone wants that as an MEng project, let us know!
Since we do not support mobile Windows devices, we currently view Windows as a debugging platform. It is like macOS is for XCode: a way for a developer to quickly test code without having to have a device handy. With that said, it is a very powerful debugging platform, as Visual Studio provides you with a lot of C++ tools not found in Android Studio. If you are getting segmentation faults in your Android App, Visual Studio has some of the best memory tools out there.
It is also true that there is nothing preventing you from releasing your game as a Windows app (though you cannot do it through the Windows App Store). If you are developing your game for the Steam Deck, it will likely play the same on a Windows machine provided you have an XBox controller attached to it. However, we will not grade your game on the Windows platform.
If you are working on Windows, you should use Visual Studio 2022 (Community Edition). Visual Studio 2022 has stable support for C++17, which is the dialect of C++ that we will be using. You can freely download this version of visual studio from this page.
Working With Visual Studio
If you have never worked with Visual Studio before, you should be aware of the
difference between a solution and a project. A project builds a self-contained
library or piece of software. A solution combines several projects together,
possibly linking the result. In the windows
folder generated by the build
system will be a file that ends in the suffix .sln
. This is the solution.
Open this file with Visual Studio.
When you open the solution, you will see several projects. There will be a project for your game, together with several projects for CUGL and the associated libraries (i.e. SDL, box2d, etc). Since those other projects are not important, we have hidden them away in a folder. You should only focus on your game project. Fortunately, the solution marks this as the main project, so that it is the one that launches whenever you run the application.
Figure 18: A Visual Studio Solution with Associated Projects
To build the application, choose Build > Build Solution. You will need to select a configuration before doing so. These are the two drop-down menus to the left of the play button. The default configuration is Debug x64, which is an unoptimized 64-bit application. To make it a 32-bit application (why?), choose x86 from the second drop-down. You should only choose a Release configuration for packaging your app. The optimizations in Release mode will erase and re-order a lot of code, making the debugger useless.
When you want to run the application, hit the play button. This will run it in a debugger, allowing you to set breakpoints or inspect the program when errors occur. Most of your time with Visual Studio will be doing just this.
Third-Party Libraries
CUGL does not have everything, and occasionally teams want to add libraries with extra functionality. For example, last year one team added a library to provide Blender OBJ file support. However, keep in mind our requirements. You have to use libraries compatible with commercial releases. That means libraries with the GPL license are off limits.
To integrate with CUGL, your library must include build files for CMake. If it uses a fancy system like Meson, you are out of luck. Only CMake is supported by all of the platforms that CUGL targets.
To integrate your library with CUGL you will need to perform a CMake build. While CMake is primarily intended for Linux, we have tested it on both Windows and macOS. It is guaranteed to work on both of those platforms as well. Once again, the install folder guarantees that the executable is packaged together with all of the necessary assets.
Add your third party library to the external
folder. Look at the
CMakelists.txt
file in cugl/buildfiles/cmake
for how to link this library
into CUGL. In addition, you will need to make the include files accessible
to your application. Modify the CMakelists.txt
file in cugl/templates/cmake
to do this. Run the python program on a demo like HelloCUGL
to create the
CMake configuration folder, and build your application
following the instructions.
If you are only developing for Android (which also uses CMake) or SteamOS, this will be sufficient. However, if you want to use this library with iOS you will need to take an additional step. You will want to generate an XCode project for your library. You can do this by navigating to a build folder and typing
cmake -G Xcode path/to/library
However, you will still need to integrate this XCode project with the other XCode build files. You should talk to the instructor if you need to do this.