In my previous post, I introduced my latest Android game – Down the hill – a one-click game, based on the the Emoji Down the hill template. In this post, I’d like to discuss the development process and changes I made to the template.
Handling the “premium” features
The template comes with a few “premium” feature, which are based on the Easy Mobile asset and costs somewhere between 35$ and 50$, depending on any ongoing sale in the Assets Store.
The features include:
- Advanced ads support, which I just replaced with my own simple implementation that supports only AdMob
- Leaderboards and achievements, which again I replaced with with my own simpler implementation
- In-app purchase to remove the ads – I just removed that functionality
- Native sharing to share screenshots of the game – which I also removed
- Push notifications and alerts, which I also removed.
Down “the hill”
Emoji Down the hill came with the code that generates the random hill, which included the the normal ground, empty ground (hole) and trees. The code was quite simple to understand and work with, but wasn’t well designed to support more variations of the grounds, so I started redesigning and implementing it:
public enum GroundType
{
Normal,
Hole,
Locked,
Left,
Right
}
[Serializable]
public class Ground
{
public string name;
public Sprite sprite;
public float frequency = 0.02f;
public GroundType type;
public Range range;
}
[Serializable]
public class Range
{
public int min = -1;
public int max = -1;
public bool IsRelevant(int level)
{
if (min == 0 && max == 0)
return true;
var adjustedLevel = level % Consts.maxRange;
return min < adjustedLevel && adjustedLevel <= max;
}
}
Nothing fancy here – the only part worth explaining, is the “range” concept – I wanted to control when certain ground types can be used – to avoid overwhelming the player too early. This allows me to control the fact that left & right grounds appear only when the player reaches level 50 and beyond…
Generating a wave of grounds is now just about selecting a random ground, with some special handling for holes.
GroundType selectedGroundType = GroundType.Normal;
foreach (var ground in theme.grounds)
{
if (!ground.range.IsRelevant(ScoreManager.Instance.Score))
continue;
bool hasGround = Random.value < ground.frequency;
if (hasGround)
{
if (ground.type == GroundType.Hole && !has5Cubes)
{
bool deleted = false;
if (countVacancy < 3)
{
DeleteCube(myCubes[index]);
countVacancy++;
holeFrequency -= 0.35f;
deleted = true;
}
if (countVacancy == 3)
{
has3Holes = true;
}
if (deleted)
{
selectedGroundType = GroundType.Hole;
break;
}
}
else if (ground.type != GroundType.Hole)
{
selectedGroundType = ground.type;
var terrain = myCubes[index].GetComponent<TheTerrian>();
terrain.type = ground.type;
terrain.GetComponent<SpriteRenderer>().sprite = ground.sprite;
break;
}
}
}
Special handling for the hole type, is there to prevent having too many holes in the same wave – up to 3.
Dropping items
For items, power-ups and coins, we have a very similar code:
[Serializable]
public class Event
{
public string name;
public GameObject prefab;
public float frequency = 0.02f;
public Vector3 position = Vector3.zero;
public Range range;
}
When the ground is of type Normal, we can decide if we want to place something on it:
foreach (var gameEvent in theme.events)
{
if (!gameEvent.range.IsRelevant(ScoreManager.Instance.Score))
continue;
bool hasEvent = Random.value < gameEvent.frequency;
if (hasEvent)
{
GameObject x = Instantiate(gameEvent.prefab);
x.gameObject.name = gameEvent.name;
x.transform.SetParent(myCubes[index].transform);
x.transform.localPosition = gameEvent.position;
break;
}
}
Characters
Once again, the template comes with a very simple code – just a list of sprites – with all characters available to the player. I wanted something more complex than that – I wanted players to collect coins, and use them to purchase new characters. So I started with defining a Character class:
[Serializable]
public class Character
{
public string ID = "";
public Sprite sprite;
public int price;
public bool available
{
get { return PlayerPrefs.GetInt("Character:" + ID) > 0; }
}
public bool canPurchase
{
get { return PlayerPrefs.GetInt("Coins") >= price; }
}
public void Purchase()
{
PlayerPrefs.SetInt("Character:" + ID, 1);
}
}
From there, it was just a matter of updating the UI and the character manager to support the new class.
Down the hill – the next version
That’s it for now – there was a lot of more work to do – handling the collision with all new ground types, adding the support for the coins, daily gift of coins, etc..
Depending on the number of downloads the game will get, there are a few additional improvements that I’m considering implementing:
- Support for themes – as the player advances, expose him to themed environments, such as a desert, snow, etc.
- Additional ground types and items, to make the game more challenging and interesting
- Social support – adding back social sharing, etc.