Blog banner

Atualização

Já se passaram dois anos, descubra oque aconteceu e o que está por vir na Chicane.

  • Erick Frederick
  • há 2 anos
  • Desenvolvimento de Jogos

Já faz um tempo desde o meu último blog post] mais de dois anos, eu acho, mesmo gostando de escrever esse tipo de coisa, não tinha muito o que falar durante esse tempo.

Venho melhorando a chicane engine ativamente, quase 400 commits para ser exato! Levando isso em consideração, vou fazer o meu melhor para resumir e dar uma aprofundada sobre essas mudanças neste post, e falar um pouco sobre o que vem pela frente.

Camadas

Levando em consideração que sou novato no desenvolvimento de jogos fui em busca de dicas numa vasta gama de mídias, com isso me deparei com o canal do youtube The Cherno, ele é um desenvolvedor com experiência no mercado com uma boa quantidade de vídeos relaciados a área, um vídeo em específico referente a um sistema em camadas chamou muito minha atenção, então resolvir tentar implementar na aplicação. Como o nome já diz, é um design baseado na renderização uma sobrepondo a outra, fazendo a aplicação mais maleável, com isso eu conceitualizei algumas camas principais:

  • Camada Sky - Renderiza o céu;
  • Camada Shadow - Escreve no shadow map;
  • Camada Level - Renderiza tanto os objetos como as sombras;
  • Camada UI - Renderiza os components 2D da UI.

Mesmo com essas camadas essênciais, o sistema dá suporte para adição de novas camadas independente de sua posição reafirmando essa filosofia da maleabilidade, é responsabilidade do desenvolvedor de manter isso em mente, a engine não mantém regras referentes as ordens das camadas.

Desacoplamento

No começo da minha jornada eu tinha uma engine para Vulkan em mente, mas com a evolução do meu entendimento e do sistema, fazia mais sentido separar o código referente a API's gráficas do resto, com isso decidi em isolar esta parte como um todo.

Mesmo sem uma implementação com uma novas APIs em mente foi feita a refatoração com a adoção de novas APIs gráficas mais fácil, diferentes APIs trazem os suas particularidades, com isso em mente cada camada tem sua própia versão com diferentes APIs.

Melhorando a fundação

Ao criar diferentes ambientes de teste, uma coisa ficou muito clara: o sistema de transformação não estava correto, era inconsistente e exigia muita cópia e colagem de código, o que pôs em evidência a minha ingenuidade na altura em que concebi este sistema pela primeira vez. Levei quase três dias e tive de me debater com diferentes fontes para acertar o básico das transformações e perceber o que estava errado na minha implementação; corrigir os principais cálculos da matriz e das orientações trouxe à tona diferentes problemas com o meu código de shader, levando-me a um beco sem saída na tentativa de perceber o que estava errado com algo que, há pouco tempo, estava a funcionar.

Após fazendo esta melhora, o próximo passo era partir para os componentes das cenas (Actor e Component), estudando o código, ficou aparente que a maioria das funcionalidades poderiam ser implemetadas na classe base Transformable, ademais, alguns métodos foram implementados para melhoria de uso da classe como os métodos addTranslation, addRotation e addScale, assim como diferentes overloads reduzindo assim a repetição de código.

O Sistema Grid

Com minha pequena experiência com a Unreal Engine, eu percebi que gostava mais do estilo implementado pelo o Qt ou Panorama UI (sistema de UI da engine Source 2 da Valve Software) que é uma implementação estilo HTM5/CSS3/Javascript, com isso criei o sistema Grid, que levado o nome baseado nas posíções dos veículos em uma corrida na linha de largada.

Este sistema é baseado em arquivos XML com valores e atributos como o HTML5 tags e valores do back end que lembram o AngularJS e estilização como CSS3.

Os componentes básicos são os seguintes:

  • Button
  • Container
  • List
  • Popup
  • Progress Bar
  • Text
  • Text Input

Estes componentes como uma fundação para futuras especializições, como div ou span no HTML5, abaxio segue um exemplo de arquivos do sistema Grid.

Exemplo do template .grid

    <View id="home" style="Content/Sample/Views/Home.decal">
        <Container id="victory" isVisible="{{ didPlayerWin }}">
            <Text id="victoryText">YOU WIN!</Text>
        </Container>
        <Container id="frameTelemetry" direction="row">
            <Text id="framePerSecond">{{ getFPS() }} FPS</Text>
            <Text id="frameTimeText">{{ getFrametime() }} ms</Text>
        </Container>
        <Container id="crosshair">
            <Container id="crosshairTop"></Container>
            <Container id="crosshairBottom"></Container>
            <Container id="crosshairLeft"></Container>
            <Container id="crosshairRight"></Container>
        </Container>
    </View>

Exemplo de estilização .decal

    #victory {
        position: absolute;
        height: 30vh;
        width: 100%;
        margin-top: 10vh;
        background-color: #333333;
    }

    #victoryText {
        alignment: center;
    }

    #frameTelemetry {
        position: absolute;
        width: 175px;
        height: 25px;
        margin-left: auto;
    }

    #framePerSecond {
        margin-left: 1vw;
        alignment: start center;
        color: #24f51d;
    }

    #frameTimeText {
        alignment: end center;
        color: #24f51d;
    }

    #crosshairTop {
        position: absolute;
        height: 10px;
        width: 2px;
        background-color: #FFFFFF;
        margin: 50% 2px 28px 50%;
    }

    #crosshairBottom {
        position: absolute;
        height: 10px;
        width: 2px;
        background-color: #FFFFFF;
        margin: 50% 2px 8px 50%;
    }

    #crosshairLeft {
        position: absolute;
        height: 2px;
        width: 10px;
        background-color: #FFFFFF;
        margin: 50% 15px 15px 50%;
    }

    #crosshairRight {
        position: absolute;
        height: 2px;
        width: 10px;
        background-color: #FFFFFF;
        margin: 50% -5px 15px 50%;
    }

O sistema Box

Sempre tive em mente que uma engine com um sistema de assets controlada é uma engine feliz, então em decidi criar o meu própio sistema, no início era só um arquivo de contia o tipo e os dados binários do asset, seguindo o tema de corridas, o sistema foi nomeado Box referente os pits de paradas para os veículos.

Durante o desenvolvimento foi feito um visualizador de assets básico, e com isso ficou aparente que o sistema Box precisava de melhorias, em sua primeira iteração este era o template:

Template

    BOX;{VERSÃO_DO_ARQUIVO};{TIPO_DO_ASSET};{ID_DO_ASSET};{QUANTIDADE_DE_ITENS};[ENTRY{CONTADOR_DO_ITEM};{ID_DO_ITEM}DATA]

Seção do Header

    BOX;{VERSÃO_DO_ARQUIVO};{TIPO_DO_ASSET;{ID_DO_ASSET};{QUANTIDADE_DE_ITENS};

Seção dos Dados

    [ENTRY{CONTADOR_DO_ITEM};{ID_DO_ITEM}DATA]

Na sua concepção eu pensei que a solução era inteligente, e parecia muito com os dados de mainframe que eu trabalhava no dia a dia, uma string simples com o template fixo e rápida de processar, o problema é que este formate não escala bem com mudanças, levando em mente que novos dados deverão ser inclusos no cabeçalho, qualquer mudança invalidária as versões antigas.

Com isso, decidi reescrever o sistema de assets como um todos e como o módulo Grid, implementar usando XML que por sí só já é mais maleável e fácil de trabalhar.

A nova implmetação parou de usar o arquivo binário da mídia e passou a usar os dados convertidos para Base64, ademais, faz uso constante de atributos XML para dados customizados referentes ao asset, abaixo segue um exemplo de um arquivo Box de um arquivo mesh (combinação de modelos 3D e texture):

Exemplo

    <Asset version="1" id="Cube">
        <Group id="Body">
            <Model>Content/Sample/Models/Cube.bmdl</Model>
            <Texture>Content/Sample/Textures/Gray.btex</Texture>
        </Group>
    </Asset>

Este templete não só melhoria a maleabilidade como a facilidade na leitura.

O Futuro

Desde o início, tratei esse motor como um projeto pessoal, mas, com o passar do tempo, passei a dedicar muito tempo e energia à sua manutenção. Por mais que eu goste de aprender coisas novas, não é isso que desejo para minha carreira no momento; ainda preciso me dedicar aos meus estudos e sou muito jovem no setor de desenvolvimento de software para ingressar em qualquer grande empresa de desenvolvimento de jogos.

Levando isso em consideração, decidi encerrar este projeto para melhorar outros aspectos da minha vida. Este não é um adeus às minhas postagens no blog, mas uma despedida deste projeto em particular; com o passar do tempo, percebi que criar um motor de jogos exigia muito tempo e conhecimento, e isso é algo que não tenho no momento.

A partir de agora, as postagens do blog abordarão temas diferentes, não apenas relacionados ao desenvolvimento de software, como minha jornada de aprendizado com diferentes linguagens de programação ou futuras viagens ao exterior. Até lá, este é um adeus.