Trying libGDX android game development: Cross-breed of Pac-man, Nethack and Gauntlet. PART II


 Tools used

I selected libGDX because it is widely used and based on Java. I did the development in Android studio / Windows.

Graphics editing was done with Gimp.

I used some old and new Android devices found in our family for testing. Also the Android emulators were used a lot. Old slow Android devices were very helpful for finding bottlenecks in code.

I created a simple level editor (as an android app). The levels were stored as text files and could be edited also with normal text editor.

For advertising I used Google Admob and it’s interstitial ads, which work quite nicely in mobile phones and tablets. I decided not to spend any time taking Google play services or firebase in use, because they did not serve my goals.

Graphics and sound

Most of the sound effects are from excellent ”2000 Game Sound Effects Library Collection”. http://www.gameburp.com/

My son composed the title music and created some sound effects.

Sprite graphics were purchased mostly from www.gamedevmarket.net

I created the graphics for maze walls trying to get some organic feeling to it. Also the sprites for the worms were created by me. The worms were only sprites that required some kind of animation to get the movement smoother.

Game mechanisms

The basic act/draw -game loop comes from libGDX. I used the libGDX graphics, sound and input apis and ended up writing a lot of the rendering, collision and game logic by myself. The custom code was required partly because the representation of maze was such that collision and line-of-sight logic required some tweaking.

The starting screen was developed as normal Android activity with Android libraries. When the ”Start” button is pressed, an advertisement screen is shown first after which the libGDX activity is fired up. The start screen and game activities communicate through standard android intents.

The level randomness is achieved by composing the levels of small subparts of level. Each level has a collection of something like 30 small parts and when level is created a few of the parts are selected and glued together randomly.

Here are pictures of the maze representation in file and in the editor.



The java interface for the maze walls is pretty simple:
  • public int getWallType(int x1, int y1, int x2, int y2);
This method returns the type of wall between two maze points. There are also methods for getting and setting maze objects and actors (e.g. enemies).

I tried to utilise basic object oriented techniques whenever I could: interfaces, inheritance, polymorphism, generics etc. The main interfaces were for different actors in the game (player, enemies), items in inventory, items and objects in the maze and handling the maze levels.

Finding paths for enemies

The enemy movement logic is pretty simple:
  • If enemy has not seen the player it has 2 strategies
    • If it sees way points, follow them. Way points are points in map that can be used to define movement paths for the enemies.
    • Otherwise move to the selected direction as long as possible and then determine a new direction. There is a (random) chance that enemy changes direction also even if it would be possible to continue to previous direction.
  • If enemy sees the player or has seen it recently
    • Go towards the player selecting the shortest path.

Worms do not follow the player, they always use way points.

I used Bresenham's line algorithm to check if the enemy can see the player. So each pixel of the line is checked for walls (which block the sight) starting from the direction of the enemy going towards the player. For the Bresenham's algorithm a more accurate representation about the maze is created. The blocks in maze are represented as 8x8 ”pixels”. For this case the maze is represented as simple interface, which returns true if the pixel coordinate has wall.
  • public boolean isWall(int x, int y);




If player is visible to the enemy, a recursive path finding algorithm is used to get the shortest path to the player. This created a lot of objects and I soon discovered that in older devices it slowed the game down. I then had to use object pooling to minimize the garbage collection processing.

This enemy movement logic was quite hard to debug because of recursive implementation. I created some visual information about how enemies see player and calculate paths. So when game is run in debug mode it shows when enemies see the player and display the movement paths by dots. Also in the right bottom corner a input debugger is displayed showing the latest user input.




To the previous part of this article
To the next part of this article

Comments