Rust is not meant to replace C++, although they are syntactically similar. Rust provides memory security as its core feature, which is why those who like Rust really like it. Rust is also versatile: it can be used for web development, game development, file systems, operating systems, and more.
C++ is an object-oriented programming language that can be used for game development, operating systems, web browsers, cloud/distributed systems, etc. It is particularly popular in game development because of its high performance, abstraction, and many libraries and tools.
In this guide, we will compare Rust and C++ in the context of game development. We’ll cover the similarities and differences between Rust and C, as well as the pros and cons of using each programming language in game development. We’ll also introduce you to some tools for developing games with Rust and C++.
Here’s what we’ll be talking about.
- Why is C++ so popular in game development
- Game engine for C++ developers
- C++ tools for game development
- Rust in game development. Our game?
- Why use Rust for game development?
- Object-oriented programming versus data-oriented programming
- Game engine for Rust developers
- Rust tools for game development
- Rust’s shortcomings
- C + + vs. Rust. Which is the best fit for your game development project?
Why is C++ so popular in game development
C++ has been around for quite some time in the game development industry. Many game developers have chosen to supplement it with other C series languages or even assembly language.
C++ hangs its hat on high performance and abstraction. Developers also choose C++ because of its inheritance capabilities and the capabilities offered by other object-oriented models. Anyone who has worked in the games industry for any length of time can attest to the widespread availability of tools for building games in C++. For developers who need to meet deadlines or who are just starting out in the game industry, C++ is always the first choice due to the plethora of tools and resources available.
Game engine for C++ developers
Due to C++ ‘s long standing in the game development community, there is a wide variety of game engines built in C++. Let’s compare some of the most popular tools for C++ game developers.
Blender
Blender is a FREE and Open Source software (FOSS) 3D production suite. It is built entirely in C++ and provides support for OpenAL 3D sound and Python scripts. Since it is cross-platform, Blender supports most major operating systems. Game development isn’t all there is to Blender, you can also make short films and other movie elements.
unified
Unity is a cross-platform game engine that allows you to create 2D, 3D and virtual reality games. Although it was primarily used as a MAC OS X specific game engine, Unity was later adopted for many film, engineering, and architecture applications.
The panda 3 d
Some game engines require you to use external libraries for collision detection, I/O, audio, etc. Panda3D offers all this and more in one package. This game engine written in C++ allows you to write games in Python, although there is a workaround for writing games in C++.
godot
Godot is an open source, cross-platform game engine packed with tools to keep you focused on your game development. The game engine is built in C++ and is popular for developing games in C++ due to the flexibility it supports.
C++ tools for game development
Unlike Rust, most C++ game engines contain all the tools you need to develop your game.
When building a game in C++, it’s important to think carefully about which engine is best for your project. It is also important to understand the general concepts of object-oriented programming, because you will be working with object-oriented models.
Rust in game development. Have we started our game yet?
To understand what Rust has to offer and why it’s a useful language for game development, let’s take a ride on the train of history and understand why it was created in the first place.
Rust began as a side project of Graydon Hoare, a Mozilla employee, who solved most of the bugs in C++. Over time, Mozilla users became frustrated with memory leaks and other vulnerabilities in C++, the language at the heart of its web browser, Firefox.
That’s why Graydon Hoare recommends Rust, a language he’s been studying since 2006. Mozilla didn’t support Rust until 2010 because it showed significant improvements in memory security.
Why use Rust for game development?
Why would anyone want to develop games in a new language, rather than using the C series, which has been around for so long? This is because memory-safe languages like Rust eliminate many of the errors that users will face when using your product. Memory-safe languages will not allow code with memory leaks to run. To achieve memory security, Rust uses a data-oriented model. It treats game elements as data, rather than as objects in object-oriented programming.
Object-oriented and data-oriented programming
There are some problems with object-oriented programming in game development — in particular one of the core features of object-oriented programming, encapsulation. Encapsulation helps developers hide data to maintain a secure environment. However, in game development, this feature is a foot gun because it defeats the purpose for which it was created.
For example, you need to follow inheritance rules to access data because you can’t expose it due to encapsulation. So, for every new feature added to the game, you might need to access the data from another field, which might be encapsulated so they can inherit the feature.
To understand the drawbacks of encapsulation/inheritance related to OOP in game development, let’s look at this quick example from Catherine West’s closing keynote at RustConf 2018.
typedef uint32_t EntityId; // Declare World to pass it to Entity struct World; struct InputState { ... }; struct RenderState { ... }; // Pure virtual interface! class Entity { public: virtual Vec2F position() const = 0; void update(World* world) = 0; void input(InputState const& input_state) = 0; void render(RenderState& render_state) = 0; private: }; class Player : Entity { public: Vec2F position() const override; void input(InputState const& input_state) override; void update(World* world) override; void render(RenderState& render_state) override; private: Physics m_physics; HumanoidState m_humanoid; . }; class Monster : Entity { public: Vec2F position() const override; void input(InputState const& input_state) override; void update(World* world) override; void render(RenderState& render_state) override; private: Physics m_physics; . }; class NPC : Entity { public: Vec2F position() const override; void input(InputState const& input_state) override; void update(World* world) override; void render(RenderState& render_state) override; private: Physics m_physics; HumanoidState m_humanoid; . }; struct WorldTile { ... }; struct World { List<EntityId> player_ids; HashMap<EntityId, shared_ptr<Entity>> entities; MultiArray2D<WorldTile> tiles; . };Copy the code
As your project grows, many of the child, parent, and ancestor relationships in your application will become unmanageable and may create a hole in your project. For example, if our game gets a new feature in a future release, we need to apply inheritance.
For example, we need a monster to track down players who are in poor health. To do this, we must create a public accessor for the player’s health, since it is private.
class Monster : Entity {
public:
Vec2F position() const override;
void input(InputState const& input_state) override;
void update(World* world) override;
void render(RenderState& render_state) override;
DamageRegion const& damage_region() const;
private:
...
};
Copy the code
If we want to add more functionality to those private states, we need to create more accessors. By doing so, we keep digging holes in our application until it becomes unsafe and unmanageable.
Because Rust takes a data-oriented approach, game elements are treated as data. Rust uses the Entity Component System (ECS) model for game development. Entities are made up of different components attached to them. Components are made up of chunks of data (game development data), and systems manage the application logic. For example, if we wanted to replicate the same example in C++ in Rust, we would use ECS methods with entities and components as structures.
type EntityIndex = usize; struct Physics { position: Vector2<f32>, velocity: Vector2<f32>, mass: f32, } struct HumanoidAnimationState { ... } struct HumanoidItem { ... } struct HumanoidState { animation_state: HumanoidAnimationState, left_hand_item: HumanoidItem, right_hand_item: HumanoidItem, aim_position: Vector2<f32>, } struct Player { physics: Physics, humanoid: HumanoidState, health: f32, focused_entity: EntityIndex, food_level: f32, admin: bool, ... } enum MonsterAnimationState { ... } struct DamageRegion { ... } struct Monster { physics: Physics, animation_state: MonsterAnimationState, health: f32, current_target: EntityIndex, damage_region: DamageRegion, ... } struct NpcBehavior { ... } struct Npc { physics: Physics, humanoid: HumanoidState, health: f32, behavior: NpcBehavior, ... } enum Entity { Player(Player), Monster(Monster), Npc(Npc), } struct Assets { ... } struct GameState { assets: Assets, entities: Vec<Option<Entity>>, players: Vec<EntityIndex>, ... } fn main() { let mut game_state = initial_game_state(); loop { let input_state = capture_input_state(); player_control_system(&mut game_state, &input_state); npc_behavior_system(&mut game_state); monster_behavior_system(&mut game_state); physics_system(&mut game_state); / /... lots more systems render_system(&mut game); audio_system(&mut game); wait_vsync(); }}Copy the code
New functionality can easily be added to the structure. To avoid duplication, you can use the IMPL keyword. With this approach, data can be easily retrieved or passed to a feature without inheritance, because components can be called in when needed.
Game engine for Rust developers
Although Rust is a relatively new language in game development, there are already many game engines built with Rust to choose from. Let’s take a look at some of the top Rust game engine boxes and briefly explore how to use them in game development.
Amethyst
Amethyst is data-oriented, fast, and easy to configure. It has a massively parallel architecture, uses an ECS model, and allows rapid prototyping using RON files.
Amethyst is an easy way for developers who are new to game development to get started. The game engine provides examples that you can easily familiarize yourself with. To run any of the examples, execute the following command in the command line interface of your choice.
cargo run --example name_of_example
Copy the code
Caper
Caper supports other systems, including audio, rendering, input, and collision detection. It’s not a cross-platform game engine, it only supports Linux. Like Amethyst, Caper provides examples to help you navigate the direction of your game engine. You can test these examples by running the following commands on your command line interface.
cargo run --example transforms
Copy the code
Chariot
Chariot is a re-implementation of the “Age of Empires” games released by Microsoft, using the Genie engine. Chariot is an open source game engine that can be ported to any desired platform. The goal of this game engine is to make games with similar titles.
The console
If you want an engine that provides tools to handle user input, Console is your best bet. With the Console engine, you can even easily create separate screens if you don’t want terminal, mouse, or keyboard processing.
Oxygengine
Oxygengine is a web game engine written with Rust and Web-sys. It is a SPECscrate-based HTML5 and WebAssembly game engine for its ECS framework.
Other notable game engines written with Rust include Bevy, Coffee, Corange, Doryen, Dotrix, Muoxi, [rusty_engine] (https://crates.io/crates/rusty_engine), turbine, and more.
Rust tools for game development
As we mentioned earlier, instrumentalization plays an important role in game development. In this section, as we did with C++, we’ll take a closer look at some Rust tools for game development.
2 d rendering
Rendering is an important part of game creation because it gives the users of your product an attractive user interface with two-dimensional, lifelike graphics. Some of the top 2D rendering tools for Rust game development include.
beryllium
blit
crow
fermium
image
3 d rendering
While 2D rendering provides realistic images in two dimensions, you can probably guess that 3D rendering makes your game environment look more realistic in three dimensions. Here are some of the most useful 3D rendering tools for Rust game developers.
ash
gfx
gl
glow
glutin
Artificial intelligence (AI)
The AI library enables you to use algorithms to achieve predictive behavior in your game. For example, there are ai libraries with pre-built chess algorithms that you can use to create such a game in Rust. Prominent examples of Rust ai libraries for game development include.
chess_ai
pathfinding
navmesh
steering
big_brain
The animation library
Most games require movement. The animation library in Rust enables you to manipulate images to appear as if they are moving. Since most Rust libraries are built by community members and Rust is a relatively new language, Pareen is the only animation library for Rust game development that is widely used at the time of this writing.
Pareen allows you to create animations that take time as arguments without passing time variables around. This is useful for creating smooth transitions between multiple game states.
Audio wrapper
Sound is as important in game development as movement. An action game, for example, would feel incomplete and boring without realistic rumbles, crashes, and other sounds associated with debris and destruction.
The following list of Rust Audio wrappers is a good place to start when you want to implement audio in your Rust games.
hound
kira
oddio
rodio
portmidi
Import library
For games that use pads and other input devices, you need a board to handle the controllers in the input devices. Rust has two input libraries.
gilrs
sdl2
Web tools
The game becomes more fun when you play it with your friends. The Rust ecosystem includes a series of networking tools to help facilitate collaboration between developers and facilitate multiplayer features in Rust games, including.
naia
laminar
message-io
enet
quinn
Collision detection library
In some types of games, users lose or gain points when they collide with something. The collision detection library does exactly what it says: Detects collisions in your game.
Useful collision detection libraries for Rust game developers include.
physme
physx
rapier
salva
mgf
UI library
The user interface is the player’s first impression and judgment of your game, even before they participate and play it. In game development, first impressions are everything, and a poor user interface will often turn off players before they even start interacting with your game.
Some of the UI libraries used for Rust game development are.
egui
fungui
imgui
iced
vitral
VR engine
In 2021, parts of the game development community are moving toward virtual reality, creating stunning, lifelike visual landscapes that surround and immerse players like never before.
Here are some of the best VR engines Rust has to offer.
openvr
openxr
rovr
libovr
Rust’s shortcomings
When building games with Rust, it is important to understand that most Rust tools and engines are still under development. And, again, Rust’s approach to game development is data-oriented. Therefore, if you come from an object-oriented background like C++, you should spend some time familiarizing yourself with data-oriented models before starting game development with Rust.
For further reading on the challenges of object-oriented programming in game development, check out Catherine West’s closing keynote at RustConf 2018.
C + + vs. Rust. Which is the best fit for your game development project?
In my humble opinion, there is no perfect programming language, or even a native programming language. The best language, framework, library, or tool for any job depends on how comfortable you are with it and the unique requirements and goals of your project.
Tool availability and support is also a primary consideration for game developers. So if you’re building a game that makes memory safety a priority, Rust is probably your best bet. There are community support and communication channels in Discord and elsewhere. You can keep up to date and track Rust’s production readiness in Game development by visiting Are We Game Yet.
On the other hand, C++ is a good choice for game development projects that don’t require memory security. The C++ ecosystem includes a wider range of proven tools that have been around for years and are trusted by the game developer community. If you’re more comfortable with object-oriented programming than with a data-oriented language like Rust, C++ is a particularly powerful choice for your project.
conclusion
In this tutorial, we explore the basics of game development with the C++ and Rust programming languages. We compare the experiences of developers building games using Rust and C++; Lists the most useful and widely adopted tools for animation, sound, collision detection, multiplayer capabilities, etc. It defines some simple parameters to determine which language is best for your game development project.
The postRust vs. C++ for game developmentappeared first onLogRocket Blog.