a small mobile game made in C# with the Unity engine
made by Cloud Worm in 2023
Ball Game is a physics-based game. You control a ball that you can shoot in any direction, with variable force; however, you may only shoot when the ball is touching something else, like a wall or the floor. You also have a limited amount of shots for each level, meaning that you must time each shot perfectly right.
Different materials will have different effects on the ball — while the regular, black walls does not bounce, pink walls will send your ball flying away. The game is all about aiming and timing your shots correctly to attain the final objective.
The game was created using the Unity game engine (version 22.2.6f1), and therefore the language C#. The source code is available at the official GitHub repository, and is licensed under the GNU General Public License.
The game is fully free and has no ads or microtransactions or whatnot. The source code is also written in a way that’s easy to understand for beginners, and is elegantly commented for easier reading.
There are two ways to get the game:
.apk
build from the GitHub releases page.$ git clone "https://github.com/cloud-worm/ball-game"
Several tricks are used in the code to make it more performant and easier to read — in fact, creating clear, efficient code was of my main goals here, since my scripts sometimes end up unreadable. For example, instead of using a bunch of booleans and therefore having many unnecessary binary operations, I used a simple enum
to represent each state of the player control:
public enum State
{
Playing,
Ended,
CanRestart,
}
Each state corresponds to what the player can do at a given time — Ended
is when they lose, for example, and CanRestart
is when they can touch the screen to try a failed level again.
To access specific data for each level (such as the amount of shots the player has), I have created a class called LevelDetails
, which contains public variables that I can access in the Player.cs
script and methods that allow me to fetch level data. This is probably not optimal, but it works well and is quite practical. Here’s an example:
public class LevelDetails
{
public int number; // Level number
[HideInInspector]
public Dictionary<int, int> levelAttempts = new Dictionary<int, int>()
{
{ 1, 1 },
{ 2, 2 },
{ 3, 3 },
};
// [...]
}
This class also boasts the following function, facilitating data retrieval:
public int NumAttempts() { return levelAttempts[number]; }