Usando o Rust para Gamedev

Matthew Michelotti Blocked Unblock Seguir Seguindo 3 de janeiro

Eu criei recentemente um novo site e terminei um jogo online chamado Adventures of Pascal Penguin . Uma das coisas mais originais sobre este jogo é que ele foi escrito em Rust e roda em navegadores graças ao WebAssembly . O WebAssembly só é popular há cerca de um ano, por isso, não são criados muitos jogos como este. Quero compartilhar um pouco da minha jornada com Rust: como comecei e como cheguei a esse ponto.

O desenvolvimento de jogos tem sido um hobby meu há muito tempo. Antes de meados de 2015, quando o Rust 1.0 foi lançado, eu estava fazendo o gamedev em Java com o LibGDX . Como esse era um hobby, escolhi as tecnologias que gostava de usar, mas isso não quer dizer que não houvesse frustração. A maior frustração que tive com o Java, além de sua verbosidade, foi que eu me vi forçado a escolher entre escrever código Java idiomático e escrever código Java que tivesse um desempenho decente. Por exemplo, a API LibGDX incentiva o uso de seus utilitários de pooling de objetos e implementações especializadas de array redimensionável com arrays nativos públicos como campos. Estas não são práticas idiomáticas de Java, mas são úteis para fazer um jogo que corre suavemente. Quando você precisa ser mesquinho sobre a criação de objetos, eu diria que é hora de encontrar um novo idioma.

Eu aprendi Rust lendo seu livro on-line, que parecia muito diferente na época. Era mais curto naquela época, mais como um tutorial do que um livro completo. Havia muitas coisas que eu achava interessantes: abstrações de custo zero, traits e genéricos com monomorfização, o paradigma de propriedade, enums flexíveis combinados com correspondência de padrões, tratamento ergonômico de erros, coleções com eficiência de memória, etc. Mas em um nível fundamental, Rust é uma linguagem segura, ou seja, o desenvolvimento em Rust não é propenso a erros, embora ainda seja uma linguagem altamente e previsivelmente de alto desempenho. Observei que quando escrevo código Rust e chego ao ponto em que meu código é compilado sem mensagens de erro, ele provavelmente funciona corretamente e é eficiente. Eu acho que isso é o que faz a linguagem parecer atraente e fortalecedora para muitas pessoas.

Há também algumas excelentes ferramentas em torno de ferrugem. O próprio compilador Rust fornece mensagens de aviso e erro úteis. A ferramenta de gerenciamento de dependências Cargo é extremamente simples e cria construções reproduzíveis. O repositório central do crates.io é fácil para qualquer um fazer upload. Os documentos da API html gerados são os mais úteis que já vi em qualquer idioma, e os documentos para todas as caixas públicas são criados e hospedados em docs.rs.

Então eu experimentei o desenvolvimento de jogos no Rust, mas não (inicialmente) com a intenção de rodar um jogo através de um navegador web. Na época, havia um excelente tutorial chamado ArcadeRS que demonstrava como fazer um jogo Rust usando o SDL2 . Infelizmente, esse tutorial não está mais atualizado e o site foi desativado . Enquanto trabalhava em um projeto, decidi que seria uma boa prática extrair uma “camada” reutilizável, específica para minhas necessidades, que separasse a lógica do jogo do gerenciamento de recursos, renderização, áudio e outras interfaces necessárias para um jogo. Eu também decidi fazer essa camada de código aberto, e ela se tornou a biblioteca do Gate . Para acompanhar isso, criei um breve jogo de plataforma 2D de código aberto que já foi chamado Chirperjax.

Por esta altura, ouvi falar de uma nova tecnologia chamada WebAssembly. Graças a isso, o Rust pode ser compilado para ser executado em um navegador e atingir um desempenho quase nativo. Eu sabia que tinha que experimentá-lo, embora fosse mais além do que eu normalmente gosto de trabalhar. Um dos problemas com o desenvolvimento de jogos como hobby é que as pessoas tendem a ser cautelosas com o download e a execução de um executável em seus computadores, e com razão. Hospedar um jogo que é executado em um ambiente de sandbox em um navegador permite que mais pessoas joguem o jogo. Minha primeira tentativa foi compilar o Chirperjax usando o suporte a SDL2 do emscripten, mas não consegui que ele funcionasse corretamente. Então eu passei por alguns tutoriais para o alvo ism32-unknown-unknown do Rust e aprendi a chamar métodos JavaScript do Rust e como chamar métodos Rust do JavaScript. Como o html moderno está equipado para criar uma experiência audiovisual interativa por conta própria, eu não precisei depender do SDL2 ou de outras bibliotecas adicionais, com exceção do howler.js . Isso tornou todo o aplicativo leve e me deu uma grande quantidade de controle.

Tenha em mente que eu estava fazendo isso enquanto o ferramental do WebAssembly da Rust ainda era imaturo. Mas consegui colocar o Gate Building no WebAssembly e publiquei o Chirperjax on-line em janeiro de 2018. Depois de fazer isso e ver as pessoas gostarem de jogar, decidi criar um jogo mais ambicioso com o mesmo ferramental. Esse foi o começo das Aventuras de Pascal Penguin, que foi concluído em dezembro de 2018. Foi essencialmente um projeto de um ano para mim.

Então essa foi minha experiência em poucas palavras. Há certamente outros caminhos que eu poderia ter tomado, como aprender MonoGame ou Unity. Mas quando me deparei com Rust pela primeira vez, senti que era exatamente o que eu queria de uma linguagem de programação, e como eu estava fazendo isso por diversão, decidi aprender sobre as opções de gamedev mais mainstream. Eu não tive muita dificuldade em aprender Rust. Claro, houve um tempo em que eu estava, citando, “combatendo o verificador emprestado”, mas aprendi que poderia reorganizar meus modelos de objetos e meu raciocínio para trabalhar mais naturalmente com o verificador emprestado, o que também melhorou a qualidade do meu código. Se eu tivesse algumas reclamações, seria a falta de um tutorial rápido e de bibliotecas imaturas. Mas, no geral, tenho sido muito produtivo com o Rust e incentivo os outros a testá-lo.