6 KiB
Sand box Python
Este projeto foi desenvolvido em pouco mais de 2 dias durante um fim de semana. A principal motivação para sua criação foi a nostalgia de um jogo de navegador da minha infância, o Powder Game. O objetivo foi criar algo semelhante ao jogo original, embora, no meu projeto, existam apenas 6 tipos diferentes de elementos, em contraste com a grande variedade do jogo original.
Índice
- Sand Box Python
- Dificuldades e Como As Contornei
- Como Executar e Instalar
- Configurando Propriedades
- Elementos
- Contribuições
- Licença
- Contato
Dificuldades e Como As Contornei
A ideia original era desenvolver o jogo em uma engine como Unity ou Unreal. No entanto, devido ao tempo limitado, optei por usar uma tecnologia com a qual já tinha familiaridade: Python.
Problemas
O principal problema surgiu ao tentar iniciar o jogo com Python puro, usando arrays nativos para uma tela de 500x500 pixels, resultando em um array com 250.000 itens. Percorrer cada item a cada quadro resultava em um desempenho muito ruim, com apenas 1 a 5 fps sem mencionar o uso de memória, que era gigantesco.
Solução Parcial
Para melhorar a performance, substituí o array nativo por um array do NumPy, que oferece vantagens significativas em termos de desempenho e uso de memória. Cada pixel foi representado por 5 números uint8, o que resultou em uma melhoria modesta, alcançando 5 a 10 fps, mas ainda não o suficiente para uma jogabilidade aceitável.
por que 5 numeros?
class Types(Enum):
BG = (0, 0, 0, 0, 0)
SAND = (203, 189, 147, 1, 0)
WATER = (28, 163, 236, 2, 0)
STONE = (115, 112, 112, 3, 0)
VACUUM = (20, 20, 20, 4, 0)
CLONER = (108, 60, 12, 5, 0)
- Os três primeiros números representam a cor do pixel, permitindo leves variações dentro do mesmo elemento.
- O quarto valor é o ID do pixel, por exemplo, o ID da água é 2.
- O último valor é para dados adicionais, utilizado principalmente pelo elemento "cloner", mas pode ser usado para outros tipos de elementos, se necessário.
Dessa forma, cada pixel na minha tela é representado por 5 números uint8, totalizando 5 bytes por pixel. Para um array de 250.000 pixels, isso resulta em 1.250.000 bytes ou 1,25 MB, um valor baixo e eficiente.
python + numpy 320 x 320 exemplo AVG: 7 fps
Solução Final
Recentemente, descobri a possibilidade de compilar código em tempo de execução (JIT) usando Numba. Embora o Numba tenha algumas limitações quanto aos tipos de dados que pode manipular, consegui adaptar o código para utilizá-lo. Isso resultou em um aumento drástico na performance, elevando a taxa de quadros para 150 a 200 fps, tornando o jogo jogável.
python + numpy + numba 1000 x 1000 exemplo AVG: 120 fps
Como Executar e Instalar
# Clone o repositório
git clone https://github.com/LucasKalil-Programador/sand-box-python.git
# Acesse a pasta do projeto
cd sand-box-python
# Crie um novo ambiente virtual
python -m venv .venv
# Ative o ambiente virtual
# No Windows:
.venv\Scripts\activate
# No macOS/Linux:
source .venv/bin/activate
# Atualize o pip para a versão mais recente
python -m pip install --upgrade pip
# Instale as dependências do projeto
pip install .
# Execute o código
python main.py
configurando propiedades
Para ajustar as configurações básicas do jogo, abra o arquivo main.py. No final do arquivo, você encontrará a instância da classe Game, onde é possível modificar as propriedades. Veja o exemplo abaixo:
game = Game(size=(160, 160), fps=120, scale=4, font_size=30, test_mode=False)
game.run()
size: Define o tamanho da tela como uma tupla (largura, altura).scale: Define o multiplicador do tamanho da janela. Por exemplo, com size=(160, 160) e scale=4, a janela será de 640x640 pixels (160 * 4).fps: Define a taxa de quadros por segundo.font_size: Define o tamanho da fonte.test_mode: Ativa ou desativa o modo de teste. Quando ativado, um elemento aleatório é gerado em um local aleatório a cada quadro, o que é útil para testar a performance e a estabilidade.
Elementos e Controle
Backgroundelemento padrao nao possui nenhum efeito especialSandcomportase como areia possui gravidade e afunda na aguaWatersimula um fluido portanto tende a se acomodar e escorrer em superficiesStoneelemento estatico nao se move e impede a passagem de outros elementoVacuumexclui elementos que entram em contatoClonercopia o primeiro elemento que o toca e gera mais desse elemento a cada quadro
Controle
- Números de
1 a 6controlam o elemento selecionado, seguindo a ordem anterior. - Use o botão esquerdo do mouse para gerar (spawn) o novo elemento.
- Pressione a tecla
+para aumentar o tamanho do spawn e-para diminuir. - Segure
CTRL++ouCTRL+-para aumentar ou diminuir o tamanho do spawn em incrementos de 10.
exemplo
Contribuições
Infelizmente, este projeto está descontinuado. Caso você queira fazer alguma adição ou melhoria, sinta-se à vontade para fazer um fork e modificar o código para uso próprio.
Licença
Este projeto está licenciado sob a Licença MIT - veja o arquivo LICENSE para mais detalhes.
Contato
Lucas - lucas.prokalil2020@outlook.com
Repositório no GitHub: sand-box-python


