Better Off Android – 1.1 Bit:Update

Android-logo

Last year I put together four simple Android games – Bit:Shift, Bit:Run, Bit:Rise & Bit:Fall.

I wrote these game using scratch code – That is code ‘scratched‘ together from any samples, tutorials, etc I could find on the internet – along with a little guesswork on my part to fill in the gaps..

It creates very messy code, which I wouldn’t want to show anyone. But is a surprisingly useful technique for learning quickly & having a product to use at the end of it all.

By and large I’m pretty happy with these games, there’s not much to them, but I think they are fun to play & have all the elements I wanted to try out – online highscores, achievements, ability to purchase & what I hope is an entertaining diversion at its core.

However they are not without their problems – The most obvious of which is scrolling.

Currently scrolling on these games is atrocious – For the most part – with Bit:Rise & Bit:Fall especially it’s not an issue – But with Bit:Run and especially with Bit:Shift it’s very noticable & takes away most of the fun from playing the game.

I need to try and fix this – If I can’t remove the problem entirely then I need to at least try to minimise their impact.

 


 

Since a scroll fix would involve updating all the games code; I figured I’d do a little housecleaning at the same time.

Really I need to tidy the code & do a little restructuring (not that much) – But I’ll save that for the next update. This time I thought I’d do some optimisation – Especially trying to get the garbage collector to run as infrequently as possible.

 


 

I have four games (Bit:Run, Bit:Rise, Bit:Fall & Bit:Shift) – each games has two versions (One version for GooglePlay , the other for the Amazon App Store).
I used Google’s ‘Performance Tips‘ as a primary guide – alongside a few google searches to decide which to focus on.

Settling on six processes;

1. Remove getters & setters
2. Use direct reference with For loop conditions
3. Convert floats to ints
4. convert int to shorts & bytes
5. Change variables to static & static final
6. Object pools

 

Links:
Performance Tips
Coding for performance and avoiding garbage collection in Android

 


 

1. Remove getters & setters

I’ve always been taught to use getters and setter & I’ve been pretty consistent in using them in code. But never been a huge fan – Unless the getters and setters actually do something (filter the values being retrieved or updated) – They didn’t seem to do anything other than provide an extra layer (& extra code) for what was essentially direct access to an objects variables.

For Android – within an class anyway – Google agree; ‘on Android. Virtual method calls are expensive, much more so than instance field lookups. It’s reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.

 


 

2. Use direct reference with For loop conditions

The title isn’t particularly clear; so I’ll try to explain through example;

I had a lot of for loops that looked like this;

for(int counter = 0; counter<array.length; counter++)

The problem here is ‘counter<array.length‘ – Because JIT will need to reconfirm the array.length every loop it’s unable to optimise performance.

A better solution (one which I have currently implemented) is to assign ‘array.length‘ to an integer before looping;

int arrayLength = array.length;
for(int counter = 0; counter<arrayLength; counter++)

JIT now has a static value to check against; it can optimise the loop’s performance.

However, an even better method (& one which I haven’t yet implemented) would be to use Java’s ‘enhanced for loop syntax’

for (Foo a : array) {

 


 

3. Convert floats to doubles

Google explainss;

As a rule of thumb, floating-point is about 2x slower than integer on Android-powered devices.

In speed terms, there’s no difference between float and double on the more modern hardware. Space-wise, double is 2x larger. As with desktop machines, assuming space isn’t an issue, you should prefer double to float.

Searching around, the vast majority of people seemed to agreed – With the consensus – use doubles by default & floats only when absolutely necessary.

When are floats necessary? – My games had three, rather major areas, where using floats was necessary;

  1. When creating a large number of objects (e.g. particles for explosions) – Explosions create a lot of particles – I don’t need absolute accuracy when drawing them & using floats means they take up far less space in memory.
  2. Matrices- I use basic graphics for the Bit: games – using matrices to manage them. In java Matrix methods have floats as parameters rather than doubles.
  3. Graphics – Beyond the matrix, most of the graphics methods in Java use floats rather than doubles – GPU’s are generally optimised for float processing – some can’t handle doubles at all.

While doubles are preferred, they are not always feasible – especially with game development.

I guess as a rule – If it’s CPU work, use a double, if its a graphics operation, use floats.

 


 

4. convert int to shorts & bytes

I figured, since I’m use doubles, which take up twice the space of floats – I’d try to save some space by replacing integers (32-bit  min value:-231  max value:231-1) for short’s (16-bit min value:-32,768 max value: 32,767) or bytes (8-bit min value:-128 max value: +127).

This would be especially useful in for loops – Most of my four loops count to less than 10 – a byte which has a value between -128 – +127 should do the job nicely.

As it turns out this is bad idea;
Java is optimised for processing integers, but not shorts or bytes.

Byes & shorts will probably be promoted to integers – a process which will take up processing time to perform & will mean no space has been saved

The Java Virtual Machine models stacks and object fields using offsets that are (in effect) multiples of a 32 bit primitive cell size. So when you declare a local variable or object field as (say) a byte, the variable / field will be stored in a 32 bit cell, just like an int.

Which isn’t to suggest that shorts & bytes aren’t useful – Just not for purposes I had in mind.

Links:
In java, is it more efficient to use byte or short instead of int and float instead of double?
Why does the Java API use int instead of short or byte?

 


 

5. Change variables to static & static final

This makes sense when trying to avoid calling garbage collection. The garbage collector is called when enough elements are orphaned or disconnected (e.g. setting an instantiated object to null). Since static objects exist throughout the lifetime of the application there’s not disconnection.

So, although it ensures a larger constant memory footprint, with fewer objects being destroyed/recreated – There are fewer reasons for Java to run garbage collection.

On a method level, Google explains;
If you don’t need to access an object’s fields, make your method static. Invocations will be about 15%-20% faster. It’s also good practice, because you can tell from the method signature that calling the method can’t alter the object’s state.

Optimisation is further increased if you can declare the objects static final since ‘the constants go into static field initializers in the dex file. Code that refers to intVal will use the integer value 42 directly, and accesses to strVal will use a relatively inexpensive “string constant” instruction instead of a field lookup.

Though, for for static final, it’s worth noting the caveat; ‘This optimization applies only to primitive types and String constants, not arbitrary reference types. Still, it’s good practice to declare constants static final whenever possible.

 


 

6. Object pools

Another garbage collection management method. Object pools use the same principle as using static variables.

Wikipedia explains; ‘initialized objects [are] kept ready to use – [in] a “pool” – rather than allocating and destroying them on demand. A client of the pool will request an object from the pool and perform operations on the returned object. When the client has finished, it returns the object to the pool rather than destroying it; this can be done manually or automatically.

So, for example – You have a game in which X number of bad guys are going to be active at any one time. Which you can’t guarantee how many will be active, you know it will never be more than 32 at any one time.

To manage the bad guys – You may create a List – of type BadGuy – This way you can easily add new BadGuy’s when they are needed – & remove old BadGuy’s once they have been dispatched by the player. It also means you’re not using up any more memory at any one time than you absolutely need to.

This is fine, except, after x number of BadGuy’s have been removed from the list, the garbage collector will run which will take up precious processing time.

To alleviate this, instead of a list – you use an array – of type badGuy – since we know there’s never more than 32 active bad guys we make the array 32 elements in size.

Also adding a boolean to the badGuy object – called, say isActive – This allows the program to determine if the BadGuy is alive (and should be updated/drawn to screen) or dead (& ignored)

Now when a BadGuy is killed, instead of removing them from the list, you set isActive to false.

When looping through the array (for update or drawing) – you check ‘if badGuy[counter].isActive‘ – to ensure out of play bad guys are not processed.

When adding a new bad guys into the game game; you find a cell in the array with a bad guy whose ‘isActive == false‘ – re-Initialise & they are back in play. You can find an empty cell by looping through the array and checking each element, but a better option is to keep an index of available cells

Like static objects, this has the downside of having a consistently larger memory footprint – but lowers garbage collection calls dramatically.

While I don’t have that many elements active at any one time, objects are constantly falling off the bottom of the screen and being added to the top.

Since this happens in a very controlled manner, converting from lists to basic object pools was pretty straight forward.

Links:
Simple object pool

 


 

Thats was about it – There always more I can do; & for these games, there’s a LOT more that needs to be done – but for now, I figure that’s enough procrastination – I need to get to the heart of the problem & actually fix the scroll issue.

Adventures in Unity – 1.9 Tighten & Tidy

Official_unity_logo

With the inclusion of Obstacles; there isn’t anything else I really wanted to add to this project.

It still needed a lot of work; pulling all the elements together and polishing the presentation – One final Tighten & Tidy.

But I felt I’d done what I set out to achieve at the start.

I’ve included notes for the larger updates and amendments below – & while there’s a lot more that could be done (especially with the code structure) – I think this will be it for project 1.

 


 

Particles – This is a very simple game, and could sometimes look a little flat. I added a small number of collision particles (platform collision, pickup collision, obstacle collision) to hopefully make the game more visually appealing.

particles

 


 

Standardised Colours – For better or worse I’ve used the same colour scheme for all my games since EOL back in 2010.

To standardise the same colours across the game  I created a script called ColourManager. This contains a number of static methods to manage element colours;

GetColour returns a specific colour, used by HighScoreAdd to manage the keyboard key colours.

SetColour used to set the colour of a components renderer. Used to set the colours of platforms, obstacles and pickups

CurrentColour & NextColour used by platforms and titlescreen text to loop through each colour in rotation.

 

colour_range

 


 

Ensure player isn’t killed at game start – Until now, at the game start; a player would sometimes immediately hit the edge of a platform and fall out of the game – Ending the game before it had begun. To fix this I made a very minor edit to the PlatformManager code so that the very first platform is much longer – Giving the player a safe entry to the game before different platform heights are introduced.

 


 

Ensure player managed when not in-game –  On the title screen (and game over screen) the player components ridgedbody element was still being updated – If a player left the title screen running for any length of time, they would be subjected to mysterious platform colour changes & collision sound effects being played seemingly randomly. To resolve this, I now only update the player if in-game (if statement in the players Update method) – Otherwise I reset them to an offscreen position and reset the velocity

     void ResetPlayer()
     {
          rb.transform.position = new Vector3(0, 7.5f, 0); //Set game init position
          rb.velocity = Vector3.zero;
     }

 



 

Set Alternate Game Name – Changed the title screen to say 20 goto 10 presents Bock Run. It’s not a great name, but seemed a little better than Welcome to Test Game (Colours are randomly determined on screen init).

 

GameTitle

 


 

In-Game Scoreboard – I simplified the presentation of the scoreboard by only displaying the players score. Though I wanted the score to be shown behind the player (but in front of thr skybox), so I complicated the back end. Adding a new canvas (called CanvasScore), plugging in the Main Camera changing the render mode to ScreenSpace – Camera

CanvasScore

 


 

SkyBox – I liked the default skybox, but I thought I should at least try something a little different. Ultimately I settled on the Fantasy Skybox FREE by G.E.TeamDev  – Stripping out all the content except the Sunny 01A material and Sunny_01A_Front texture.

Sunny_01A_front

 


 

Player Death Pause – Colliding with an obstacle, results in the player exploding in a cloud of particles – game over. Previously, after creating an instance of explosion particles the game went straight to either the ‘new highscore‘ or ‘game over‘ screen letting the particles play out in the background. While this didn’t look too bad, I wanted to add a slight pause – Long enough to let the player appreciate what had happened – But not so long as to be distracting – I guessed about a second would do the job.

My quick and dirty way to add this, was to create a new game states ‘GameOverPause‘ which would be set only if the game over state was a result of obstacle collision. When setting  ‘GameOverPause‘, a timer is run as a coroutine;

IEnumerator GameOverPauseTimer()
{
     yield return new WaitForSeconds(1);
     HighScoreCheck();
}

Once the timer completes HighScoreCheck() is called and the games next state is detemined – ‘New Highscore’ or ‘Game Over’

 


 

Background scrolls smoothly when transitioning from game over to game start – At the moment, when a new game is started, I reload the scene – start everything from fresh. I wasn’t sure if this was a little jumpy & liked the idea of the background blocks continually scrolling, whatever the game state (game/game over/new highscore, etc…). No reset or reloads – when the game ends, the background keeps scrolling – when the player presses play they fall straight into the scene whatever state it’s in. I ultimately decided not to go this way (Because of ‘Ensure player isn’t killed at game start‘), but the code is still in place & can be activated, either in-code by setting the ‘bool reloadLevel‘ (in the GameStateManager class) to false – Or in-game by pressing ‘R‘.

 


 

Multiple obstacle types – spheres bounce, blocks burst – Expanding obstacles a little – As well as the instant death obstacles, I added new type – using the ObstacleSphere prefab – bounce. Both obstacle types use the same script, the only change is the addition of a enum used to determine obstacle type;

public enum ObstacleType { Cube = 0, Sphere, Pyramid }
public ObstacleType type;

& a little code to handle the different collision responses – Cubes & pyramids use the old/existing – instant death code – While spheres ‘bounce’ the player uncontrollably

void OnCollisionEnter(Collision collision)
{

     if (GameState.Is(GameState.State.InGame) && collision.gameObject.CompareTag("Player")) //Ensure we are checking aginst the player.
     {

          Player player = collision.gameObject.GetComponent(); //Grab the player

          if (type == ObstacleType.Cube || type == ObstacleType.Pyramid)
               player.PlayDie();

          else if (type == ObstacleType.Sphere)
               player.Bounce();

     }

}

Bouncing just increases the players Y velocity;

public void Bounce()
{

     float bounceAmount = 6f;
     rb.velocity = new Vector3(rb.velocity.x, Mathf.Abs(rb.velocity.y) + bounceAmount, rb.velocity.z);
     audioBounce.Play();

}

 


 

Controller support – Support for different input methods was pretty spotty – some screens recognised mouse and keyboard input; others only mice. – I wanted to ensure all screens could be controlled by either keyboard or mouse, as well as gamepad (No touch input yet though).

The setup as it currently stands is a little rough, clearly a first draft which could  benefit from a review/rewrite or two. It’s a static class based around four methods – Two methods Horizontal & Vertical check for player movement requests  & two methods ButtonsDown & Buttons to check for player action requests (jump, select key, button, etc).

Companion axis methods Left/Right – Up/Down – HorizontalOff/VerticalOff use the results of Horizontal  & Vertical to provide reference to the current state (e.g. is the player trying to move left) without needing to rerun Horizontal & Vertical more than once a frame. Used to navigate the the virtual keyboard and main menu buttons.

Companion button methods e.g ButtonADownButtonBDownButtonShoulderLDown are used to reference specific button selections.

Horizontal()  & Vertical() effectivly both work in the same way, just along different axis. They are run every loop; checking for user input using a valid method (left thumbstick, right thumbstick, arrow key, etc) and return a result value; -1 for left/down, 0 for no input  & 1 for right/up.

public static float Horizontal() //Is the player using horizontal movement
{

     lastHorizontal = currentHorizontal;

     if (Input.GetKey(KeyCode.LeftArrow) || ZoneCheck(ZoneRange.Left, Input.GetAxis("Horizontal")) || ZoneCheck(ZoneRange.Left, Input.GetAxis("HorizontalThumbstickR")) || Input.GetAxis("HorizontalDPad") < 0)           currentHorizontal = -1;      else if (Input.GetKey(KeyCode.RightArrow) || ZoneCheck(ZoneRange.Right, Input.GetAxis("Horizontal")) || ZoneCheck(ZoneRange.Right, Input.GetAxis("HorizontalThumbstickR")) || Input.GetAxis("HorizontalDPad") > 0)
          currentHorizontal = 1;

     else if (Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.RightArrow) ||
                    (currentHorizontal != 0 && ZoneCheck(ZoneRange.Centre, Input.GetAxis("Horizontal")) && ZoneCheck(ZoneRange.Centre, Input.GetAxis("HorizontalThumbstickR")) && Input.GetAxis("HorizontalDPad") == 0))
          currentHorizontal = 0;

     return currentHorizontal;

}

Buttons() checks all valid input methods (gamepad buttons, space bar, return key, etc) using the unity function GetButton – To check if the button is currently being pressed -Used for in game jumping.

public static bool Buttons() //Any button pressed
{

     if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.Space) || 
            Input.GetButton("JoystickButton0") || Input.GetButton("JoystickButton1") || Input.GetButton("JoystickButton2") || Input.GetButton("JoystickButton3"))
          return true;

     return false;

}

ButtonsDown() checks all valid input methods (gamepad buttons, space bar, return key, etc) using the unity function GetButtonDown – To check if the button was pressed in the last frame. Used when the user selects a button from the Main Menu.

public static bool ButtonsDown() //Any button pressed
{

     if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.Space) || 
            Input.GetButtonDown("JoystickButton0") || Input.GetButtonDown("JoystickButton1") || Input.GetButtonDown("JoystickButton2") || Input.GetButtonDown("JoystickButton3"))
          return true;

     return false;

}

 


 

Split GameController into multiple classes – The GameController script was heavily overloaded – It managed the games states, title screen buttons, gameplay loop, player score, game timer, scroll speed, in-game music. While I suspect it really needs to be completely re-worked, for the moment I spread the functionality over three classes;

GameState – Really just holds & manages an enum used to determine the games current state (title screen, game over screen, in-game, etc) and the games last state.

GameStateManager – Is still rather overloaded since it does a lot more than just manage the GSM – Looks after the title screen buttons, manages highscore add, game over pause – Pretty much everything that isn’t ‘in-game’

InGameManager – Does handle everything in game (platforms, obstacles, player, etc) – It also manages the players score, background scroll speeds, etc.

It’s far from idea & both GameStateManager and InGameManager are still overloaded, but I think it is an improvement.

 


 

Instructions – I added some very simple instructions -To let players know what they can do (e.g. double jump) and how they can do it (keyboard mouse, gamepad). I try to keep instructions as simple as possible – & as free of words as possible – In case the player doesn’t speak English.

GamePad icon made by EpicCoders from http://www.flaticon.com
Mouse icon made by Freepik from http://www.flaticon.com

InstructionsALT

 


 

So, for version 1 at least, I think that’s pretty much everything. It’s far from perfect, but for my first attempt at a Unity game – not a complete failure – I’ve some very basic gameplay, a messy GSM, a working online highscore table and a much greater understanding of Unity.

As usual, a video showing the game, a link to the source code and a link to play the game online (WebGL) can be found below.

Thankyou!

 


 

Play this build (WebGL)

 


 

Grab a copy of the project here

 


 

 


 

Last post: 1.8 Obstacles

Contents page.