Rust não está aqui para substituir C ++, embora sejam sintaticamente semelhantes. Rust fornece segurança de memória como seu principal recurso, e é por isso que aqueles que amam Rust realmente o amam. Rust também é versátil: pode ser usado para desenvolvimento web, desenvolvimento de jogos, sistemas de arquivos, sistemas operacionais e muito mais.

C ++ é uma linguagem de programação orientada a objetos que pode ser usada para desenvolvimento de jogos, sistemas operacionais, navegadores da web, sistemas distribuídos/em nuvem, etc. É particularmente popular para desenvolvimento de jogos devido ao seu alto desempenho, forte abstração e disponibilidade de bibliotecas e ferramentas.

Neste guia, compararemos Rust vs. C ++ no contexto do desenvolvimento de jogos. Cobriremos semelhanças e diferenças entre Rust e C e os prós e contras do uso de cada linguagem de programação para o desenvolvimento de jogos. Também apresentaremos algumas ferramentas para desenvolvimento de jogos em Rust e C ++.

Aqui está o que vamos cobrir:

Por que C ++ é popular para desenvolvimento de jogos

C ++ já existe há algum tempo na indústria de desenvolvimento de jogos. Muitos desenvolvedores de jogos optam por complementá-lo com outras linguagens da família C ou mesmo com linguagens assembly.

C ++ se destaca pelo alto desempenho e forte abstração. Os desenvolvedores também escolhem C ++ por seu recurso de herança e outros recursos fornecidos por seu modelo orientado a objetos. Qualquer pessoa que já esteja na indústria de jogos há algum tempo pode atestar a grande disponibilidade de ferramentas para construir jogos em C ++. Para desenvolvedores que têm um prazo a cumprir ou que são novos na indústria de jogos, C ++ é sempre a escolha certa devido à vasta disponibilidade de ferramentas e recursos.

Mecanismos de jogo para desenvolvedores C ++

Como C ++ tem sido um grampo na comunidade de desenvolvimento de jogos por muito tempo, há uma grande variedade de motores de jogos construídos com C ++. Vamos comparar algumas das ferramentas mais populares para desenvolvedores de jogos C ++.

Liquidificador

Blender é um pacote de produção 3D de software livre e de código aberto (FOSS). É inteiramente construído com C ++ e oferece suporte para som OpenAL 3D e script Python. Dado que é multi-plataforma, o blender suporta a maioria dos principais sistemas operacionais. O desenvolvimento de jogos não é tudo para o que o Blender é bom; você também pode criar curtas-metragens e outros elementos cinematográficos.

Unidade

Unity é um mecanismo de jogo de plataforma cruzada que permite criar jogos 2D, 3D e de realidade virtual. Embora tenha sido construído principalmente como um mecanismo de jogo exclusivo do MAC OS X, o Unity já foi adotado em muitos aplicativos de cinema, engenharia e construção.

Panda3D

Alguns mecanismos de jogo exigem que você use bibliotecas externas para detecção de colisão, E/S, áudio, etc. P anda3D oferece tudo isso e muito mais em um pacote. Este mecanismo de jogo escrito em C ++ permite que você escreva jogos em Python, embora haja uma solução alternativa para escrever jogos em C ++.

Godot

Godot é um mecanismo de jogo de plataforma cruzada de código aberto com ferramentas que permitem que você se concentre no desenvolvimento do jogo. Este mecanismo de jogo é construído com C ++ e é bastante popular para desenvolvimento de jogos com C ++ devido à flexibilidade que oferece suporte.

Ferramentas C ++ para desenvolvimento de jogos

Ao contrário do Rust, a maioria dos mecanismos de jogo em C ++ vem com todas as ferramentas de que você precisa para desenvolver jogos.

Ao criar jogos em C ++, é importante considerar cuidadosamente qual mecanismo é mais apropriado para o seu projeto. Também é importante entender o conceito geral de programação orientada a objetos, uma vez que você lidará com o modelo orientado a objetos.

Ferrugem no desenvolvimento de jogos: ainda estamos no jogo?

Para apreciar o que o Rust oferece e por que é uma linguagem útil para o desenvolvimento de jogos, vamos dar uma voltinha no trem da história para entender por que ele foi criado.

Rust começou como um projeto paralelo de um dos Funcionários da Mozilla, Graydon Hoare, que abordou a maioria das vulnerabilidades em C ++. Com o tempo, os usuários do Mozilla ficaram frustrados com os vazamentos de memória e outras vulnerabilidades do C ++, que é a linguagem central de seu navegador, o Firefox.

É por isso que Graydon Hoare sugere o Rust, uma linguagem em que ele trabalhava desde 2006. Foi só em 2010 que o Mozilla começou a oferecer suporte ao Rust, depois de ter mostrado grandes avanços na segurança da memória.

Por que usar Rust para desenvolvimento de jogos?

Por que alguém iria querer usar uma nova linguagem para o desenvolvimento de jogos em vez da família C, que existe há anos? É porque linguagens de memória segura, como Rust, eliminam muitos dos bugs que seus usuários enfrentarão ao usar seu produto. Linguagens seguras para memória não permitem a execução de códigos com vazamentos de memória. Para obter segurança de memória, Rust usa o modelo orientado a dados. Ele trata os elementos do jogo como dados, em vez de objetos, como na programação orientada a objetos.

Programação orientada a objetos vs. programação orientada a dados

Existem alguns problemas com a programação orientada a objetos no desenvolvimento de jogos-especialmente com um dos principais recursos da programação orientada a objetos, o encapsulamento. O encapsulamento ajuda os desenvolvedores a ocultar dados para manter um ambiente seguro. No entanto, no desenvolvimento de jogos, esse recurso é uma espingarda porque vai contra o propósito para o qual foi criado.

Por exemplo, você precisa seguir a herança para poder acessar os dados porque não pode torná-los públicos devido ao encapsulamento. Portanto, para cada novo recurso adicionado ao jogo, você pode precisar acessar dados de outro campo, que podem ser encapsulados, para que possam herdar o recurso.

Para entender o lado negativo do encapsulamento/herança associado à OOP no desenvolvimento de jogos, vamos dar uma olhada neste exemplo rápido de Keynote de encerramento de Catherine West na RustConf 2018 :

 typedef uint32_t EntityId; //Declare o mundo para passá-lo para a entidade
struct World; struct InputState {...};
struct RenderState {...}; //Interface virtual pura!
class Entity {
público: posição Vec2F virtual () const=0; void update (World * world)=0; entrada vazia (InputState const & input_state)=0; void render (RenderState & render_state)=0; privado:
}; class Player: Entity {
público: Vec2F position () const override; anular a entrada (InputState const & input_state); anulação de atualização void (World * world); void render (RenderState & render_state) override; privado: Physics m_physics; HumanoidState m_humanoid; ...
}; class Monster: Entity {
público: Vec2F position () const override; anular a entrada (InputState const & input_state); anulação de atualização void (World * world); void render (RenderState & render_state) override; privado: Physics m_physics; ...
}; classe NPC: Entity {
público: Vec2F position () const override; anular a entrada (InputState const & input_state); anulação de atualização void (World * world); void render (RenderState & render_state) override; privado: Physics m_physics; HumanoidState m_humanoid; ...
}; struct WorldTile {...}; struct World { Listar  player_ids; HashMap > entidades; Blocos MultiArray2D ; ...
};

À medida que seu projeto cresce, muitos dos relacionamentos com filhos, pais e ancestrais em seu aplicativo se tornam muito difíceis de lidar e podem criar uma lacuna em seu projeto. Por exemplo, se nosso jogo receber um novo recurso em uma versão futura, precisaremos aplicar a herança.

Digamos, por exemplo, que precisamos de um monstro para rastrear jogadores com problemas de saúde. Para fazer isso, temos que criar um acessador público para a saúde do jogador porque é privado:

 class Monster: Entity {
público: Vec2F position () const override; anular a entrada (InputState const & input_state); anulação de atualização de void (World * world); void render (RenderState & render_state) override; DamageRegion const & damage_region () const; privado: ...
};

Se quisermos adicionar mais recursos para estados que são privados, precisamos criar mais acessores. Fazendo isso, continuaremos cutucando nosso aplicativo até que ele fique inseguro e não possa ser gerenciado.

Como o Rust adota uma abordagem orientada a dados, os elementos do jogo são tratados como dados. Rust usa o padrão Entity Component System (ECS) no desenvolvimento de jogos, onde a entidade consiste em diferentes componentes anexados a ela, o componente, consiste em pedaços de dados (dados para desenvolvimento de jogos) e o sistema gerencia a lógica do aplicativo. Por exemplo, se quisermos replicar o mesmo exemplo de C ++ no Rust, usaremos a abordagem ECS com entidades e componentes como estruturas.

 digite EntityIndex=usize; struct Physics { posição: Vector2 , velocidade: Vector2 , massa: f32,
} struct HumanoidAnimationState {...}
struct HumanoidItem {...} struct HumanoidState { animation_state: HumanoidAnimationState, left_hand_item: HumanoidItem, right_hand_item: HumanoidItem, aim_position: Vector2 ,
} struct Player { física: física, humanóide: HumanoidState, saúde: f32, focus_entity: EntityIndex, food_level: f32, admin: bool, ...
} enum MonsterAnimationState {...}
struct DamageRegion {...} struct Monster { física: física, animation_state: MonsterAnimationState, saúde: f32, current_target: EntityIndex, damage_region: DamageRegion, ...
} struct NpcBehavior {...} struct Npc { física: física, humanóide: HumanoidState, saúde: f32, comportamento: NpcBehavior, ...
} enum Entity { Jogador (jogador), Monstro (Monstro), Npc (Npc),
} Struct Assets {...} struct GameState { ativos: ativos, entidades: Vec >, jogadores: Vec , ...
} fn main () { deixe mut game_state=initial_game_state (); ciclo { deixe 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); //... muito mais sistemas render_system (& jogo mut); sistema_de_udio (& jogo mut); wait_vsync (); }
}

Novos recursos podem ser facilmente adicionados às estruturas. Para evitar a repetição, você pode usar a palavra-chave impl . Com essa abordagem, é fácil recuperar ou passar dados para um recurso com segurança, sem herança, porque os componentes podem ser chamados sempre que forem necessários.

Mecanismos de jogo para desenvolvedores Rust

Embora Rust seja uma linguagem relativamente nova no cenário de desenvolvimento de jogos, já existe uma seleção sólida de motores de jogo construídos em Rust. Vamos dar uma olhada em alguns dos principais engradados de mecanismo de jogo do Rust e explorar brevemente como usá-los no desenvolvimento de jogos.

Ametista

Amethyst é orientado a dados, rápido e fácil de configurar. Ele tem uma arquitetura massivamente paralela, usa o modelo ECS e permite a prototipagem rápida com arquivos RON.

O Amethyst permite que os desenvolvedores que são novos no desenvolvimento de jogos comecem a trabalhar imediatamente. O mecanismo de jogo oferece exemplos que ajudam você a se familiarizar com facilidade. Para executar qualquer um dos exemplos, execute o comando abaixo na interface de linha de comando de sua escolha:

 corrida de carga--example name_of_example

Caper

Caper tem suporte para outros sistemas, incluindo áudio, renderização, entrada e detecção de colisão. Não é um motor de jogo de plataforma cruzada e suporta apenas o sistema operacional Linux. Como Amethyst, Caper fornece alguns exemplos para ajudá-lo a se orientar com o motor de jogo. Você pode testar esses exemplos executando o comando abaixo em sua interface de linha de comando.

 corrida de carga-transformações de exemplo

Carruagem

Chariot é uma reimplementação do jogo “Age of Empires” publicado pela Microsoft, que usa o Genie Engine. Chariot é um motor de jogo de código aberto que pode ser portado para qualquer plataforma desejada. O objetivo desse mecanismo de jogo é fazer jogos como o título mencionado anteriormente.

Console

Se você quiser um mecanismo que forneça ferramentas para lidar com a entrada do usuário, Console é sua melhor aposta. Com o mecanismo do console, você pode até criar telas autônomas facilmente se não quiser manipulação de terminal, mouse ou teclado.

Oxigotor

Oxygengine é um mecanismo de jogo da web escrito em Rust com web-sys. É um mecanismo de jogo HTML5 e WebAssembly baseado em S pecs crate usado para sua estrutura ECS.

Outros motores de jogo notáveis ​​escritos em Rust incluem bevy , café , corange , doryen , dotrix , muoxi , rusty_engine , turbina e muitos mais.

Ferramentas Rust para desenvolvimento de jogos

Como mencionamos anteriormente, as ferramentas desempenham um papel importante no desenvolvimento de jogos. Nesta seção, como fizemos com C ++, daremos uma olhada de alto nível em algumas ferramentas Rust para desenvolvimento de jogos.

Renderização 2D

A renderização é uma parte importante da criação do jogo porque oferece aos usuários do seu produto uma interface de usuário envolvente com imagens bidimensionais e fotorrealistas. Algumas das principais ferramentas de renderização 2D para o desenvolvimento de jogos Rust incluem:

Renderização 3D

Embora a renderização 2D ofereça imagens fotorrealistas bidimensionais, como você provavelmente pode imaginar, a renderização 3D faz com que seu ambiente de jogo pareça ainda mais realista com imagens tridimensionais. Abaixo estão algumas das ferramentas de renderização 3D mais úteis para desenvolvedores de jogos Rust:

Inteligência artificial (IA)

As bibliotecas de IA permitem que você use algoritmos para implementar comportamentos preditivos em seu jogo. Por exemplo, existem bibliotecas de IA com algoritmos de xadrez predefinidos que você pode usar para criar tal jogo no Rust. Exemplos proeminentes de bibliotecas Rust AI para desenvolvimento de jogos incluem:

Bibliotecas de animação

A maioria dos jogos requer movimento. Bibliotecas de animação no Rust permitem que você manipule imagens para que se comportem como se estivessem em movimento. Como a maioria das bibliotecas Rust são construídas por membros da comunidade e Rust é uma linguagem relativamente nova em cena, Pareen é a única linguagem amplamente usada caixa de animação para desenvolvimento de jogos em Rust no momento da escrita.

Pareen permite que você crie animações que são parametrizadas pelo tempo sem a necessidade de passar variáveis ​​de tempo. Isso é útil para criar transições suaves entre vários estados do jogo.

Wrappers de áudio

O som é tão importante quanto o movimento no desenvolvimento de jogos. Um jogo de ação, por exemplo, pareceria incompleto e enfadonho sem estrondos, travamentos e outros ruídos realistas associados a destroços e destruição.

A lista a seguir de wrappers de áudio Rust é um ótimo lugar para começar quando for implementar áudio em seu jogo Rust:

Bibliotecas de entrada

Para jogos que usam pads e outros dispositivos de entrada, você precisará de uma caixa para lidar com controladores em dispositivos de entrada. Rust tem duas bibliotecas de entrada:

Ferramentas de rede

Os jogos ficam muito mais divertidos quando você os joga com os amigos. O ecossistema Rust inclui uma variedade de ferramentas de rede para ajudar a promover a colaboração entre os desenvolvedores e facilitar recursos multijogador em jogos Rust, incluindo:

Bibliotecas de detecção de colisão

Em certos tipos de jogos, o usuário falha ou ganha pontos ao colidir com algo. Bibliotecas de detecção de colisão fazem exatamente o que o nome sugere: detectam colisões dentro do seu jogo.

Bibliotecas de detecção de colisão úteis para desenvolvedores de jogos Rust incluem:

Bibliotecas de IU

A interface do usuário é a primeira coisa que um jogador vê e julga sobre o seu jogo, mesmo antes de se envolver com ele e experimentá-lo. As primeiras impressões são tudo no desenvolvimento de jogos, e uma interface de usuário ruim geralmente desativa os jogadores antes mesmo de eles começarem a interagir com o jogo.

Algumas bibliotecas de IU para desenvolvimento de jogos Rust são:

Motores de RV

Em 2021, alguns segmentos da comunidade de desenvolvimento de jogos estão se voltando para a realidade virtual, criando paisagens visuais incrivelmente realistas que envolvem e envolvem os jogadores como nunca antes.

Abaixo estão alguns dos melhores motores de RV que a Rust tem a oferecer:

Onde a ferrugem fica aquém

Ao criar jogos no Rust, é importante entender que a maioria das ferramentas e mecanismos do Rust ainda estão em estágio de desenvolvimento. E, para reiterar, a abordagem de Rust para o desenvolvimento de jogos é orientada a dados. Portanto, se você tem experiência em orientação a objetos como C ++, deve passar algum tempo se familiarizando com o modelo orientado a dados antes de iniciar o desenvolvimento de jogos em Rust.

Para ler mais sobre os desafios impostos pela programação orientada a objetos no desenvolvimento de jogos, consulte Catherine Keynote de encerramento de West na RustConf 2018 .

C ++ vs. Rust: qual é o melhor para o seu projeto de desenvolvimento de jogos?

Na minha humilde opinião, não existe uma linguagem de programação perfeita ou mesmo uma linguagem de programação inerente. A melhor linguagem, estrutura, biblioteca ou ferramenta para qualquer trabalho depende do seu nível de conforto ao usá-la e dos requisitos e objetivos exclusivos do seu projeto.

A disponibilidade e o suporte das ferramentas também são considerações importantes para os desenvolvedores de jogos. Portanto, se você está construindo um jogo em que a segurança da memória é uma prioridade, Rust é provavelmente sua melhor escolha. Há canais de suporte e comunicação da comunidade em Discord e em outros lugares. Você pode se manter atualizado e acompanhar a preparação de Rust para a produção em relação ao desenvolvimento de jogos visitando Are We Game Yet?

Por outro lado, C ++ é uma ótima escolha para projetos de desenvolvimento de jogos que não requerem segurança de memória. O ecossistema C ++ inclui uma gama mais ampla de ferramentas testadas e comprovadas que existem há anos e são confiáveis ​​entre a comunidade de desenvolvedores de jogos. C ++ é uma escolha especialmente forte para seu projeto se você se sentir mais confortável com a programação orientada a objetos do que com linguagens orientadas a dados, como Rust.

Conclusão

Neste guia, exploramos os fundamentos do desenvolvimento de jogos em C ++ e a linguagem de programação Rust. Comparamos a experiência do desenvolvedor ao usar Rust e C ++ para criar jogos; listou as ferramentas mais úteis e amplamente adotadas para implementar animações, sons, detecção de colisão, recursos multijogador e muito mais; e definiu alguns parâmetros simples para determinar qual linguagem é mais apropriada para o seu projeto de desenvolvimento de jogos.

A postagem Rust vs. C ++ para desenvolvimento de jogos apareceu primeiro no LogRocket Blog .