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 see 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. In its sixth year now, we have made major upgrades to the build system, making it easier than ever to use.

Table of Contents


download

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 SVG support), we ran out of time to properly test them. As we do not like supporting untested software, we did not include them.

Most notably, this version of CUGL does not support networking. While networking was included in the game engine last year (as seen by the huge number of multiplayer games at Showcase), the third-party library we built upon had many, many problems. We will talk about these problems on the first day of class.

However, we discovered a last minute replacement two weeks before class started. We are still in the middle of testing, but we hope to have a networking code release the third week of class. This networking support will be very bleeding edge and not for the faint of heart. We only recommend it for teams with strong developers confident in their C++ skills.

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 sixth 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 this 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 3.1. Therefore, it is not safe to target any feature after OpenGL 3.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.

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). 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 the config.yml.
  • background: The background color for transparent regions, specified as a string
  • transparent: Whether to allow transparency to remain on desktop platforms
  • rounded: 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 bottom
  • landscape: Fixed in landscape mode with the home “button” on the right
  • portrait-flipped: Fixed in portrait mode with the home “button” at the top
  • landscape-flipped: Fixed in landscape mode with the home “button” on the left
  • portrait-either: Able to rotate between portrait and portrait-flipped
  • landscape-either: Able to rotate between landscape and landscape-flipped
  • multidirectional: Able to rotate between portrait and landscape
  • 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 project
  • apple: To create an XCode project
  • windows: To create a Visual Studio project
  • cmake: To create a CMake source folder for Linux

Apple Development

To develop for macOS and iOS, you must have at least XCode 14. You do not need upgrade to Ventura (though we recommend it), but you should be running Monterey at the very least. That is because iOS 16 requires XCode 14. 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.

If no one on your team has access to a Macintosh, you can still develop for iOS. We are currently working on a virtual machine solution that will allow you to connect to a physical Macintosh on campus, and use that Macintosh to load your game on to your iPhone. This is still in testing, so we hope to have more information about this option soon.

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.

apple-xcode
Figure 1: XCode Build Targets

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.

apple-xcode
Figure 2: iOS Code Signing

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.

android-import
Figure 10: Supported SDK Platforms

android-import
Figure 11: SDK Tools Including the NDK

Warning: There is an important issue to be aware of. Our build process uses ndk-build, which does not tolerate paths with spaces in them. The entire path from the root folder (C:\ on Windows, / on MacOS) to the project must be free of spaces. On Windows, if you have a space in your user directory, you are in trouble. You will need to make a new user (as you cannot change user directories for an existing user) account on your machine.

Configuring the Emulators

Games written in CUGL will have no problem running on modern (released in the past five 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.

android-emulator
Figure 16: An Android Emulator

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.

android-settings
Figure 17: 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.

android-import
Figure 9: 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.

android-build
Figure 12: Building an Android Project

It is important that you do that, since the build is a long process. First, Android Studio invokes ndk-build 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.

android-device
Figure 13: 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.

android-logcat
Figure 14: Android Device Logging


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).

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.

With that said, there is nothing preventing you from releasing your game as a Windows app (though you cannot do it through the Windows App Store). You are welcome to create a Windows fork of your game if you wish. However, we will not grade your game on this 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.

windows-ide
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 x86, which is an unoptimized 32-bit application. To make it a 64-bit application, choose x64 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.


Linux Development

Linux development is new for 2023. While SDL has always supported Linux (indeed it is the primary gaming engine for Linux), the build system was always a bit of a mess.
Fortunately SDL now has clean CMake support, which allows us to support CMake for CUGL as well. This means Linux support is now official, and we hope to have Steam Deck support in the near future.

When you use the build system, it will create a cmake folder for you. Inside of that cmake folder is another folder called src.dir. The folder src.dir is actually the CMake source directory, tailored to your project. So CUGL performs a two-level out-of-source build: one step for the source directory, and one for the build directory. But running the python program only initializes the source directory. The create the build files, you enter the cmake folder and type

cmake src.dir

Note that this is not required. You could put the build files where ever you want. It just makes sense to put them in the provided build folder.

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 output. This is to ensure that the executable will be in the same folder as the game assets, as well as any necessary dynamic libraries. If you wish to distribute your executable, make sure to distribute it as this complete folder.

CMake and Other Platforms

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 output folder guarantees that the executable is packaged together with all of the necessary assets.

With that said, this is not the preferred way to compile for macOS. CMake makes an executable, but it does not make an .app package. That means that the application can be run from the command line only; it is not a normal, double-clickable app. All macOS applications should be built using XCode.