Rust is not an Oriented-Object Programming language. Despite this, Rust borrows some principles from multiple languages
During the last month, I was training my skills about Rust. In my learning roadmap, it was time to start a personal project. I chose to create a "Run-And-Gun"/"Multidirectional shooters "game in Rust, inspired by the classic game" Sheriff".
To implement it in Rust, I should choose a game engine. Fortunately, I found two significant game engines based on Rust:
The two games engines look great. After few analyses, I didn't find a good reason to choose Amethyst or Bevy. They look similar (Amethyst inspires Bevy) and perform both well. Then, I selected the Bevy engine because it looked easier to use.
My game and sources are free and open sources (don't hesitate to clone it or test!). The source code is under MIT license and sprites under Creative Common License. Don't hesitate to check the code on my GitHub!
Another point, the game is available in WebAssembly on the web! You can try it on this webpage (Controls: Arrow to move, Space to fire).

My video game Street of Zombies- Programmed with Rust and Bevy
Bevy is a data-driven game engine free and open-source (license MIT). The engine has many features that convinced me to use it:
All around Bevy, there are multiple Third-P plugins developed by several contributors. In my case, I used the bevy_webgl2 to support the rendering in a wasm target! Other Third-P plugins are available, such as a ".tmx" support (a file format generated by tiled, based on XML).
As I said in the introduction, I created a game based on the classic game arcade by Nintendo, "Sheriff".

Sheriff - A run&gun arcade game. By Nintendo
The game principle is simple: The player moves on a game arena in four directions. The goal is to avoid the projectiles fired by the "bandits" on the border. To win, the player should eliminate all of them like a classic "Space Invaders". It was my main inspiration, but I completed the game with other features:
I also had other ideas, such as weapon management (multi-shot fire, camera movement). However, I didn't take the time to implement those ideas as the game is playable right now. Maybe a next time?
As I have no experience in game development (Excepted in some projects in schools), I checked the examples provided by Bevy. One of them was a great source of inspiration thanks to its 2D format and movements: The breakout.

The breakout game featured the Bevy's example.
I used the system to move the "pad", and I adapted it for my player. Then my first function, "keyboard_capture", was created with few modifications to support "diagonal movements". I started a new trait, "MoveableSprite", which represent a "Moveable entity" with three main variables:
Now, let's modify the sprites, and I obtain the beautiful squares to test my movements:

How a "Moveable" 2D sprite is represented in my game
Now, let's use those "MoveableSprites" to create my enemies and projectiles.
It is where I made my worst error: The usage of a trait for the moveable sprites. I quickly featured this error during one of my previous posts concerning design patterns on Rust.
By defining the "Trait", I re-implemented the methods to retrieve and set the speed, direction, and position of the entity for each structure: "Player", "Enemies", and even "Projectiles"! I copy the same code, the same test and the same documentation for all structures. Something is wrong!
First, I was slightly concerned about this. But quickly, when I added the "Hitboxes", "Initial Position", and others, the code started to smell, and I was overwhelmed by my mistake!
I created this trait like an inheritance in an OOP language.
As I described previously, the consequences were terrible.
The solution is a traditional good practice for OOP language: Prefer the inheritance per interface. I transformed the "MoveableSprite" trait into a simple "Struct" and moved my "movement methods" inside it. Then, the code was more straightforward and more efficient!

Inheritance per interface for a "Player" structure. Player can access to MoveableSpriteData
The following things are more anectodical. I will summary one of the Bevy add values in my project with the projectile movement and collision systems.
"Projectiles" are managed by "Weapons", a structure that regulates the fire rate, the number of Amo, and the time to reload the weapon (valid for the "enemy AI", which has a cooldown between each burst of fire). Each entity Player or Enemy contains a Weapon.
Concerning the projectiles movements, Bevy plays its part gracefully by using two "Bevy" systems based on projectiles. Those two methods are directly managed and called by the game engine!

The movement system. Based on a "Bevy" call.
The system is the following: Each projectile created contains an "ID" created by Bevy. Thanks to those IDs, Bevy select a set of data where are collected:
When a weapon fires a projectile, all those data come from this single "ID".

The method from "Weapon" which fires a projectile. The red frame represents the creation of a projectile on Bevy.

This part is executed by "Bevy" frequently. It checks if a "projectile" hits a Player or an Enemy hitbox.
Here, the collision system is a loop that retrieves all my projectiles all around the game area.
For each projectile, I match with the "Player" or list of "Enemies" (following the type of projectile) to check if there is a "Collision". The collision is detected thanks to the "Moveable Sprite" structure where the position and the "hitbox size" is contained. A "collision" gears an update of the Scoreboard (Player Health/Score) and the enemy structure (Enemy health/Enemy destruction if life equals 0).
Now, I have a prototype where a player launches projectiles on a single enemy.

The prototype of my game! Player and Enemy move. Projectile and collisions, OK!
Let's continue to code!
Now, my "Game System" is complete. It is time to make up the game! As I have few talents in graphical design, I looked for free sprites only. Fortunately, I found Sprites under Common Creative License (a huge thanks to the contributors!) that are beautiful. I modified and merged the format for my blog:
An example of SpriteSet from my game "Street Of Zombies"
Now that I have my sprite sets, I cut them per line and columns with Bevy. The management of 2D sprites is logical and user friendly! All the sprite management is in my file "sprite_management_system.rs". I enumerated the texture available (one for the player, one for zombies). Then, I generate the sprite on the map after a "Player" or "Zombie" creation. This process keeps the "Sprite" in the same Bevy "ID" to encapsulate resources.
The sprite is created with a "SpriteSheetBundle" from Bevy.
My sprite is selected and loaded from this function.
My sprites are now generated and created in the game area. Unfortunately, they are not yet "Animated", and the game looks static.
The next step is to create another "Bevy system" dedicated to the sprite animation. Fortunately, sprites with "Player" nor "Enemies" structures are together in an indivisible "Bevy ID". Then, an "animate_sprite" method can be called with the object "MoveableSprites" to determine "Where the entity is seeing" thanks to the "Direction Factor"!
I complete this task with a timer that changes the animation on a single "Row". If the direction changes, the Sprite Set "Cols" switches to the corresponding one thanks to the "TexturePositionEnum"!
Animation of the sprites in my game "Street Of Zombies".
Great, now the game is completed and animated:

The game is running!
Now that the game is complete, it is time to enlarge the deployment of the game. Currently, it only supports Windows, Mac, and Linux.
After a few research, I saw that Bevy could be deployed in WebAssembly to produce a code integrable in the web.
Fortunately, I found a great and precise tutorial in the unofficial Bevy book! As my game doesn't use audio, I focused on graphic rendering. The principle is the following:
Replace the "WebGPU" official rendering with an unofficial one supporting deployment on a Web Page: bevy_webgl2.
After that, the book proposed two solutions to deploy my application: use "wasm-pack" or "Cargo Make". I choose "Cargo Make" to ease the deployment of my application (it requires more configurations, but the process is automated!). This process needs a kind of "Makefile" dedicated to cargo.
Finally, I modified my "cargo.toml" file to support a "Native" or "Wasm" configuration. The last complicate situation was the "Random Number Generator" support, which required an extra configuration in wasm. Fortunately, the book explained the procedure to use the "getrandom" crate with the "js" feature!
Wasm format should be the smaller possible to accelerate the browser downloading. I choose two solutions that are not intrusive in my build process:
Although my "wasm" file is large (~10Mb), it is better than the default version (~12Mb). This process is not the optimized one, but it automated my build optimization and deployment.
Now, let's talk about the deployment with "Github Pages". Initially, "Github Pages" are used to hosting project pages on a GitHub repository. I created a new empty branch, "web".
This branch will contain all the files to deploy my game on the web. It concerns a javascript file, an index.html and the wasm of my game.

My Github page is created!
During this personal project, I was happy to start game development. Although I don't have any experience with Game Engines, Bevy was intuitive to use. Sometimes, the documentation is not complete, but overall, the performance was significant and user friendly!
I think I made some errors concerning a game structure or usage of a game engine. I only touched the surface of Bevy and didn't expect the impressive number of features I didn't use, such as the UI, scenes, sound, and other features through the Data-Driven system.
Moreover, even if I considered the game as completed, it could support multiple weapons or enemy types. Last, there are no sounds implemented (It is maybe a chance 🙂 ).
Bevy is still in development, but the state of the art is promising for the next steps. It looks like a new version (0.6) is in progress with multiple new features and bug fixes, such as the Android support.
Later, I will choose Bevy again to develop another game. This time, in 3D!
I recommend this engine to initiate a game in Rust! It is promising for the future!
The composite Pattern is dedicated to creating a group of similar objects in a tree. This Pattern is represented as a tree, where branches are connected to others and finishes with a single leaf.
Remember: I will feature here an example of Composite Pattern, among others. The pattern form depends on the problem to resolve!
The composite Pattern contains an interface with a series of Leaf and Branches.
IComponent is my trait linking the two distrinc objects: Leaf and Branch.

A classic “composite” problem is the file system from our computers!
Indeed, a folder can contain another folder. However, a file cannot hold a folder. If I generalize this with the composite Pattern format:

This is where the composite Pattern helps us. It creates a hierarchy composed of folders and files represented as a tree structure. By dealing with the organization with a contract (The trait), we can complete this complex structure with a scalable code. Here, the client can ignore the differences of the “tree components”.
The following example is an implementation of the “Composite Pattern” for the File/Folder problem.
In this code example, I recreated the following data structure in my function “create_structure()”:

As you see, the standard interface is a “trait” implemented in my “structs” File and Folder.
The “Trait” is my “Contract” usable by the client to print my “Folders” and “Files” content. Then, a simple call to “open_and_print_all()” reaches my tree recursively to publish the texts.
Here, the Pattern was exploitable by Rust because it exploits an “Interface” (represented by the “trait” Component) and not the inheritance features.
Photo by Viktor Talashuk on Unsplash
Rust is not an Oriented-Object Programming language. Despite this, Rust borrows some principles from multiple languages like C++, JavaScript or Haskell. The language can partially use "OOP" and then some design patterns. My first tentative in Rust was to reproduce those patterns as defined by the GoF. Unfortunately, it was an error, and I got a codebase unclear. For this post, let's check how and why using Design-Patterns in Rust can be a good idea or a trap!
In software development, we encounter and resolve many problems. A design pattern is a reusable solution to a problem type. The practice of those helps to solve common problems during application design. They give to your design multiple benefits: clean code, SOLID principle respect and, essentially, a common language.
Initially, the Design Patterns defined by the GoF serve an OOP language. Then, they are not suitable for Rust! We will see when and how we can interpret some of those patterns in a no-OOP language.
I insist on the word "interpret" or "equivalent": Some of those patterns are hard to apply. Furthermore, class diagrams are not always a good representation in Rust. If you want more details about Design Patterns, I created a post about them.
At first, I tried several times to apply those design patterns in Rust. It is the case in my project, "street of zombie", a run and gun game in Rust. I designed my objects per "structs" and defined some patterns in my code.
Quickly, I started to re-copy some data in another struct. Then I continued until I reached a milestone where my "structs" are similar to mimic inheritance. I tried to code in Rust as I code in C++: Like an OOP language. I made a classic mistake: The patterns defined by the GoF are not wholly applicable in Rust!
Then, I stopped this style of language and reorganized my code. I started to code as I code in C, then I began to use the traits to complete with some known patterns. Now, my coding style in Rust is different from what I do in Java or C++.
Using the "trait" like a "contract", a standard interface for multiple structs, my code became cleaner and more maintainable! Then, I extracted those patterns from my code and compared them with the "official ones":
I will feature (and complete this post) with a few pattern examples in Rust!
Here is a tab about the Design-Patterns in Rust I presented in GrapeProgrammer.com. If I write another post concerning a Design Pattern in Rust, this tab will be updated.
Name | Description | Post | Usage in Rust |
|---|---|---|---|
Composite | Design a tree structure of different components | Usage of "traits" and "dyn" in Box. Adaptable in Rust |
Photo by Barn Images on Unsplash
During my different usages and learning of Rust, I tried to use paradigms from the C++ and Java. After some practice, I was able to reproduce some design patterns in my Rust code. It is a great start to organize my code with interfaces and recognizable patterns! However, Rust is not an Object-Oriented-Programming language… At least, it is the “short answer”, the nature of Rust is complex. Indeed, the OOP deserves an entire chapter in the Rust book!
For this post, I will review with you some characteristics of Rust and why it is or not an OOP language!
I will try to make a short definition because the term is complex. I already made a post about the OOP and its paradigms here. Do not hesitate to check it!
For this post, I will simplify the definition of OOP to the respect of three of the main paradigms:
Let review the three pillars of object-oriented programming language in Rust!
Rust respects the Encapsulation principle! Indeed, it is a simple “struct”:
Polymorphism is the ability to pass a function that will differ following the object type. In Rust, Polymorphism is possible thanks to the “traits”:
Inheritance is one of the biggest benefits of OOP. The key is to provide code re-usability: Instead of implementing the same code in many places, inheritance allows to copy the property of a class to another one.
Concerning Rust, inheritance is not possible: A structure cannot inherit another one. The reuse of the content and functions is not possible. The only key which is closer to this definition is the declaration of default functions in “Traits” … But it is not enough to call that “Inheritance”!
However, I am not surprised: The Inheritance is a poisoned chalice. Indeed, even if the re-usability of code is a great advantage, it complexes the code structure:
Without discipline, documentation, and coding rules, it can trigger a complex and hard-to-read architecture:

Inheritance is beneficial but also one of the most criticized paradigms of OOP.
Rust is a “multi-paradigm” language. In fact, Rust is inspired by multiple languages with various paradigms. It can concern JavaScript, C/C++, Haskell, Swift and others!
However, be careful, it is hard to write Rust code in an OOP style. If you write it as you are using classes, you can run into problems. Indeed, the “Trait” feature is a great way to mimic OOP style. However, remember that “Trait” had been created to define “contracts”. It links multiple structures to a common interface.
Do not hesitate to check this quite interesting story about Rust! It is a great way to start this programming language and how it helps you to write secured and clean code in other languages!
Photo by Christina @ wocintechchat.com on Unsplash
Today I feature to you a quick introduction about RUST. I am preparing more and more posts (and then, a new section) about this great programming language.
First, we will review quickly the characteristics of this language. Don’t hesitate to review my previous post about its comparison with C++:
Rust is a system programming language. In this language, all types are statically defined (like C and C++) - it means, all types are known at compile time. As the C/C++, it offers direct access to the physical hardware of your system.
RUST has a particularity: It had been designed to make it harder to write incorrect and unsafe code. Thanks to this, you have better confidence in your Software when it compiles. Especially compared to C/C++ where memory leaks and buffer overflow can occur easily.
Thanks to all of those features, RUST is “safe by default”. Unfortunately, those memory security checks trigger a longer compile time. Moreover, the compiler force you to write “safe code” (But it well worth the effort!). You can also note other specificities like:
For the next weeks, I will prepare some new stuff about the language specificities and its modules. Don’t hesitate to review "The book".
As I said, expect to see more and more posts about it. Of course, I continue to make posts about C / C ++ during the next weeks. Learning RUST changes your habits on C / C ++ programming. It sensitizes you about “safe code” and it forces you to avoid some strange designs.