Good day, dear habrazhiteli.
I wanted to write games from the moment I started programming. And so, I decided to try my hand at writing games on Android.
I made the game in the fall and put it in the market. True, it was removed, as the rights to Bomberman'a Konami. But the article, of course, is not about that.
In parallel with the development of the game, he wrote tutorials on LibGDX, and constantly people asked to lay out the source code. I decided to share them and tell a little about the development. Maybe someone will help in the study of LibGDX. Link to the source repository at the bottom of the article.

Small retreat
Before that I had no experience with Java, and even more so with Android. I decided to study both on a practical task. I didn't really want to write my own engine on pure OpenGL. There was not much difference on which engine to develop the game. Something I liked LibGDX, I decided to start with it. So, do not judge too harshly. There was no special plan or TK. As soon as I understood Libe, I also slowly wrote a game.
')
Architecture
For architecture, it seemed to me, MVC is best suited. I have already talked about this in the article about
architecture .
In general, everything is quite simple and clear. The main game class
BomberMan
inherited from
Game
. It contains links to all possible game screens: the game itself, the main menu, the window on victory, etc. We only need to switch between these classes using the
setScreen()
method.
As a View, we have classes that implement the Screen and InputProcessor interfaces (switching between them in the
BomberMan
class). In the class, we handle user actions and render objects. Change of objects and the subsequent drawing happens in one method of this class. First, we change the state of objects, if necessary (roughly speaking, we work with physics), and then render:
@Override public void render(float delta) { controller.update(delta); renderer.render(); }
The controller, I think it is clear, works with the model. Most of the logic is in it. He was not quite sure where to push the logic. As a result, part of the logic transferred to the objects themselves (handling of collisions), and the logic of processing explosions, murders (that is, when objects need to influence other objects) in the controller. There was an idea to implement this with messages. That is, in each object, define a handler that will process the messages and react in some way. But then the problem with synchronization arose. Therefore, I decided to process everything synchronously.
As a result, in the controller we simply consistently work with all the objects of the world:
public void update(float delta) { processInput(); checkBombsTimer(); if(!world.bonus) destroyBricks(); removeDeadNpc(); killByBoom(); removeHiddenObjects(); bomberman.update(delta); for(NpcBase npc : world.getNpcs()){ npc.update(delta); } removeBooms(); }
To explain the model, I think, it is easier to provide a diagram:

World
is a container that contains all objects: blocks, bonuses, player, npc. There is no logic in it. Only in the objects themselves there is a part of logic on them (as already mentioned above). Did not begin to give the full class diagram.
All npc types are inherited from NpcBase. All objects (door, bonuses) from HiddenObject.
Prototype

Initially dealt with textures and satin. Initially, all the sprites were in separate files. After that, he combined everything into one atlas, which accelerated the work. And there were problems. I tested everything on my phone (HTC One S) with Android 4.0. When I tried on earlier versions, the game crashed. As it turned out, older devices are falling due to limitations on texture size. For example, some did not support sprites more than 1024x1024. In addition, the initial dimensions of the atlases were not a power of two, which also led to a fall on many devices.
So that:
1) Do not make too large atlases.
2) Dimensions must be a power of two.
Things are pretty obvious, but while wandering around the develop forums, many suffered from such errors). After everything gathered in one atlas and figured out how to select regions and set up animation, I began to handle collisions.
Most objects have integer coordinates, and they do not change so often. Defined an array of
public int[][] map
and accessed it in order not to constantly chase lists of objects. The bottom line is that all blocks are on integer coordinates, so using an array helped speed up the work. When we update physics, we simply look at the distance from the player / npc to the objects around it.
Sort of:
if(around[0][1] ==0 && Math.abs(getPosition().x-x1)<SIZE/2 && Math.abs(getPosition().x-x1)>0.05){ if(getPosition().x-x1<0){ getVelocity().x = +speed; getVelocity().y = +speed; } if(getPosition().x-x1>0){ getVelocity().x = -speed; getVelocity().y = +speed; } }
A very crooked decision, yes. In the following games, all collision handling is based on delta, which shows how much time has passed since the last rendering. But here everything is so sad = /
NPC
Once I figured out the textures and collision handling, I added npc in the game. Behavior strategies, in essence, they have only three:
1) Move in a random direction. After a certain time, change direction to random.
2) As the first as a whole. But, if the npc sees the player, then it starts moving towards it. If a player disappears from view, then npc changes the direction of movement to random.
3) In general, as the second strategy. But only if he loses the view of the player, he still goes to the side where he last saw the player.
All types of npc are inherited from
NpcBase
and must implement the methods:
public abstract void changeDirection(float delta); public abstract void update(float delta) ;
GUI
GUI also implemented using LibGDX. All interface elements are represented as classes, instances of which are contained in the
World
class. Each element has coordinates and dimensions in the properties, which allows us to determine at the tapes on the screen which element the user actually clicked on.
Implemented two control methods:
1) Arrows.

2) Joystick.

In the settings you can set the position of objects, what we want:

Total
The entire development process in one post does not fit. I thought maybe people themselves will propose a topic for an article if they are interested in this engine. I would tell you about some of the most interesting aspects of development or the most interesting points when working with LibGDX.
Sources posted on
github .
You can also see my LibGDX lessons if someone wants to work with this engine.