Aplicación de San Valentín en Libgdx

Cada año hay muchos artículos dedicados al Día de San Valentín. También decidí involucrarme en este tema y crear algo original e inusual. La idea era crear una aplicación de Android simple con corazones que tendrían sus modelos físicos e interactuarían entre sí. Luego agregué texto, sonidos, partículas y algunos otros efectos. ¡La aplicación resultante funcionaba y era bastante original! En este artículo describiré el proceso de creación, así como las capacidades y las dificultades de la biblioteca libgdx .


Corazones del día de san valentín .


Contenido



Programas y herramientas.


Para implementar esta idea, utilicé los siguientes programas y bibliotecas:


  1. IntelliJ IDEA : un IDE para aplicaciones multiplataforma. Alternativamente, puede usar Android Studio , Eclipse .
  2. libgdx : una biblioteca Java multiplataforma (PC, Mac, Linux, Android) para desarrollar juegos y otras aplicaciones gráficas. Esta biblioteca se distribuye bajo la licencia Apache 2.0. Algunos fragmentos de código se optimizaron utilizando JNI (por ejemplo, Box2d).
  3. box2d-editor : un editor para crear modelos físicos utilizados en el motor físico box2d , que está integrado en libgdx . Aquí se usará para hacer coincidir la imagen del corazón con su modelo físico.
  4. Generador de fuentes de mapa de bits Hiero : un programa para convertir fuentes vectoriales en ráster (ya que en libgdx solo se admiten fuentes ráster).
  5. Particle Editor : un editor para crear sistemas de partículas, desarrollado por el creador de libgdx . Se utiliza para partículas en el efecto de "explosión" durante la destrucción del corazón.
  6. Paint.NET : un editor de imágenes, se utilizó para editar la imagen del corazón y crear el fondo.

Todos estos programas y componentes se distribuyen libremente, y esta es una gran ventaja. libgdx porque, en primer lugar, ya tengo algo de experiencia con él y, en segundo lugar, usando libgdx no es necesario en un emulador lento de Android, ya que es multiplataforma y permite probar aplicaciones en un entorno nativo de Java y luego compilar ellos para Android.


Hola mundo


Primero, le diré en pocas palabras cómo crear proyectos libgdx. Usando gdx-setup.jar , genere una plantilla de proyecto (basada en Gradle), que especifica las plataformas de destino. Actualmente, Desktop , Android , Ios , Html son compatibles. Para ser honesto, no pude probar los dos últimos, ya que no tengo un dispositivo iOS y hay algunas dificultades con HTML que aún no he resuelto.


Proyecto


También puede seleccionar las extensiones que usará. En nuestro caso, esta es la biblioteca de física Box2d.


Sin embargo, todo esto se describe en la wiki: Creación de un proyecto libgdx .


Después de la generación, se crean tres carpetas:


  • núcleo
  • escritorio
  • androide

En los dos últimos, se colocan DesktopLauncher y AndroidLauncher respectivamente, que se ven así:


 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); } } 

No habrá más código específicamente para la plataforma Android, que es una gran ventaja de la biblioteca elegida. Solo queda permitir la vibración y deshabilitar el modo de suspensión (para evitar que se restablezca el estado de la aplicación) en la configuración de AndroidManifest.xml . Y también establezca la orientación horizontal para que el mundo no se ponga patas arriba:


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

y


 android:screenOrientation="landscape" 

El código común se almacena en la carpeta core . La clase principal llamada ValentinesDayHeartsApp implementa la interfaz ApplicationListener (para manejar eventos de inicialización, renderización, finalización y otros estados) y la interfaz InputProcessor (para manejar la entrada del usuario).


Eso es todo, ¡el esqueleto está listo! Ahora nuestra aplicación se ejecutará tanto en PC como en Android.


General


El proyecto tiene una estructura simple: en la clase ValentinesDayHeatsApp , se touchDown métodos create , render , dispose , touchDown . El método create inicializa todos los recursos (texturas, fuentes, partículas, sonidos) y crea el mundo físico. En el método de representación, se produce la representación de todos los objetos del mundo:


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

En el método dispose , se liberan todos los recursos. Sí, sí, a pesar del hecho de que Java tiene recolección de basura automática, los recursos no administrados (objetos Box2d y algunos otros) aún deben liberarse manualmente. El método touchDown se activa con un toque o un clic del mouse. Funciona así: si un punto de contacto se cruza con un corazón, el corazón se elimina. De lo contrario, se crea un nuevo corazón en el punto de contacto. El objeto Heart tiene las siguientes propiedades:


  • Body : un modelo físico.
  • Sprite : un modelo gráfico (sprite).
  • String : un texto que se muestra en el corazón.
  • Font : una fuente.
  • ParticleEffect partículas: partículas creadas al destruir el corazón.
  • BreakSound : un sonido de destrucción del corazón.

A continuación, describiré los componentes de la aplicación con más detalle.


Texturas


En primer lugar, necesitaba encontrar o dibujar el corazón. Afortunadamente, lo busqué en Google fácilmente y luego lo edité un poco: agregué un brillo y un fondo transparente. Para cargar texturas en libgdx , utilicé la clase Texture . Como la misma textura se puede usar varias veces, se usaron objetos Sprite adicionales. Fueron dibujados usando el método de render . La posición del sprite y el ángulo son los parámetros de representación y el modelo físico del corazón. Para variar, decidí dibujar los corazones en diferentes tonos. Utilicé la paleta HSL, que permite manipular el tono, la saturación y el aclarado, no componentes de color como RGB. La fórmula para la conversión RGB -> HSL y HSL -> RGB se puede encontrar fácilmente, y utilicé los métodos del artículo Manipulación de colores en .NET en Java. Todas las conversiones están en los prepareHeartsTextures , prepareHslData y generateHeartTexture . Aquí está el ejemplo:


 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; 

Desafortunadamente, la aplicación de Android comienza con algún retraso debido a la generación de texturas con diferentes tonos.


Fuentes


Como libgdx solo puede funcionar con fuentes ráster, utilicé Hiero Bitmap Font Generator (versión 5), que crea imágenes de todos los caracteres en formato PNG, y el archivo FNT, que contiene información sobre las coordenadas de cada carácter en la imagen. Aquí está la captura de pantalla de este programa:


Herramienta de fuente de mapa de bits


Después de que se generan los archivos necesarios, la fuente se puede usar en la aplicación libgdx de la siguiente manera:


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

Y luego renderizarlo así:


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

Al renderizar, encontré algunas dificultades: por ejemplo, la fuente no se puede representar en ángulo, ya que se puede hacer con un sprite. Para resolver este problema, debe cambiar la matriz de proyección de SpriteBatch y luego representar la fuente de la siguiente manera:


 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 motor de física, se utilizó box2d .


Para hacer coincidir la imagen del corazón con su modelo físico, utilicé box2d-editor :


Editor del cuerpo de física .


Usando este programa, creé un polígono del corazón, que se dividió automáticamente en polígonos convexos. El modelo físico es un conjunto de coordenadas de estos polígonos en formato JSON.


Además, este archivo se usa en nuestra aplicación (la carga se realiza en el método addHeart ). libgdx solo puede cargar archivos en formato binario. Afortunadamente, se encontró la clase BodyEditorLoader.java , que también se puede utilizar para cargar el modelo desde JSON (es decir, representación textual).


No olvide establecer la densidad, fricción y elasticidad del cuerpo:


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

¡Ahora nuestros corazones tienen un caparazón físico!


Para que los corazones no salgan volando de la pantalla, podemos agregar cuatro rectángulos estáticos a los lados de nuestro pequeño mundo. En dispositivos móviles, es recomendable establecer la gravedad en función de la orientación del 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


En libgdx , el sistema de partículas se especifica utilizando archivos especiales que se pueden generar en el editor:


Editor de partículas .


Como puede ver, este editor tiene una gran cantidad de configuraciones: puede cargar diferentes texturas, cambiar la vida útil, la forma de propagación, la transparencia y otros parámetros. Hice partículas en forma de corazón, que aparecerán cuando toques la pantalla y destruyas un gran corazón físico. En la aplicación, el trabajo con partículas ocurre de la siguiente manera:


Inicialización


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

Comienzo del ciclo de vida.


Es importante no olvidarse del start sin el cual las partículas no se mostrarán:


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

Suena


Los sonidos se cargan de la siguiente manera:


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

Y luego se juegan así:


 sound.play(1); 

¿Qué podría ser más fácil? Sin embargo, también hay dificultades. Por alguna razón, los archivos solo se pueden cargar en formato OGG y con una velocidad de bits de 96 kbit / s .


Conclusión


Espero que las técnicas descritas en este artículo sean útiles para muchos de ustedes para desarrollar juegos usando libgdx . Puede usar el código fuente y los recursos. Enviar aplicaciones para el Día de San Valentín a sus novios :)


Vale la pena señalar que el texto que se muestra en los corazones se puede cambiar en el archivo data/words.txt . Funciona incluso sin recompilación.


Código fuente y ejecutables


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


All Articles