Aplicativo do dia dos namorados no Libgdx

Todos os anos, há muitos artigos dedicados ao Dia dos Namorados. Também decidi me envolver neste tópico e criar algo original e incomum. A ideia era criar um aplicativo Android simples com corações que tivessem seus modelos físicos e interagissem entre si. Então eu adicionei texto, sons, partículas e alguns outros efeitos. O aplicativo resultante estava funcionando e bastante original! Neste artigo, descreverei o processo de criação, bem como os recursos e as armadilhas da biblioteca libgdx .


Corações do dia dos namorados .


Conteúdo



Programas e ferramentas


Para implementar essa ideia, usei os seguintes programas e bibliotecas:


  1. IntelliJ IDEA - um IDE para aplicativos de plataforma cruzada. Como alternativa, você pode usar o Android Studio , Eclipse .
  2. libgdx - uma biblioteca Java de plataforma cruzada (PC, Mac, Linux, Android) para desenvolvimento de jogos e outros aplicativos gráficos. Esta biblioteca é distribuída sob a Licença Apache 2.0. Alguns trechos de código foram otimizados usando JNI (por exemplo, Box2d).
  3. box2d-editor - um editor para criar modelos físicos usados ​​no mecanismo físico box2d , incorporado ao libgdx . Aqui será usado para combinar a imagem do coração com seu modelo físico.
  4. Hiero bitmap font generator - um programa para converter fontes vetoriais em raster (uma vez que na libgdx apenas fontes raster são suportadas).
  5. Particle Editor - um editor para a criação de sistemas de partículas, desenvolvido pelo criador da libgdx . É usado para partículas no efeito "explosão" durante a destruição do coração.
  6. Paint.NET - um editor de imagens, foi usado para editar a imagem do coração e criar o plano de fundo.

Todos esses programas e componentes são distribuídos gratuitamente, e essa é uma grande vantagem. Eu escolhi a libgdx , porque, em primeiro lugar, já tenho alguma experiência com ela e, em segundo lugar, usando a libgdx você não precisa de um emulador lento do Android, pois é multiplataforma e permite testar aplicativos no ambiente Java nativo e depois compilar para Android.


Olá mundo


Primeiro, vou dizer em poucas palavras como criar projetos libgdx. Usando gdx-setup.jar , gere um modelo de projeto (baseado em Gradle), que especifica as plataformas de destino. Atualmente, Desktop , Android , Ios , Html são suportados. Para ser sincero, não tentei os dois últimos, pois não tenho um dispositivo iOS, e há algumas dificuldades com o HTML que ainda não resolvi.


Projetos


Você também pode selecionar as extensões que usará. No nosso caso, esta é a biblioteca de física Box2d.


No entanto, tudo isso é descrito no wiki: Criando um projeto libgdx .


Após a geração, três pastas são criadas:


  • núcleo
  • área de trabalho
  • andróide

Nos últimos dois, DesktopLauncher e AndroidLauncher respectivamente, são colocados, com a seguinte aparência:


 public class DesktopLauncher { public static void main (String[] arg) { LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); config.width = 800; config.height = 480; new LwjglApplication(new ValentinesDayHeartsApp(), config); } } 

 public class AndroidLauncher extends AndroidApplication { @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); initialize(new ValentinesDayHeartsApp(), config); } } 

Não haverá mais código específico para a plataforma Android, o que é uma grande vantagem da biblioteca escolhida. Resta apenas permitir vibração e desativar o modo de suspensão (para impedir que o estado do aplicativo seja redefinido) na configuração AndroidManifest.xml . E também defina a orientação da paisagem para que o mundo não vire de cabeça para baixo:


 <uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> 

e


 android:screenOrientation="landscape" 

O código comum é armazenado na pasta core . A classe principal chamada ValentinesDayHeartsApp implementa a interface ApplicationListener (para manipular eventos de inicialização, renderização, finalização e outros estados) e a interface InputProcessor (para manipular a entrada do usuário).


Isso é tudo, o esqueleto está pronto! Agora, nosso aplicativo será executado no PC e no Android.


Geral


O projeto possui uma estrutura simples: na classe ValentinesDayHeatsApp , os métodos create , render , touchDown , touchDown são substituídos. O método create inicializa todos os recursos (texturas, fontes, partículas, sons) e cria o mundo físico. No método de renderização, a renderização de todos os objetos do mundo ocorre:


 @Override public void render() { updatePhysics(); updateBackground(); updateSprites(); updateParticles(); refresh(); renderBackground(); renderHearts(); renderFonts(); renderParticles(); } 

No método de dispose , todos os recursos são liberados. Sim, sim, apesar do Java ter coleta automática de lixo, os recursos não gerenciados (objetos Box2d e outros) ainda precisam ser liberados manualmente. O método touchDown é acionado por um toque ou um clique do mouse. Funciona assim: se um ponto de contato se cruza com um coração, o coração é excluído. Caso contrário, um novo coração é criado no ponto de contato. O objeto Heart tem as seguintes propriedades:


  • Body - um modelo físico.
  • Sprite - um modelo gráfico (sprite).
  • String - um texto exibido no coração.
  • Font - uma fonte.
  • ParticleEffect partícula - partículas criadas ao destruir o coração.
  • BreakSound - um som de destruir o coração.

A seguir, descreverei os componentes do aplicativo em mais detalhes.


Texturas


Antes de tudo, eu precisava encontrar ou desenhar o coração. Felizmente, pesquisei facilmente no Google e editei um pouco: adicionei um brilho e um fundo transparente. Para carregar texturas na libgdx , usei a classe Texture . Como a mesma textura pode ser usada várias vezes, objetos adicionais do Sprite foram usados. Eles foram desenhados usando o método de render . A posição do sprite e o ângulo são os parâmetros de renderização e o modelo físico do coração. Para variar, decidi desenhar os corações em diferentes tons. Usei a paleta HSL, que permite manipular matiz, saturação e iluminação, não componentes de cores como RGB. A fórmula para a conversão RGB -> HSL e HSL -> RGB pode ser facilmente encontrada, e eu usei os métodos do artigo Manipulando cores no .NET on Java. Todas as conversões estão nos prepareHeartsTextures , prepareHslData e generateHeartTexture . Aqui está o exemplo:


 Pixmap pixmap = new Pixmap(fileHandle); float[][][] result = new float[pixmap.getWidth()][pixmap.getHeight()][4]; for (int i = 0; i < pixmap.getWidth(); i++) for (int j = 0; j < pixmap.getHeight(); j++) { int color = pixmap.getPixel(i, j); float r = (float)((color >> 24) & 0xFF) / 255.0f; float g = (float)((color >> 16) & 0xFF) / 255.0f; float b = (float)((color >> 8) & 0xFF) / 255.0f; float a = (float)(color & 0xFF) / 255.0f; result[i][j] = ColorUtils.RgbToHsl(r, g, b, a); } return result; 

Infelizmente, o aplicativo Android inicia com algum atraso devido à geração de texturas com tons diferentes.


Fontes


Como a libgdx pode funcionar apenas com fontes raster, usei o Hiero Bitmap Font Generator (versão 5), que cria imagens de todos os caracteres no formato PNG e o arquivo FNT, que contém informações sobre as coordenadas de cada caractere na imagem. Aqui está a captura de tela deste programa:


Ferramenta de fontes Bitmap


Após a geração dos arquivos necessários, a fonte pode ser usada no aplicativo libgdx da seguinte maneira:


 font = new BitmapFont( Gdx.files.internal("data/Jura-Medium.fnt"), Gdx.files.internal("data/Jura-Medium.png"), false); font.setColor(Color.WHITE); 

E então renderize assim:


 font.draw(spriteBatch, heart.String, screenPosition.x, screenPosition.y); 

Ao renderizar, encontrei algumas dificuldades: por exemplo, a fonte não pode ser renderizada em ângulo, como pode ser feita com um sprite. Para resolver esse problema, você precisa alterar a matriz de projeção do SpriteBatch e renderizar a fonte da seguinte maneira:


 Matrix4 projection = spriteBatch.getProjectionMatrix(); projection.setToOrtho2D(0, 0, WorldWidth, WorldHeight); projection.translate(tmpVector1.x, tmpVector1.y, 0); projection.rotate(0, 0, 1, body.getAngle() / (float)Math.PI * 180); projection.translate(-tmpVector1.x, -tmpVector1.y, 0); Vector2 stringSize = heart.getStringSize(); tmpVector1.add(heart.Size.x / PhysWorldWidth * WorldWidth * CenterDisplacement.x - stringSize.x * 0.5f, heart.Size.y / PhysWorldHeight * WorldHeight * CenterDisplacement.y + stringSize.y); spriteBatch.begin(); BitmapFont.BitmapFontData fontData = font.getData(); fontData.setScale(heart.Size.x * FontSizeHeartSizeCoef.x, heart.Size.y * FontSizeHeartSizeCoef.y); font.draw(spriteBatch, heart.String, tmpVector1.x, tmpVector1.y); fontData.setScale(1, 1); spriteBatch.end(); 

Física


Como um mecanismo de física, o box2d foi usado.


Para combinar a imagem do coração com seu modelo físico, usei o box2d-editor :


Editor do corpo de física .


Usando este programa, criei um polígono do coração, que foi automaticamente quebrado em polígonos convexos. O modelo físico é um conjunto de coordenadas desses polígonos no formato JSON.


Além disso, esse arquivo é usado em nosso aplicativo (o carregamento ocorre no método addHeart ). A libgdx pode carregar apenas arquivos em formato binário. Felizmente, foi encontrada a classe BodyEditorLoader.java , que também pode ser usada para carregar o modelo a partir do JSON (isto é, representação textual).


Não se esqueça de definir a densidade, fricção e elasticidade do corpo:


 FixtureDef fdef = new FixtureDef(); fdef.density = 0.75f; fdef.friction = 1.0f; fdef.restitution = 0.4f; bodyLoader.attachFixture(body, "Heart", fdef, newWidth); body.resetMassData(); 

Agora nossos corações têm uma concha física!


Para que os corações não voem para fora da tela, podemos adicionar quatro retângulos estáticos nas laterais do nosso pequeno mundo. Em dispositivos móveis, é aconselhável definir a gravidade com base na orientação do dispositivo:


 if (Gdx.app.getType() == ApplicationType.Android) { gravity.x = -Gdx.input.getPitch() / 90.0f; gravity.y = Gdx.input.getRoll() / 90.0f; gravity.mul(gravityCoef); world.setGravity(gravity); } 

Sistema de partículas


Na libgdx , o sistema de partículas é especificado usando arquivos especiais que podem ser gerados no editor:


Editor de partículas .


Como você pode ver, este editor possui muitas configurações: você pode carregar diferentes texturas, alterar a vida útil, a forma de espalhamento, a transparência e outros parâmetros. Criei partículas em forma de coração, que aparecerão quando você tocar na tela e destruir um grande coração físico. No aplicativo, o trabalho com partículas ocorre da seguinte maneira:


Inicialização


 ParticleEffect effect = new ParticleEffect(); effect.load(Gdx.files.internal("data/destroy.p"), Gdx.files.internal("data")); 

Início do ciclo de vida


É importante não esquecer o start sem o qual as partículas não serão exibidas:


 effect.setPosition(.., ..); effect.start(); 

Sons


Os sons são carregados da seguinte maneira:


 sound = Gdx.audio.newSound(Gdx.files.internal("path/to/file")); 

E então são jogados assim:


 sound.play(1); 

O que poderia ser mais fácil? No entanto, também existem armadilhas. Por alguma razão, os arquivos podem ser carregados apenas no formato OGG e taxa de bits de 96 kbit / s .


Conclusão


Espero que as técnicas descritas neste artigo sejam úteis para muitos de vocês no desenvolvimento de jogos usando a libgdx . Você pode usar o código fonte e os recursos. Envie pedidos de Dia dos Namorados para seus namorados :)


Vale ressaltar que o texto exibido nos corações pode ser alterado no arquivo data/words.txt . Funciona mesmo sem recompilação.


Código fonte e executáveis


Source: https://habr.com/ru/post/pt440298/


All Articles