A combinação do LittleJS, um motor de jogos 2D extremamente leve, com o Electron, permite que desenvolvedores transicionem projetos web para aplicativos nativos multiplataforma. Este guia aborda a arquitetura e a implementação necessária para empacotar um jogo baseado em LittleJS como um software de desktop.
Configuração do Ambiente de Desenvolvimento
Antes de iniciar, certifique-se de ter as seguintes ferramentas instaladas:
- Node.js (versão 16 ou superior recomendada)
- Gerenciador de pacotes npm ou Yarn
- Git
Clone o repositório base e navegue até o diretório do projeto:
git clone https://github.com/example/littlejs-desktop-template.git
cd littlejs-desktop-template
Arquitetura do Projeto
A estrutura de um aplicativo Electron integrado com LittleJS segue o modelo de processo principal e processo de renderização. Os arquivos essenciais incluem:
main.js: Gerencia o ciclo de vida do aplicativo e as janelas do sistema operacional.package.json: Define metadados, dependências e scripts de automação.index.html: Ponto de entrada do processo de renderização que carrega o motor e os asssets.src/game-logic.js: Contém a lógica do jogo escrita com a API do LittleJS.
Executando o Projeto Localmente
Para testar a integração em seu ambiente local, instale as dependências e inicie o processo do Electron:
npm install
npm run start:desktop
Isso abrirá uma janela nativa renderizando o canvas do LittleJS sem a interface do navegador.
Configurações Essenciais
1. Definição do package.json
O arquivo de configuração deve apontar corretametne para o script do processo principal:
{
"name": "littlejs-native-app",
"version": "2.1.0",
"main": "main.js",
"scripts": {
"start:desktop": "electron .",
"build:desktop": "electron-builder --win --mac --linux"
}
}
2. Processo Principal (main.js)
O script do processo principal é responsável por instanciar a janela e carregar o arquivo HTML. Abaixo está uma implementação otimizada com isolmaento de contexto:
const { app, BrowserWindow } = require('electron');
const path = require('path');
function createGameWindow() {
const gameWindow = new BrowserWindow({
width: 1024,
height: 768,
resizable: false,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false
}
});
gameWindow.loadFile('index.html');
}
app.whenReady().then(createGameWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
3. Integração do HTML e Motor
O arquivo index.html atua como a camada de renderização, importando o motor e a lógica do jogo:
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>LittleJS Desktop</title>
<style>
body { margin: 0; background: #111; overflow: hidden; }
canvas { display: block; }
</style>
</head>
<body>
<script src="./lib/littlejs.min.js"></script>
<script src="./src/game-logic.js"></script>
</body>
</html>
Empacotamento para Distribuição
Para gerar instaladores nativos (.exe, .dmg, .AppImage), utilize o electron-builder. Após adicionar a ferramenta como dependência de desenvolvimento (npm install electron-builder --save-dev), execute o script de build:
npm run build:desktop
Os artefatos compilados serão gerados no diretório dist/, prontos para distribuição.
Otimizações e Recursos Avançados
Alternância de Tela Cheia via HTML5 API
Em vez de expor objetos do Electron ao processo de renderização, utilize a API nativa de Fullscreen do HTML5 dentro da sua lógica de jogo (game-logic.js) para alternar o modo de exibição:
function handleFullscreenToggle() {
// Exemplo usando a API de input do LittleJS
if (engineInput.keyIsDown('KeyF')) {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else {
document.exitFullscreen();
}
}
}
Aceleração de Hardware
Para jogos com muitas partículas ou shaders complexos, force a aceleração de hardware no processo principal antes de criar a janela:
app.commandLine.appendSwitch('ignore-gpu-blacklist');
app.commandLine.appendSwitch('enable-gpu-rasterization');
Resolução de Caminhos de Assets
Ao carregar texturas e áudios no LittleJS dentro do Electron, utilize caminhos relativos baseados no diretório atual para evitar erros de protocolo file://:
const assetBasePath = window.location.origin + '/assets/';
engineInit(gameInit, gameUpdate, gameRender, { image: assetBasePath + 'sprites.png' });