📜 ⬆️ ⬇️

The app in honor of Valentine's Day on libgdx

Hi, Habr!

I remembered here recently that soon Valentine's Day and on Habré a year ago (and not only) there were some topics related to it. I decided to support this tradition and do something original and unusual this year, and later write a topic about it.

And I decided to create a simple Android application with hearts that would have their own physical models and interact with each other. It was easily and quickly implemented. Next, I added to all this zoo text, sounds, particles, and some other beautiful. As a result, I even got something sane and original, which I will hasten to talk about in this article, and at the same time promote the description of the excellent cross-platform library libgdx .
')


At the end of the topic, the source of the projects, the jar executable file and some utilities are laid out so that you can’t google again. Further - under cat.

To implement my ideas, I used the following programs and libraries:
  1. Eclipse is a free integrated development environment for modular cross-platform applications. Actually on what we will all kodit and compile. IntelliJ IDEA and NetBeans are also possible.
  2. ADT Plugin for Eclipse - plugin for eclipse, which allows you to create and compile projects for Android.
  3. libgdx - cross-platform (PC, Mac, Linux, Android) Java-library for game development and more. This library is distributed under the Apache License 2.0. Some parts of the code are optimized using JNI (for example, Box2d).
  4. box2d-editor - An editor for creating physical models used in the physical box2d engine that is built into libgdx. Here it will be used to compare the pattern of the heart and its physical model.
  5. Hiero bitmap font generator - Program for converting vector fonts into raster (since only such can be used in libgdx).
  6. Particle Editor is an editor for creating particle systems, written by libgdx. We will use it to create an effect during the destruction of the heart.
  7. Paint.NET I used to edit the image of the heart found on the Internet, and create the background.

As you can see, all programs and components are free, and this is a big plus.

I chose the libgdx library, because, firstly, I already have some experience with it (I am writing a game for android now), and, secondly, when using it, there is no need for a decelerated android emulator, since it is cross-platform and allows you to test applications in native java environment, followed by compilation under the green.

libgdx "Hello World"


So, first, I will briefly explain how to create projects on libgdx in eclipse. For the desktop, a regular Java project is created (File -> New -> Java Project) and the necessary external libgdx libraries are added (Right click on the project -> Java Build Path -> Libraries). There are four of them:
gdx.jar, gdx-backend-jogl.jar, gdx-backend-jogl-natives.jar, gdx-natives.jar .

Then an Android project is created (File -> New -> Other -> Android Project), libraries are added in the same way (now gdx.jar , gdx-backend-android.jar , as well as armeabi and armeabi-v7a ). Then a link is added to our first created project (Right click on the project -> Java Build Path -> Projects).

After that, in the first project (let it be called ValentinesDayHearts), you need to create a class ValentinesDayHearts , which will implement the ApplicationListener interfaces (for handling initialization events, render, finalization and other states), as well as InputProcessor (in order to handle user input).

Next, create the DesktopStarter class with the main entry point:
public static void main(String[] args) { new JoglApplication(new ValentinesDayHearts(), "Valentine's Day Hearts", 800, 480, false); } 

And in the project for Android, ValentinesDayHeartsActivity is created:
 public class ValentinesDayHeartsActivity extends AndroidApplication { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initialize(new ValentinesDayHearts(), false); } } 

More code in the android project will not.

The only thing you need to add permissions (permissions) to the configuration of the Android application (vibration and prohibition of sleep mode, so that the state of the application is not reset), as well as to set the landscape orientation (so that the world does not turn over):
 <uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> 

and
 android:screenOrientation="landscape" 


All frame ready! Now this application will be compiled for PC and Android.

General


This application is small in size and has a simple structure: in the ValentinesDayHeats class, the methods create, render, dispose, touchDown are overloaded .

In the create method, initialization of all resources (textures, fonts, particles, sounds), creation of the physical world takes place.

In the render method, the rendering and rendering of all objects of the world occurs:
 @Override public void render() { updatePhysics(); updateBackground(); updateSprites(); updateParticles(); refresh(); renderBackground(); renderHearts(); renderFonts(); renderParticles(); } 

In the dispose method, the release of all resources. Yes, yes, despite the fact that java has garbage collection, unmanaged resources (Box2d objects and some others) should still be freed up manually. True, due to the rush, I didn’t really bother with that.

The touchDown method is triggered by clicking the mouse or touching the touchscreen. If the point of contact intersects with some heart, it is removed. Otherwise, a new heart is created in the place of the click.

The Heart object has the following properties:
  1. Body is a physical model.
  2. Sprite - graphic model (sprite).
  3. String - the text displayed on the heart.
  4. Font - the font that draws the text.
  5. ParticleEffect - created by the destruction of particles.
  6. BreakSound - sound when destroyed.

Next, I will briefly describe the aspects of the application being developed.

Textures


The primary task was to search or create graphic resources. Without thinking twice, I googled the heart image and slightly edited it a bit (added glow and made a transparent background).

To load textures in libgdx, the Texture class is used, but since the same texture can be used several times, additional Sprite objects are introduced. Sprites are rendered in the render method. The drawing parameters are the position of the sprite and its angle. These parameters are the parameters of the physical model of the heart.

For a change, I decided to make the hearts have not the same colors, but colors with different shades. For this, I used the HSL palette, which allows you to manipulate hue, saturation and lightening, and not directly colors in RGB. The RGB -> HSL and HSL -> RGB conversion formula can be easily google, and I rewrote the methods of a certain C # library in Java. In my code, all color conversions are in the prepareHeartsTextures , prepareHslData, and generateHeartTexture methods.

Here is an example of one of the methods:
 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; 

By the way, due to these generations of textures with different shades, the Android application loads with some delay.

Fonts


Since libgdx can work only with raster fonts, I used the Hiero Bitmap Font Generator program, which creates images of all characters in the png format and an fnt file, which contains information about the coordinates of each character in the image.

Here is the screen of this program (not your own, because it stopped working for me):



After the necessary files are generated, the font can be used in our libgdx application as follows:
 font = new BitmapFont( Gdx.files.internal("data/Jura-Medium.fnt"), Gdx.files.internal("data/Jura-Medium.png"), false); font.setColor(Color.WHITE); 

and then render it like this:
 font.draw(spriteBatch, heart.String, screenPosition.x, screenPosition.y); 

When rendering, I encountered some subtleties: for example, the font cannot be rendered at an angle, as can be done with a sprite. To solve this problem, you need to change the projective matrix of SpriteBatch, and then render the font as follows:
 projection.translate(rotationCenter.x, rotationCenter.y, 0); projection.rotate(0, 0, 1, body.getAngle() / (float)Math.PI * 180); projection.translate(-rotationCenter.x, -rotationCenter.y, 0); spriteBatch.begin(); font.setScale(heart.Size.x * FontSizeHeartSizeCoef.x, heart.Size.y * FontSizeHeartSizeCoef.y); font.draw(spriteBatch, heart.String, screenPosition.x, screenPosition.y); font.setScale(1, 1); spriteBatch.end(); 

Physics


I think that on box2d anyone can find a lot of materials on the Internet. So I will not dwell on it in detail, but rather I will talk about the interaction of libgdx and box2d and the creation of a physical model for the heart.

To compare the graphical and physical models, I used box2d-editor:



At first I did not understand how to do something there, but after looking in the help and poking a little on the buttons , I figured it out.

This program generates a file in the formats bin, xml or json. Further, these files are used in the application (loading occurs in the addHeart method).

When loading models, I ran into the problem that loaded bodies do not rotate. A little googling, I realized that for this they need to set the density, friction and elasticity. But this action did not fix the problem. Later, a solution was found after all: after assigning the above characteristics to the body, you need to call the resetMassData function:
 BodyDef heartBodyDef = new BodyDef(); heartBodyDef.type = BodyType.DynamicBody; heartBodyDef.angle = ..; heartBodyDef.position.x = ..; heartBodyDef.position.y = ..; Body body = world.createBody(heartBodyDef); fixtureAtlas.createFixtures(body, "heart.png", newWidth, newHeight); for (int j = 0; j < body.getFixtureList().size(); j++) { Fixture fixture = body.getFixtureList().get(j); fixture.setFilterData(filter); fixture.setFriction(0.75f); fixture.setDensity(1.0f); fixture.setRestitution(0.4f); } body.resetMassData(); 


In order for the hearts not to fly off the screen, four static rectangles are simply created on the sides of our little world.

On Android phones, it would be nice to change gravity depending on the orientation of the phone, I thought. No sooner said than done:
 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); } 

Particle system


In libgdx, the particle system is specified using special files that can be generated in the editor:



As you can see, this editor has a lot of settings: you can load different textures, change the lifetime, the form of distribution, transparency, and many others.
I made particles in the form of hearts, which will appear when you press and destroy one physical heart.

In the application I work with particles as follows:


Sounds


Sounds are loaded like this:
 sound = Gdx.audio.newSound(Gdx.files.internal(  )); 

and then played like this:
 sound.play(1); 


It would seem, what could be easier? But no - here, too, has its pitfalls.
The fact is that for some reason I only downloaded files in the .ogg format and the bitrate of 96 kbit / s . I do not know why, but loading other files did not work.

Conclusion


I certainly understand that the text was not very interesting, coherent and formatted, but this was due to the fact that I wrote it in a hurry - I wanted to have time for Valentine's Day on the one hand, and to highlight as many aspects and nuances as possible on the other. .
I think that this knowledge will be useful to many, and they will be useful in the future for developing a game using libgdx.

Also, do not really scold for the design and sounds - also in a hurry, so maybe somewhere I picked the wrong colors, texture, sound. But I am ready to listen to any constructive criticism and by code too :)

I allow everyone to use my sources and resources, modify them with a file and give ready-made applications for Valentine's Day to their halves :)

PS All words displayed on the hearts can be changed in the data / words.txt file even without recompilation.

PPS In the Market did not lay out, because it is the UG, whom the whole market is littered with .

Update (February 13, 21:56) Fixed a bug with running under the x86 system. Fixed bug with resolution (for smartphones).

Sources, executables and utilities


jar executable file
apk file for android
Sources
Editor of physical models, fonts and particles

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


All Articles