Demorei para realmente tomar essa decisão, sabia que ia ser um trampo significativo. No entanto descobri que foi até menos trabalhoso do que eu pensei.
A repercussões nesse sistema de inventário, uma delas é o tamanho dos itens, itens muito grandes não podem ser carregados nas bolsas. Mas isto é algo que ocorre no mundo real.
Um modelo de inventário com slots seria uma tarefa até simples, bastaria uma matriz X por Y, e para colocar um item bastaria verificar se há espaços adjacentes suficiente na matriz.
Outro modelo é o de lista (ex.: Ragnarok, Skyrin ), ai você limita o inventário por peso dos itens.
Mas eu optei por manter o experimentalismo, afinal é um jogo indie mesmo.
Esse modelo vai possibilitar que o jogador invente combinações para melhor alocar objetos como runas, baralhos, "lock-picks", kunais, poções, ervas e outros elementos.
Lógicamente não será possível colocar objetos como espada e escudo nos bolsos, não é um problema devido a classe da personagem.
E também servirá perfeitamente para criar pluzes durante o jogo.
Mas mesmo não muito realista a geometria dos objetos pode ser bem detalhada para dar um grau maior de possibilidades.
Eu poderia fazer em 3D aproveitando a já existente engine de física mas isso daria um trabalho adicional de eu modelar os objetos em volume, mesmo se mantivesse o visual 2D. Sem falar do processamento ser maior.
Manter o visual em 2D além de facilitar o trabalho me dá também um grau de abstração da realidade, assim não há necessidade de uma exatidão muito grande nas formas.
Box2D e LibRocket
Ai entrou a parte complexa, a inserção de uma engine de física 2D: Box2D.
O resultado ficou com uma aparência meio de que "nas coxa"
physic.B2World.handle("IDdoObjetoRML","NomeDoDocument.rml")
Ficou desta forma porque, em C++, fiquei com dificuldades de pegar o ponteiro de Lua. De fato talvez seja melhor assim, fica com uma aparência de estar bem separado da RML (HTML).
Eu comecei com uma proposta de fazer class pai para o centro da física e do bolso, e uma classe para os objetos. Mas deixei de lado e passei para uma única classe simples.
Essa classe tem o nucleo da Box2D, e gera as formas e a geometria para desenho na LibRocket.
Ficou até muito interessante o resultado, a classe tem um metodo Render que desenha a imagem do bolso e das sub-geometrias (formas), e graças a LibRocket automaticamente desenha qualquer outra coisa que eu coloco nela.
Assim eu posso criar uma GUI aprimorada, que ao clicar no item ele exibe seus atributos e etc. Algo assim:
<b2world image="bolso.png" bodies="bolso01.json" id="bolso01">
<div id="info01" class="informacao">bla bla bla</div>
</b2world>
Eu imagino que fãs de outras linguagens queiram me tacar pedras, mas usado para o bem e não para o mal o C++ nos permite as terríveis "heranças múltiplas".
Ao invés de usar uma segunda classe controlando a classe do bolso, a estrutura funciona assim:
Classe wwpb2World (classe do bolso)
LibRocket::Core::Element (estende a classe para trabalhar com tags HTML)
WWP::WWP_Base (minha implementação de Lua)
Como a conexão delas vai morrer ai, não vai causar prejuízo mais adiante.
O Box2D é simples de ser inserido, bastou chamar as classes e pronto.
O difícil foi integrar um componente novo ao LibRocket, a biblioteca é muito boa mas é cheia de regrinhas.
Os objetos de física são criados por este editor open source, ele salva tudo em JSOM.
Ai eu pensei em fazer a leitura do JSON pela Lua, mas o processo de ficar passando valores entre Lua e C++ em tempo de execução ia consumir um bom trabalho, principalmente porque ando tendo muito medo das threads que andam fugindo ao controle.
Procurei umas soluções livres de parsers C++ para JSON, mas todas estavam dando muito trabalho, acho que se fico mais de 30 minutos tentando gerar a .lib para os includes eu me estresso. Ai parti para uma solução mais espartana, mas ao mesmo tempo simples e excelente.
Um simples parser identificando os tokens no texto e pronto.
O conceito é simples e parecido com leitores XML: uma maquina de estados para identificar o tipo de valor sendo lido, oque é relativamente fácil já que o JSON trabalha com pares (chave, valor). Ai você vai adicionando os caracteres lidos a uma string conforme a chave selecionada.