The central code of my game is a loop, that consists of three phases: initialize, update and draw.
The first phase is used to do any necessary game setup. It is run only once and I am loading resources called assets into the memory (mostly images of terrain, units and buildings). We have an option to load resources while the game is running, but this can cause unwanted behavior (we can hit invisible building, because its graphics are not loaded yet). Loading bar can be used if we have several megabytes of assets, because processing them all can be time consuming.
The main purpose of the update phase is to prepare all objects to be drawn. We are also processing input from the user, AI and moving camera.
When everything is properly updated and ready we enter the draw phase, where all this information is displayed on the screen. Every object is rendered, even if they were not changed. If we don’t want to make our game a slideshow presentation, we need to redraw a scene at least 30 times per second.
This design-pattern helps us separate the model (attributes of units, camera position, game state,...) from its controller (player input, AI input, game logic) and its view (unit images, particle effects, terrain graphics,...). To maintain code readability we need to separate at least display code from game logic.
Tiled is a 2D level editor, that helps you develop the content of your game. Its primary feature is to edit tile-maps of various forms http://www.mapeditor.org/. Slick2D can import files created by this editor and work with them. Even though I did not use Tiled files in the final game (because I was generating terrain procedurally), it is very powerful and easy to use tool.
My island is generated procedurally, because I wanted to have different kind of islands every time I launch the game. Only a part of the island is generated around the player at start. Other parts are created as the player is exploring it. We are saving lots of memory this way. Before the player gets too close to the end of one generated plate, another one is generated, so he will not see where one plate ends, thus experiencing fluent transition from one plate to another. To generate one plate I am using modified diamond-square algorithm.
Generating plates is done in a separate thread, because doing this in the main thread caused the game to wait for a new plate to be finished, which resulted in a noticeable lag when player went too close to the end of an existing plate. In games based on LWJGL we can use other threads for calculations, but we cannot use them to update graphics. This is the advantage of the main thread.
Almost every graphic comes from page http://opengameart.org . We can find here lots of content for 2D or 3D games.
Lots of CPU time takes picking the correct color for nearby tiles and then redrawing all those tiles around the player. The color of the tile depends on the distance from the player, nearby light sources (fire), day/night cycles. We musts calculate this for 500 tiles, 30 times per second.
As the player is exploring the island, I am updating the minimap (which is just a bitmap image). Challenging part was creating „Fog of war“. This was achieved by OpenGL alpha mask and drawing only parts of the map that were under it.
Units can be facing one direction and move other. Lots of trigonometry was used for calculating distance, direction, speed. I implemented simple collision detection mechanism to prevent units occupying the same space. Units should be able to find shortest path between two points in case there is obstacle in their path. Algorithm called A* is solving this problem, but I did not use it in my game.
In my game, player is collecting cards to boost his stats. I implemented a drag-and-drop system that enables him to pick a card and add it in inventory slot.
To model the AI behaviour, state pattern should be used. AI can start following or attacking player, but if it is losing battle, its state should change to fleeing state and it should run away. After it is healed, its state should switch to following again.
Slick is good for people who lacks experience in OpenGL, and they want to create simple games fast. But it is an obsolete framework with low support from the community.You cannot run game in Slick2D on mobile platform. Better alternative is LibGDX. Biggest advantage is – you write one code that is compiled for mobile devices and also for web (GWT). It is better documented, often updated with lots of tools and solutions for problems (pathfinding, AI behaviour, message queue, ...).
What would I do differently and what would I use next time:
Good source for starting with game programming principles is this book: