Bastidores: o Sudoku nativo para iOS e o que ele ensinou sobre arquitetura de jogos
Nem todo projeto do Guima Games roda no navegador. Antes e em paralelo aos jogos HTML5 deste portal, também desenvolvo aplicativos nativos para iOS, área em que trabalho há muitos anos. Um deles é um Sudoku escrito inteiramente em Swift e SwiftUI.
Ele não está disponível para jogar aqui no portal, que é dedicado a jogos web. Este artigo é um bastidor: como o app foi organizado e quais ideias dele acabaram migrando para os jogos que você encontra na página de jogos.
No momento o Sudoku é utilizado para estudos iOS.
Primeiras tentativas
O primeiro contato com o game foi em um Aeroporto, onde comprei uma revista de passa tempo, e achei que era caça palavras ou coisa parecida, e eram fases de um Sudoku, que eu nem conhecia. O tempo voou, em 1 hora e meia, deu pra aprender e fazer alguns. Na Sixtech, fiz um teste em C++, e fazia testes para levar ao XNA, quando lancei um desafio ao Pastro, um dos sócios da Six, e ele fez o game muito melhor que eu, em uma matriz, que resolvia diversos Sudoku's ... o meu era muito mais simples, mas achei a solução dele muito mais interessante, já preparada para várias fases. Implementei variações dela para estudos com Swift.
Por que um Sudoku é um bom projeto de arquitetura
Sudoku tem regras simples e completamente determinísticas: uma grade 9×9 em que cada linha, cada coluna e cada bloco 3×3 precisa ter os números de 1 a 9 sem repetição. Não há física, inimigos nem sorte durante a partida.
Isso o torna um ótimo laboratório de arquitetura. Toda a complexidade está no estado: quais células estão preenchidas, quais o jogador anotou a lápis, quantos erros ele cometeu, quanto tempo passou, o que dá para desfazer. Um jogo assim fica fácil ou impossível de manter dependendo de como esse estado é organizado.
A organização em MVVM
O app segue o padrão MVVM (Model–View–ViewModel), que separa o jogo em três camadas com responsabilidades bem definidas.
Model: as regras
SudokuGame.swift e SudokuLevel.swift descrevem a grade 9×9 e sabem validar as regras: se um número pode ou não ficar numa célula, considerando a linha, a coluna e o bloco 3×3. O Model também guarda as notas, os números pequenos que o jogador marca como candidatos antes de decidir.
O Model não sabe nada sobre telas, cores ou toques. Ele só responde perguntas como "este movimento é válido?".
ViewModel: o estado da partida
SudokuViewModel.swift é quem coordena a partida:
- mantém o temporizador;
- conta os erros;
- guarda o histórico para desfazer (undo) cada jogada;
- expõe tudo isso para a interface como estado observável, de forma que qualquer mudança redesenha só o que precisa.
View: a interface declarativa
ContentView.swift e CellView.swift são interfaces em SwiftUI. Elas não decidem nada: descrevem como a tela deve ficar para um dado estado. Quando o ViewModel muda, a SwiftUI atualiza a célula afetada.
Detalhes que só aparecem num app nativo
Dois cuidados do app não têm equivalente direto na web:
- O teclado que empurra a grade. Em iPhones menores, a barra de números ocupa boa parte da tela. Um
KeyboardObserver.swiftdetecta quando ela aparece e reajusta o layout, para que a célula selecionada nunca fique escondida. - Feedback háptico. Quando o jogador insere um número incorreto, o aparelho vibra de leve pelo Taptic Engine. O erro é percebido pelo toque, sem precisar de um alerta na tela interrompendo o raciocínio.
O que migrou para os jogos web
A separação entre regras, estado da partida e interface do Sudoku é a mesma ideia que aparece nos jogos do portal, só que com outras ferramentas. O GGColors, por exemplo, concentra toda a lógica numa máquina de estados que bloqueia a entrada do jogador fora da sua vez. O funcionamento é explicado em GGColors por dentro.
Para conhecer a trajetória completa do estúdio, do primeiro adventure em modo texto em C++ até os jogos em WebGL, leia A história do Guima Games.