📜 ⬆️ ⬇️

Playing for Rust in 24 hours: personal development experience

image

In this article I will tell you about the personal experience of developing a small game on Rust. It took about 24 hours to create a working version (mostly I worked in the evenings or on weekends). The game is far from over, but I think the experience will be rewarding. I will tell you what I learned and about some observations made when building a game from scratch.

Skillbox recommends: A two-year hands-on course “I am a PRO web developer . ”

We remind: for all readers of "Habr" - a discount of 10,000 rubles when recording for any Skillbox course on the promotional code "Habr".

Why Rust?


I chose this language because I heard a lot of good things about it and I see that it is becoming increasingly popular in the field of game development. Before writing the game, I had little experience developing simple applications on Rust. This was just enough to feel a certain freedom while writing the game.

Why the game and what game?


Making games is fun! I would like more reasons, but for “home” projects I choose topics that are not too closely related to my regular work. What game is this? I wanted to do something like a tennis simulator that combines Cities Skylines, Zoo Tycoon, Prison Architect and tennis itself. In general, it was a game about the academy of tennis, where people come to play.
')

Technical training


I wanted to use Rust, but I didn’t know exactly how much “from scratch” I would need to get started. I did not want to write pixel shaders and use drag-n-drop, so I was looking for the most flexible solutions.

I found useful resources that I share with you:


I studied several Rust game engines, eventually choosing Piston and ggez. I faced them during the work on the previous project. In the end, I chose ggez, because it seemed more suitable for implementing a small 2D game. The modular structure of Piston is too complicated for a novice developer (or someone who first works with Rust).

Game structure


I spent some time thinking about the architecture of the project. The first step is to make the “ground”, people and tennis courts. People have to move around the courts and wait. Players must have skills that improve over time. Plus, there should be an editor that allows you to add new people and courts, but this is no longer free.

Having thought of everything, I set to work.

Game creation


Start: Circles and Abstractions

I took an example from ggez and got a circle on the screen. Amazing Now some abstractions. It seemed to me that it was a good idea to abstract from the idea of ​​a game object. Each object must be rendered and updated as indicated here:

// the game object trait trait GameObject { fn update(&mut self, _ctx: &mut Context) -> GameResult<()>; fn draw(&mut self, ctx: &mut Context) -> GameResult<()>; } // a specific game object - Circle struct Circle { position: Point2, } impl Circle { fn new(position: Point2) -> Circle { Circle { position } } } impl GameObject for Circle { fn update(&mut self, _ctx: &mut Context) -> GameResult<()> { Ok(()) } fn draw(&mut self, ctx: &mut Context) -> GameResult<()> { let circle = graphics::Mesh::new_circle(ctx, graphics::DrawMode::Fill, self.position, 100.0, 2.0)?; graphics::draw(ctx, &circle, na::Point2::new(0.0, 0.0), 0.0)?; Ok(()) } } 

This piece of code allowed me to get an excellent list of objects that I can update and render in an equally excellent cycle.

 mpl event::EventHandler for MainState { fn update(&mut self, context: &mut Context) -> GameResult<()> { // Update all objects for object in self.objects.iter_mut() { object.update(context)?; } Ok(()) } fn draw(&mut self, context: &mut Context) -> GameResult<()> { graphics::clear(context); // Draw all objects for object in self.objects.iter_mut() { object.draw(context)?; } graphics::present(context); Ok(()) } } 

main.rs is necessary because all lines of code are in it. I spent a little time to split the files and optimize the directory structure. Here is how everything began to look after this:

resources -> this is where all the assets are (images)
src
- entities
- game_object.rs
- circle.rs
- main.rs -> main loop

People, floors and images

The next stage is the creation of the game Person object and the loading of images. Everything should be built on the basis of tiles of size 32 * 32.



Tennis courts

Having studied how tennis courts look, I decided to make them out of 4 * 2 tiles. Initially, it was possible to make an image of this size, or to put together 8 individual tiles. But then I realized that only two unique tiles are needed, and here's why.

In total we have two such tiles: 1 and 2.

Each section of the court consists of tile 1 or tile 2. They can be placed as usual or be turned upside down by 180 degrees.



The main mode of construction (assembly)

After it turned out to achieve the rendering of sites, people and maps, I realized that I also needed a basic build mode. It is implemented as follows: when the button is pressed, the object is selected, and the click places it in the right place. So, button 1 allows you to select a court, and button 2 allows you to select a player.

But you still need to remember that we have 1 and 2, so I added a wireframe to make it clear which object is selected. Here's what it looks like.


Questions on architecture and refactoring

Now I have several game objects: people, courts and floors. But in order for wired frames to work, each entity of the object needs to be informed whether the objects themselves are in demonstration mode, or whether the frame is simply drawn. This is not very convenient.

It seemed to me that it was necessary to rethink the architecture so that some limitations emerged:


I conducted additional research and discovered the ECS - Entity Component System architecture, which is commonly used in games. Here are the benefits of ECS:

  • data is separated from logic;
  • layout instead of inheritance;
  • data-oriented architecture.

ECS has three basic concepts:


After studying it became clear that ECS solves such problems:


That's what happened after the introduction of ECS.

resources -> this is where all the assets are (images)
src
- components
- position.rs
- person.rs
- tennis_court.rs
- floor.rs
- wireframe.rs
- mouse_tracked.rs
- resources
- mouse.rs
- systems
- rendering.rs
- constants.rs
- utils.rs
- world_factory.rs -> world factory functions
- main.rs -> main loop

Appoint people to the courts


ECS has made life easier. Now I had a system way of adding data to entities and adding logic based on this data. And this, in turn, allowed to organize the distribution of people on the courts.

What have I done:



Summing up


I really enjoyed working on this simple game. Moreover, I am pleased that I used Rust to write it, because:


Rust game development is just beginning. But there is already a stable and rather large community working to open Rust for everyone. Therefore, I look at the future of the language with optimism, looking forward to the results of our common work.

Skillbox recommends:


Source: https://habr.com/ru/post/444364/


All Articles