Personal page of Vladimir Slav

Category Archives: Programming

If you showcase your game on conventions – you know how important it is to hold the attention of the user and make his experience playing the game trouble-free. The way people play your game during the event actually allows you to witness how people are going to play the game at home. This opens up a path to gather real-time feedback and, of course, improve the on-boarding process for the game. You can also miss some potential fans if your game does not look appealing or understandable in the first minute.

A bit of a backstory for context: The last 4 months of my life I’ve been spending all my spare time to develop the game with a working name “Lazy Galaxy.” It’s a game where you control an evil (albeit lazy) alien race and try to conquer the universe. It’s an experimental mix between RTS and clicker/incremental game: you build a base, then you send ships to space. The ships can be controlled as in RTS games, but this is not necessary. Since I’ve never seen something like that anywhere before (let me know if you have, I want to play this game!) – there’s a challenge of introducing players to this sort of game.

This might seem like a very specific case, but I’ve learned a lot of stuff that is going to be useful for a lot of games. Over the last two months, I’ve spent a considerable development effort to ease up the introduction into the game. Here’s how it went:

Experiment 1: Text Tutorials, Smaller Convention

I’ve actually found out that I’m going to an expo only two weeks before. The game seemed complex due to worse state of the ui in early stages of development. We knew that nobody reads texts – but how bad can it actually get? We’ve drawn cute mascot portraits, made the tutorials fit the narrative and made “bouncing buttons” that highlighted where the player should be clicking. We also made UI elements appear as the game progressed, instead of throwing everything at once.

Needless to say: I think only three or four people read the texts. Most people left in the first minute of the game. That’s understandable. Next time you are at a convention, try looking for an unknown games with average amounts of text explanations and play them. Are you capable of going through all instructions? I think the whole event atmosphere creates a “rush” feeling, because there are plenty of things happening around you. The event escalates the dislike for text tutorials, because no one wants to sit in one place, hindered by walls of text, unbeknownst about what are they going to get in the end.

Players also often missed our bouncing button cues, even though I’ve made all parts of the UI appear after the relevant feature becomes necessary.

Five people left their emails at the end of the day: two of them were friendly developers. Only the remaining three of these were actually people that enjoyed the game and wanted to know more.

Experiment 2: Pictures instead of text. Propaganda posters. Arrows that show where to click.

For the next convention, GameOn, biggest game convention in the baltic states, we understood that we needed a much better preparation. I’ve spent two weeks trying to figure out the best way to present information.

The first one to get added was the floating cursor helper. It showed where player needed to click, so the game would be accessible even to the players who don’t know english.

The next one to go were the text: most of the texts were thrown away. Only a simple reminder of what needs to be done (i.e. gather 20 minerals). It blinked for the first two seconds to indicate that the task has changed.

Another idea was to replace the texts with iconic images, to show how the game operates and what needs to be done. To avoid making it look like a chore, we’ve added some sort of a “propaganda” posters to the right side of instruction images. Those were designed as a references to the real-world propaganda posters. The idea was to make a game-world feel a bit more alive and add some lore. Feeling that this should do the trick, we went to the convention with high hopes.

Success?

Actually, only partially. Twenty five interested people left their emails. Not that much, but the results are much more successful than the previous ones: we genuinely found people who were interested in the game, but I’ve noticed that I often had to step-in and explain the core principles that I want to do. In convention, it might be OK, because people actually want to communicate with the developers directly and essentially you are the one “selling” you game idea. But imagine if they were playing my game at home? Nobody would be there to say “Hey, you can actually upgrade your buildings to increase an income.”

Here are the issues:

1) While the players stayed at the game much longer, the tutorial was unable to explain the principles of the game. The players heavily relied on the arrow pointer to show what to do. They progressed through the game, but only because the game explicitly told them what to do. They could not utilize the mechanics as those were introduced: a lot of players missed the concept of building upgrades, how those increased the flow of resources and made the gathering much easier. This is not their fault, but the fault of such design. From now on I understand that arrow/clicking tips have their place to be and are effective at directing players, but should be used with caution. The trade-off: players are able to progress, but unable to learn how to use the tools the game gives them to find solutions to their problems.
2) The images with propaganda posters / instructions got closed as annoying pop-ups. There was not much difference with text popups, although they did attract some initial attention. In the end, this did not prove to be a dependable solution. The small tasks were OK though, and people often look at them.
3) Another thing that affected the first one: the tasks were telling player what actions do they need to do instead of giving them the goals they need to achieve.

Next Steps, Solutions?

Think about the following objectives and which ones sound better:
3.1) “Build a mine” or “Establish Metal supply”
3.2) “Click on 20 asteroids to gain 20 metal” or “Gain 20 metal to start building a base”
3.3) “Research Space Travel” or “Go To Space”

I’m sure you can find out the similar action vs goal-oriented tasks in your game. After witnessing the results of the first option, the second option seems like the better choice. It needs more visual cues, but this gives players the goals they need to reach instead the actions they need to take. Instead of chewing your food in their place, you give them the opportunity to taste it. Give the opportunity to explore and experience your game, instead of letting them feel constrained.

Here’s what I’m trying to do now: the game is going to have a special “Codex,” a dictionary with lore and it’s going to have a special chapter. There is going to be an article for each one of those instructions (that essentially contains the scheme + propaganda poster). I’m not going to show the propaganda posters right away, the “?” button will appear next to a current objective and when player click it in case he needs help.

The leading mouse pointer goes away for most cases. It is going to be replaced by element outlines / slight shaking that will appear after some time if player struggles to complete his objective.

The small objective window is going to stay. The objectives are going to be task-focused instead of action-focused. Example: instead of “Upgrade Solar Panel,” there’s going to be “Get your total energy income to 2 per second.” Essentially, allow the player to find his own solutions and feel great about this. The “feel great” part will need more work: visual cues need to be subtle, instead of “In your face, doing everything instead of you.” Hopefully, this will have better results next time.

What would you do? What do you think could work in this case?

EDIT: In case anyone is wondering, here’s how the gameplay looks (explained by yours truly)

Implementing Android Controls

Technically, our game is ready, but in reality, we cannot launch it on Android. This is due to our controls read from Keyboard. Today, we are going to fix that by adding the arrow sprites for Android version.

Here’s 4 buttons that I’ve drawn:

We’re going to place 2 (up-down) buttons on the left side of the screen and remaining two on the right side. Now, let’s declare and load button images:

public TextureRegionDrawable leftArrowBtn;
public TextureRegionDrawable rightArrowBtn;
public TextureRegionDrawable upArrowBtn;
public TextureRegionDrawable downArrowBtn;

We will use it to place the button there (and also disable all of them when the game ends!). At the bottom of our GameScreen constructor, add:

controlGroup = new Group();
gameStage.addActor(controlGroup);
// comment out the next line to test buttons on desktop
if (Gdx.app.getType() == Application.ApplicationType.Android)
{
prepareDirectionButtons();
}

We create our group as we would create any other actor. After that, we check which device launched our application. If it happened on Android – prepare button! (but if you are testing – comment out the “if” check, because you want to see the buttons on the screen during tests, but players will have no use for them).

Now, we need to define the prepareDirectionButtons function. In advance, I think all of the button functions are going to be somewhat equal (only movement direction, image and button coordinates differ). Therefore, we can make a separate function to create a direction button.

As simple as that: create a new button, create a click controller that is similar to our arrow keys (calls AttemtpMove) and then add it to our group. Now all that is left to do is to add 4 direction calls to our prepareDirectionButton:

Music does not really work like sounds. We preload sounds, but music is different: since music files can be quite big, they are simply being read in realtime. We’ll simply pick the random tune from music0…music6, set it to looping and then play it. Now, just add a call to start music at the initialization of GameScreen and Stop the music at the disposal.

Alright. This part is done. Now let’s make sure we have a button to control the sound. I have four textures with sound button, to indicate different sound/music volume. 0%, 33%, 66%, 100%, called sound0, sound1, sound2 and sound3 respectively.

Now, let’s make a setting for the sound. We could make a Settings file similar to GameProgress file, but since we only have one setting (sound), let’s implement it in GameProgress. If you plan on adding more – I strongly suggest separating into your own settings file.

In our GameProgress file, add a constant to indicate MAX_SOUND_VALUE (that would be 3, 0..3), then add a new static variable called soundVolume; Also, add a save key for it.

Adjust the volume, if it goes over maximum value, just start anew (by disabling it, setting it to 0). Finally, let’s integrate the change to our SoundManager. When we play music/sound, we need to take the value of the soundVolume into account. First, the volume:

Casting to float is important! Otherwise the division happens between two integer values and you end up dividing 1 with 3 and get zero as a result. So you have to be careful with things like these. Taking the current music volume is great. But what if we change the volume during the game? We’ll need to modify the current music volume. Create a new static function, called AdjustVolume. It will call GameProgress.ToggleVolume and then change the volume of the currently playing music to a new value.

The idea is simple: change the image after the button has been pressed, indicating the current state of the volume.

Now, if you run the game, you’ll notice that the button is there but it is not clickable. The reason is that we set up our input to GameScreen and not gameStage. We catch events in our gamescreen, but we should be doing it in our stage. Thus, we have to move our keydown function into gamestage. First, remove the InputProcessor implementation from the GameScreen and move keyDown function to stage. Make sure to change the parameters from int keyCode to InputEvent event, int keyCode.

Now, try running the game and pressing the button. You’ll see that both sound/music are adjusted! Awesome! We have a sound button and we can adjust the game volume now!

Disclaimer: I’ve also tampered with game ending functions (not describing them here) to change transitions in GameScreen for html version because it was bugged otherwise. I don’t think that’s relevant to the lesson, but you can check the git commit with full code here (look for endgame boolean):

This concludes our second part of lessons, where we polished the game. Next, I’m going to focus on the Android-specific stuff implementation: ads, in-app purchases.

If you want to expand the game idea – think how you can make a special abilities for every character or add more bonuses or stats (gold per bonus picked?). The effects can also be adjusted, floating numbers on damage or when player gains gold. Never stop thinking about the things that can be improved!

Music is left-as is, in mp3, but renamed to music0..music5.ogg. In the directory android/assets/, create music folder and put sounds/music there. Finally, let’s get to coding! In our com.coldwild.dodginghero package, create a new class and call it SoundManager. It’s going to have static functions that controls menu music. Let’s introduce functions that load and unload sounds.

At the end of dispose() function. This will ensure the sounds are loaded at the start of the game and disposed at the end. The easiest ones to implement would be walk / attack sounds. Add those things to our SoundManager:

Try running the game! Whenever you move or your player gets hit – you’ll hear it. As you remember, we try to split game logic from representation. We won’t be calling soundmanager from our gamelogic, we’ll pass the bonus pickup / attack even to our gamescreen and it will handle it properly. First, add the functions for coin / health pickup:

Assigning meaning to stats

So far in our game, we can upgrade the character and unlock new ones. But the upgrades do nothing. Let’s actually make them affect the game.

Player’s hp, hp regen, damage from attack and bonus spawn time is going to depend on character level. Go to our CharacterRecord class. Introduce four functions to get each value. We are going to pass the level of the character, the function is going to return the value.

For HP, damage and regen – let’s make linear functions. First, get rid of maxPlayerLives and playerDamage in GameProgress. While you’re there, also get rid of playerLives = 3 in our „Reset” function. Then, go back to CharacterRecord and implement the three functions.

Pretty straightforward. Take the base value, add level divided by the levels necessary for upgrade, get result. Looks good. What about bonus spawning? We don’t want the bonus time to go down drastically, so it makes sense to introduce diminishing returns.

We just lookup the current character record, then try to get max hp depending on the level (we’ve also made the sprite setting line a bit more readable. Now, let’s modify GameLogic for our new character stats.

First, go to our AssignPlayerPosition function. There are two places that we should change. First,

Lesson 22: Ways to Spend Gold: Unlocking / Upgrading characters

So in the previous lesson we’ve implemented a way to collect gold, an in-game resource. But the trouble is: there’s no way to spend it yet. Let’s fix it today!

I am planning to do two things today: make characters unlockable and enable „upgrade” button for unlocked characters. All characters (except for human) are going to be locked by default. As soon as player collects 1000 gold – he can unlock a character. The amount of gold is up to you. I think 500 is a good amount, because we’ll be able to introduce In-App-Purchases later which would grant enough gold, but also player can gather enough once he played some time (without paying a dime).

Alright, so let’s modify our progress file first. We’re going to adjust it gradually, according to the changes what we are making. First thing that we are going to do, let’s make a separate array of levels of each character. 0 will mean that the character is locked, any value above that will simply mean character level (1+). Introduce the following constants / variables:

You might have noticed that we have to call uiStage.clear() before every prepareUi call. So, this is redundant. Let’s simply move uiStage.clear() to the beginning of prepareUi() and remove all other uiStage.clear() calls on this screen.

Run the game and try switching characters. If you set the CHARACTER_PRICE to lower value for debugging purposes and try unlocking a character – you’ll see that it becomes available.

After that, let’s get to upgrade button. But first, I think it makes sense if we add a label with character level or just a warning (“char locked!”). First, move textStyle declaration/initialization on top of our prepareUi function, right above the buttonStyle declaration.

Now, let’s make a new label, after our heroSprite definition. (Because we’re going to use that as an orientation / position settings).

Now we can finally get to upgrade button. You might have noticed, that the interface is getting a bit overcrowded. Let’s move the start button to the top and levelup button to the bottom (where there’s Unlock button for locked chars).

The start button code pretty much remains unchanged, except for Y position, which has moved to top of the screen.

UpgradeBtn is similar to start button, but it invokes getNextUpgradeCost function (will get to it later). The position is the same as the old “start” button position. The click function acts in a similar way, checks the next level upgrade cost and if it’s fine – takes the money and increases the character level. Looks good? Let’s go to GameProgress and define the function to get next level cost. As an experiment, I think it’s fine if we multiply the current level value by 2.

Lesson 21: Gold Gathering

Last lesson, we’ve added multiple characters and made it possible to pick them. We’ve also introduced the levelling stats. Unfortunately, since there are no levels, there’s no point of stats.

First thing’s first, how are we going to level up our characters? Well, this is quite easy! They’ll have to push the “Upgrade” button! What’s that? We cannot simply allow player to mash the upgrade button? Fine, we’ll introduce in-game currency to solve the issue of infinite upgrading.

First thing: we’ll add a coin that can be picked on the battlefield. Yes, similar to health / attack. Here’s how it looks (drawn by https://twitter.com/ElenaNazaire):

Now, make sure we create the bonus in-game. In GameLogic, let’s adjust oru SpawnBonus function. Now if you’ve played the game as much as I did, you can already notice that hearts spawn a bit too much. Let’s reduce their rate and increase the attack spawn rate a bit. Say, 5 out of 8 times we want attacks, 2 out of 8 times we want coins and 1 time we want health bonus.

Use attack bonus by default, then in a few special cases switch it to health and coins. Let’s run the game! You now see that the coins are spawning, but picking them does nothing. Let’s fix that!

Handling the logic behind coins

Great, so what do we do now? How do we make coins work? We need to introduce a separate variable that would store the coins. Let’s handle it in GameProgress.

public static int currentGold = 0;

Add saving/loading at once.

private static final String SAVE_KEY_PLAYER_GOLD = "playergold";

In our Load() function, let’s handle the loading of our gold:

currentGold = prefs.getInteger(SAVE_KEY_PLAYER_GOLD, 0);

And a bit further, in our Save() function, let’s handle the proper saving of the value!

prefs.putInteger(SAVE_KEY_PLAYER_GOLD, currentGold);

Good, the gold is saved, but it is not gathered properly. Time to implement that. Remember, in our GameLogic class, we have the AssignPlayerPosition function? In it, we process the bonus pickups. Let’s alter it to actually handle the coin pickups. Here’s how my full check looks now:

Displaying the coin amount to the player

Now let’s ensure we display our coins both in GameScreen and CharacterSelectionScreen.

Start with CharacterSelectionScreen. We want to display coins on the bottom left side of the screen. To do this, we’ll show the coin image and write amount of coins we have beside it. Open our CharacterSelectionScreen class. Go to prepareUi() function, and add the following lines to the end of it:

Pretty self-explanatory, first we draw a coin, then: the amount of gold we actually have. Run the game! You’re going to see the coins on our main screen and in the game, as well as notice how the amount increases after you pick them.

This took a bit more time and changes that I’ve expected, so I’ll try to cover levelling in our next tutorial.

Lesson 20: Introducing Character Variety and Upgrade system

So as you’ve seen in our previous lesson, we had added the character select screen. Unfortunately, there were no characters to select 🙂 Let’s fix that!

What do we need? We’ll need a data structure to describe each character’s stats. We can do the following: introduce multiple characters and make them upgradable for game currency. The trick is: each character has its own strongpoints. I.e. one character will be getting +1 health after every upgrade, the other: after every two, another one: after every three. Same goes for attack strength from picking relevant bonus and for hp regeneration (how much hp you restore from picking hearts). That way we can create a character that restores lots of hp, but has small healthpool. Or the character that does lots of damage, but has trouble with hp regeneration.

In our logic/objects package, create a new class and name it “CharacterRecord.” I suggest we make four different stats:

Upgrade levels needed for hp upgrade (player buys one upgrade level, the character’s hp upgrades after every N levels). Similar to that:

Upgrade levels needed for attack upgrade (how much damage player deals per attack?)

Upgrade levels needed for bonus time upgrade (let’s make bonus spawn time dependant on player’s character!)

Obviously, each character will also need a name (at least for display purposes on the menu). CharacterRecord will store the base stats, but not the level by itself. So, it should be simple, really. We can create a simple constructor and pre-define the characters this way:

Spider gets good health, but bad regen. Better attack than human, but bonus spawn times are getting upgraded slower.

Skeleton is terrible at health/healing, but does good damage at good intervals.

Ghost is mostly average. Good stats, but nothing exceptional.

Slime has amazingly fast bonus spawns and a bit wors stats otherwise.

Adjusting the character selection screen

Before we actually make stats relevant, we’ll have to create different character selection at first. So we have some stats pre-defined, but what do we do now? Let’s actually start by allowing to select different characters. Before we even talk about swapping active character index, let’s discuss how we get the relevant character sprite and name to be displayed in our CharacterSelectionScreen. I suggest we start working on resources class. Similar to the way we return enemySprites, we should make a hashmap that stores player sprites. This time, I’m making it with <String,Sprite> pair (as I am going to use it sparcely), but I must let you know that using strings as lookup won’t do if you do some real-time rendering and not single sporadic lookups. It just takes a big hit on performance (alright, it probably depends on the implementation of hashmap, but I won’t go that deep in this tutorial).

Open up our Resources.java class. Right beside our enemySprites declaration, declare another Hashmap:

public HashMap<String, Sprite> playerSprites;

This will store various player sprites. Initialize it at the same place where you initialize the enemySprites. Then fill it with relevant content.

Making character selection work

OK, we got player sprite list. What do we do? Go to CharacterSelectionScreen. We’ll need to adjust a few things. First, move currentCharacter variable into GameProgress class:

public class GameProgress {
public static int currentCharacter = 0;

This is necessary, because we’re going to save the selected character (a bit later). Go back to our CharacterSelectionScreen. See our hero image creation in prepareUi()? Let’s make heroSprite be initialized with the current selected character’s sprite.

From constructor. Try running the game. You should see the good old human sprite. The difference is that we’re looking it up from our hashmap instead of directly providing it to our heroSprite Image. With that, the preparations are mostly done. Let’s finally get to switching the active character sprite! All we need to do is to add listeners to nextBtn and prevBtn (which are somewhat similar).

Just to explain a bit: we assign click listeners to next/prev buttons. What we do is increase/decrease current character index. If it is out of bounds – go to the beginning/end of the list (to allow player scrolling through the characters without limitation). After that, we clear all Ui elements from the stage and reinitialize them. This might seem like an overkill (we just have to switch the heroSprite, right? But in truth this won’t be the only thing later on (when we’ll be writing stats on the main screen). So we clear all the ui elements from the screen and then repopulate it again.

Now as the final thing for this tutorial part, let’s just make out GameScreen to show the new selected sprite (but not be affected by the stats in any way).

Run the game and try picking any character! You should see that our player character sprite has successfully changed. That concludes lesson 20! Next time, we’ll actually try to make those stats affect the game and introduce the upgrade/unlock system.

My idea is to make different attack patterns for different enemies. We have vertical lines for spider. Let’s make horizontal lines for ghost, diagonal lines for bat, random attack pattern for slime and all four possibilities for skeleton.

Before we load the resources in game, let’s adjust the Resources and Enemy class constructor: it is going to accept the type of enemy now. In our Resources class, make a public static final int constants, that would enumerate the enemy types.

We are using the int’s instead of Enum because there’s no easy way in java to convert int to enum (and we are going to generate a random int to determine enemy type). Now, add the type variable to our Enemy class and adjust the Enemy constructor.

Depending on type, we’re going to load the appropriate enemy sprite. Now, to load them, we could declare 5 different sprites, but let’s think of a more optimal approach (so it would be easy to lookup later). In our Resources class, Let’s remove our enemy sprite declaration. Instead, let’s make a HashMap of &lt;Integer, Sprite&gt; pair, which would link our enemy type integers to actual enemy sprite.

public HashMap&lt;Integer, Sprite&gt; enemySprites;

Remove our enemy sprite loading line of code in Resources constructor. Instead of this, let’s initialize the enemySprites HashMap and fill it with values:

A bit repetitive, but I’m sure it will pay off 🙂 Now, let’s actually go to Enemy class and replace the

set(res.enemy);

command with something more advanced:

set(res.enemySprites.get(type));

We grab the sprite according to the type. Careful! In bigger projects, it’s better to create a getter function, which would check if enemySprites has the value of (type) first, in order to avoid nasty errors of all sorts when you add a new enemy.

Let’s make an in-between test run. However, the game won’t compile now. That’s because we’ve changed the Enemy constructor. In our GameLogic, when we create a new Enemy object, let’s add an extra parameter:

The enemy is going to be chosen randomly. Run the game. Repeat it a few times. The enemy sprite should be randomly chosen on launch now. Also, if you defeat an enemy (and progress to the next round), the enemy is chosen randomly too. Pretty cool, huh?

Adjusting the attack time

Meanwhile, let’s reduce the time between enemy attacks to make the game more dynamic. First, let’s save the player from being attack as the round starts. Add the constant:

private static final float WARM_UP_TIME = 2.0f;

Adjust the enemy update function a bit, the moment when we determine to attack:

You can see that I’ve added the first condition: we don’t want an enemy to attack for the first two seconds, let’s call it a warm-up time for player to understand that the game started / level changed.

Then, change

private static final float BASE_ATTACK_TIME = 3.0f;

To

private static final float BASE_ATTACK_TIME = 1.0f;

It’s going to be OK, because we add 0..2 seconds between attacks in resetAttackTimer function. This should make the game much more dynamic.

Adjusting the attack patterns

If you check our Enemy class, update function, you’ll see where we determine the attack coordinates. You can imagine, if we add 4 different attack types, the function will get quite bloated. Let’s delegate it to a separate functions.

Except for the two last lines! Into separate function, let’s name it performVerticalLineAttack();

Now, let’s make a similar function, which we’ll call performHorizontalLineAttack (it’s going to be pretty similar, so let’s copy performVerticalLineAttack and adjust it accordingly). In similar way, horizontal attack will choose 2 horizontal lines and mark them. Here’s how it looks:

We pass the initial x and the direction (dx). Then we go through full height of the field and pick one tile that is positioned diagonally to the previous one. All that is left is to make the function that actually picks two x coordinates and directions.

3 done, 2 more to go! The random one is quite simple: let’s not care about filling the repeated tiles. It’s part of life. Instead, just pick 10 random tiles on the field and mark them as used for attack. Here’s the final function:

We’re done! Now, I’ve noticed that we’re drawing effects below the player. In this case, it won’t be a good idea because we need to explicitly show the red warning signs (and they are poorly visible otherwise). Move the

Great. Now the warning signs are going to be shown above player (timely telling him to get out of the blast zone!). The other thing: the delay of 0.5 seconds is not enough to react appropriately. Go to WarningEffect.java and change WARNING_TIME constant to be equal to 0.75f (up from 0.5f).

Now, what do we want to do on GameEnd? We need a smooth fadeout, and then a progression to next level. Well, a restart for now. It is going to be a progression in the next lesson though. Since we are using sprites (and not gamestag eactors), we won’t be able to use libgdx in-built fadeout action. No worries, it’s not hard to implement ourselves. In advance, make two static constants at the beginning of the GameScreen class:

We’ll ignore playerWon Boolean for now (we’ll implement another transaction on loss). Now, what do we want to do on GameEnd? We create a sequence of actions. First is essentially a fade-out timer, we fade the screen out for GAME_END_FADEOUT seconds (0.5 in this case), then we return true, which indicates that that time has been spent. And then actually we create a new GameScreen that restarts the game.

Now, to get further with our implementation, in our logic initialization, add the line:

logic = new GameLogic(game, this);

Now, that we’ve added a smooth fadeout, we should actually add a smooth fadein. In our GameScreen initialization, add a new action to our freshly initialized stage (at the end of GameScreen constructor).

It’s the same quadratic fadein as you’ve seen before: take the time, add the delta, divide by expected time for fadein (0.25) in our case, thus normalizing the value to 0..1. After that, square it. Great! We got a new transparency.

Finally, if the time has passed the necessary fadein time, return true (thus ending the action). Run the game. As you see when screens actually fadeIn, you have a quick flicker (if you look closer: it’s a scaled-down version of your screen). To prevent this, we need to update a gameStage camera before drawing frame one. At the end of GameStage constructor, add: