When I was about 4 years old I lived in polish countryside. My house was surrounded with wooden fence. It was similar to one shown on photo bellow.
(Photo source: https://www.wymarzonyogrod.pl/ogrodzenia-nawierzchnie/ogrodzenia-ogrodu/ogrodzenia-z-drewna-drewniane-poty-zdjecia,36_502.html)
Anyway, one day one of the gateways broke down – one of the bands corroded and someone had to replace it. And just before my father got his toolbox, I took my small hammer (you know, that one used to break shells of peanuts) and said something like „Hold on there, I will do it!”. And I did!
Well it maybe was not the best fix that could be applied. It probably took something about an hour, and I used dozen of nails (and lost another dozen), and my parents are joking about that even today, but the gate was legitimately fixed.
I was cute ‚lil boy back then.
But that post is not about my engineering skills back in the 1998. It is about my engineering skills back in the 2015.
If you check out my previous posts, you will find that making video games is my ‚thing’. They are reason that ultimately leaded me to computer science course at university. I tried music, art and writing (and wasn’t great at them) but programming got me really hooked.
I was fascinated with idea, that you can make computer ‚do things’. Like finding prime numbers, changing random words on website to funnier ones or displaying a huge tank battle in ‚Command & Conquer: Red Alert’. Obviously, the last one was most fascinating for me.
So I learned hard. First there was C/C++ then bits of C# and some basic concepts of OOP. By the end of first university year thanks to my passion for programming i had no problem with passing all programming related classes (other story with math – but that’s for different time). Still, I didn’t knew why my teacher got mad every time I’ve put my whole program in main() function.
Most importantly – had completely no idea how to bite the video game. Back then my most complex creation ever was a „Rock, paper scissors” game (that was written completely in main() function by the way). Then I heard about that hot video game engine called Unity. It used C# for scripting language – I knew some C# so i decided to watch some tutorials, and then create something on my own. And that was exactly what I did.
Now, dear reader when you are aware of context, let’s dive into code of that thing, shall we?
First of all – you are welcome to play it here.
This is the original „release” of the game. The only thing I did was compiling it to HTML5/JS. I want you to experience it it’s initial state.
Okay, back to business. Let’s look at class diagram generated by Visual Studio.
It will be a point of reference during our little journey. Let’s start from GameController, precisely with Start method.
void Start () { if(isGameOn){ BallsUsed=0; Paddle.SetActive(true); Paddle.transform.position=new Vector2(7.72f,-7.04f); PaCon.ShieldsStatus=100; StartCoroutine("SpawnNewBall"); } }
For those not familiar with Unity – Start and Update are special methods that are executed automatically. Start is called on start of object existence, as sort of setup, and Update is called on every frame of game. So… why is there condition statement checking state of isGameOn? Maybe, if we look at isGameOn declaration it will clarify some things…
public bool isGameOn=false;
Well, there it is. Initialized with default value. So Start method does indeed nothing on start (I know, it was hard to see that, because of shitty code formatting).
But there must be some way to set isGameOn to true, right? Oh, look – there it is!
public void NewGame(){ isGameOn=true; PC.Start (); AudioSource.PlayClipAtPoint(startUpSound,transform.position); newGameButton.SetActive(false); gameOver.gameOverScreen.SetActive(false); //HiScoresTable.SetActive(false); Start (); }
So, as you see it sets isGameOn to true does some changes to UI and then… calls Start. Not only it’s own start. Also in PC which stands for PointsCounter. Let’s see what’s in there.
// Use this for initialization public void Start () { BallsUsed =0; }
(That comment appears in script files generated by Unity)
Oh, so it just sets BallsUsed to zero?
Okay, let’s calm down. I will try to explain how the game handles failure state. We are now diving into GameOver class
void OnTriggerEnter2D(Collider2D col){ if(col.tag=="Ball"){ //Game will be displaying some "funny" messages //RandomNumber=Random.Range(0,4); //gameOverTexts[RandomNumber].SetActive(true); //gameOverTexts[RandomNumber].transform.position= new Vector2(col.transform.position.x,col.transform.position.y); Destroy (col.gameObject); Debug.Log("Collision!"); GC.BallsUsed++; AudioSource.PlayClipAtPoint(gameOverSound,transform.position); if(GC.isGameOn)GC.StartCoroutine("SpawnNewBall"); } }
OnTriggerEnter2D is another special method in Unity API. It is called whenever trigger is, well, triggered. It also takes Collider of object that came in contact as parameter. Wait… trigger? In GameOver class? Yeah, since GameOver script was attached to Walls that purpose was to destroy balls coming into contact with them. So that basically changes some variables in GameController class, that to be honest could be wrapped in one method.
But we still didn’t found what we were looking for. So maybe FixedUpdate will give us the answers?
void FixedUpdate(){ if(PC.ShieldsStatus<=0){ if(GC.isGameOn){ Paddle.SetActive(false); gameOverScreen.SetActive(true); GC.isGameOn=false; GC.newGameButton.SetActive(true); //HiScoresTable.SetActive(true); AudioSource.PlayClipAtPoint(gameOverSound,transform.position); } } }
FixedUpdate is Update equivalent used when dealing with game physics. So… Not in case shown above. And also it checks variables in GameController in EVERY frame. That (and some other cases in this codebase) is probably reason why this thing works so slow (an throws OutOfMemory exception on Firefox).
I also found interesting the way how MusicScript works
void Start () { MusicButon.text="Music: On"; IsMusicOn = true; GC.Music[0].SetActive(true); GC.Music[1].SetActive(false); } // Update is called once per frame void Update () { if(IsMusicOn){ if(GC.isGameOn){ GC.Music[1].SetActive(true); GC.Music[0].SetActive(false); }else{ GC.Music[0].SetActive(true); GC.Music[1].SetActive(false); } MusicButon.text="Music: on"; }else{ GC.Music[0].SetActive(false); GC.Music[1].SetActive(false); MusicButon.text="Music: off"; } } public void SetMusic(){ IsMusicOn = !IsMusicOn; } }
I think, that words „not the most efficient” are now in your head.
So I probably could go on and on for pages what is wrong, and for some more how to fix it (fixing this may be hard… but isn’t that great idea for blog post series?). Anyway revisiting my first big software project was fun experience. The game also was fun! It had some unique mechanics, and I personally like it’s arcade cabinet style (despite it’s shitty UI). I probably wouldn’t be where I am right now as a developer without making that game.
So let’s end this little code review with ExitGame class.
public class ExitGame : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } public void Exiting(){ Debug.Log("Exiting"); Application.Quit(); } }