Gigi Labs

Please follow Gigi Labs for the latest articles.

Friday, June 21, 2013

C#: Value Types vs Reference Types

Hi all! :)

I'll be writing a few articles about Object Oriented Programming (OOP), but before I do that, there's something I need to explain. In this article, I will be discussing the difference between value types and reference types, as well as the use of the ref keyword.

Let us first create a new console application using SharpDevelop (or Visual Studio, if you prefer). In this application, we declare a struct that represents a monster in a game (if you don't remember structs, look back at "C# Basics: Snake Game in ASCII Art (Part 1)"):

    struct Monster
    {
        public string name;
        public int health;
    };

This struct goes under the namespace, at the same level as class Program. We can now make instances of Monster in the Main() method:

            Monster wolf = new Monster();
            wolf.name = "Rex";
            wolf.health = 100;
           
            Monster steve = new Monster();
            steve.name = "Steve Ballmer";
            steve.health = 10;

Next, we define a couple of methods that work on a monster and modify its attributes:

        public static void RenameMonster(Monster monster, String newName)
        {
            monster.name = newName;
        }
       
        public static void HurtMonster(Monster monster, int damage)
        {
            monster.health -= damage;
        }

In Main(), we can test this:

            Console.WriteLine("Monster's name before: {0}", wolf.name);
            RenameMonster(wolf, "Wolverine");
            Console.WriteLine("Monster's name after: {0}", wolf.name);
           
            Console.WriteLine("Monster's health before: {0}", wolf.health);
            HurtMonster(wolf, 5);
            Console.WriteLine("Monster's health after: {0}", wolf.health);
           
            Console.ReadLine();

The output, however, is not quite what we were expecting:



If we change the Monster from a struct to a class and re-run the program, on the other hand, it works correctly:


So, what exactly is happening here? A struct is an example of a value type. When you pass it as a parameter to a function, a copy of it is actually passed to the function. If you modify it within that function, you are actually modifying the copy. When the function returns, the struct still has its old values.

A class, on the other hand, is a reference type. When you pass an instance of a class (i.e. an object) as a parameter to a function, the object itself is passed. You can make changes to the class's members and they are retained even after the function returns.

Most simple data types (such as integers, floats, etc), as well as structs and enumerations, are value types. Classes and strings are reference types, although a string behaves pretty much like a value type when passed to a function (see an explanation on Stack Overflow, if you're interested).

[Sidenote for purists: in C#, functions are actually called "methods". I consider the term "method" to be more of an OOP thing, and what we're doing here isn't quite OOP.]

It is, however, possible to pass a value type by reference. Let's say you have this function:

        public static void Increment(int x)
        {
            x++;
        }

If we try to call this function on a variable as it is, we're back to square one:


However, we can use the ref keyword to mark parameters that we want to pass by reference:

        public static void Increment(ref int x)
        {
            x++;
        }

...and do the same in the calling code:

            Increment(ref x);

This gives the result we want:


Wonderful. The bottom line is that structs and classes are very similar, but there are a few subtle differences (such as value type vs reference type, stack allocation vs heap allocation, etc) that can affect the way your code works. The differences are particularly clear if you know what pointers are. We will be using classes a lot for Object Oriented Programming (OOP), so it's important to know a little bit about them.

In the next article, we will dive straight into OOP! :)

Saturday, June 15, 2013

Indexing and Search (C#)

Hello once again, and welcome to this new article at Programmer's Ranch! :)

Today we're going to talking about indexing and search: what is it that allows you to search through thousands of documents in less than a second?

In order to understand how indexing works, we will use an example where we have the following three documents:

        doc1.txt contains:
        The Three Little Pigs

        doc2.txt contains:
        The Little Red Riding Hood

        doc3.txt contains:
        Beauty And The Beast

Now, let's say you want to find out which of these documents contain a particular word, e.g. "Little". The easiest way to do this would be to go through each word in each document, one by one, and see if the word "Little" is in that document. Conceptually, we're talking about this:


Doing this in C# is very easy:

            String[] documents = { "doc1.txt""doc2.txt""doc3.txt" };
           
            String keyword = Console.ReadLine();
           
            foreach (String document in documents)
            {
                if (File.ReadAllText(document).Contains(keyword))
                {
                    Console.WriteLine(document);
                }
            }

            Console.ReadKey(true);

Remember to put in a using System.IO; at the top, to be able to use File. If you press F5 and test this program, you'll see that it works:


However, this method isn't good because it will take longer as the documents get larger (more words) and more numerous (more documents).

The proper way to process search requests quickly is to build an index. This would look something like this:


The index stores a list of all words, each with a list of documents that contain it. If you compare it with the first diagram, you'll notice that we reversed the mapping of words and documents; this is why we call this an inverted index.

We can do this in C# by first building the index (remember to add using System.Collections.Generic; at the top):

            // Build the index
           
            String[] documents = { "doc1.txt""doc2.txt""doc3.txt" };
            Dictionary<String, List<String>> index = new Dictionary<String, List<String>>();
           
            foreach (String document in documents)
            {
                String documentStr = File.ReadAllText(document);
                String[] words = documentStr.Split();
               
                foreach (String word in words)
                {
                    if (!index.ContainsKey(word))
                        index[word] = new List<String>();
                   
                    index[word].Add(document);
                }
            }

...and then using the index to search the documents quickly and efficiently:

            // Query the index
           
            String keyword = Console.ReadLine();
           
            if (index.ContainsKey(keyword))
            {
                foreach (String document in index[keyword])
                {
                    Console.WriteLine(document);
                }
            }
            else
                Console.WriteLine("Not found!");

            Console.ReadKey(true);

In this way, there is no need to search every document for the keyword each time the user wants to search for a word. The keyword is simply located in the index (if it exists), and a list of documents that contain it is immediately available:


This was a simple proof of concept of how indexing and search works, but here are a few additional notes:

  • The index is usually built as documents are added to it, and then stored in one or more files (unlike in this program, where the index is rebuilt every time the program is run - that's just to make the illustration easier).
  • Words such as "and" and "the" which are very common are called stop words and are normally excluded from the index.
  • It is common practice to make searches case insensitive, e.g. by converting indexed words and query keywords to lowercase.

This article presented the concept of indexing and how it is used to search for a single keyword. Although there are other techniques used in text search, indexing is definitely one of the most important, and has many applications including databases and text retrieval (e.g. search engines). A fundamental concept to remember is that the whole point of indexing is to make search fast!

Thanks for reading! :) Feel free to leave feedback (positive or negative) either in the comments or by contacting me. Remember to subscribe to the Programmer's Ranch Facebook page to stay up to date with articles as they are published!

Monday, June 10, 2013

Unity3D: Arkanoid

Hullo! :)

One of the subscribers of the Programmer's Ranch Facebook page requested an article on creating Arkanoid with Unity. So... here you go. :)

Create a new Unity project and save your scene. Set up your scene using scaled up cubes for the scene boundaries (except for the bottom), and put in another cube for the paddle and a sphere for the ball:



Make sure that all objects have the same z-coordinate for position, and that they are visible to the camera.

The game mechanics for Arkanoid are very similar to those of Pong, so we will be following very similar steps. As a matter of fact, we can use the same Ball script we used in Pong. Create a new C# script, attach it to the sphere, and after opening it in MonoDevelop, paste the code we used in Pong:

public class Ball : MonoBehaviour
{
    private Vector3 direction;
    private float speed;
 
    // Use this for initialization
    void Start ()
    {
        this.direction = new Vector3(1.0f, 1.0f).normalized;
        this.speed = 0.1f;
    }
 
    // Update is called once per frame
    void Update ()
    {
        this.transform.position += direction * speed;
    }
}

Attach a Rigidbody to the sphere via Component menu -> Physics -> Rigidbody, which will allow the ball to bounce off surfaces. Remember to turn off "Use Gravity".

Next, select the Main Camera and change Projection from Perspective to Orthographic to remove perspective and end up with a more suitable 2D view. Change the Size property until the scene fits the camera's view properly:


Create a new C# script and name it Paddle. Attach it to the cube to be used as a paddle. Paste the following code to enable left and right movement via arrow keys:

public class Paddle : MonoBehaviour
{
    private float speed = 0.1f;
 
    // Use this for initialization
    void Start ()
    {
 
    }
 
    // Update is called once per frame
    void Update ()
    {
        if (Input.GetKey(KeyCode.LeftArrow))
            this.transform.position += Vector3.left * speed;
        if (Input.GetKey(KeyCode.RightArrow))
            this.transform.position += Vector3.right * speed;
    }
}

This is quite similar to what we did in the Pong article, except we're moving left and right instead of up and down. We are using the static vectors Vector3.left and Vector3.right, which are really just shortcuts for unit vectors along the particular directional axis (in this case (-1, 0, 0) and (1, 0, 0), respectively). We similarly used Vector3.up ((0, 1, 0)) and Vector3.down ((0, -1, 0)) in Pong.

We can now take care of the bricks. Since we will have a lot of them, it's best to create a prefab. From the GameObject menu, select Create Other -> Cube, and drag it into the Project panel in Unity to make a prefab out of it. Rename it to Brick. Create a new tag called Brick and tag your brick as such. Remember to click the Apply button in the inspector to make the tag apply to all instances of the prefab.

Proceed to duplicate (Ctrl+D) the brick so that there are many bricks in the top part of the screen:


To make the ball destroy bricks as it hits them, add the following code at the end of the OnCollisionEnter() method in the Ball script:

        if (collision.gameObject.tag == "Brick")
            GameObject.Destroy(collision.gameObject);

You can now play happily as the ball destroys bricks but not the paddle or the edges:


That wraps up the basic game mechanics for Arkanoid. As an exercise, add victory (for when you clear all the bricks) and defeat (for when the ball escapes below the paddle) conditions.

In these recent tutorials about classic arcade games, I have purposely focused exclusively on game mechanics (e.g. bouncing, shooting, etc). This was intentional. When making a game, you should first concentrate on making solid game mechanics that work perfectly. Then, you can focus on building the rest of the game (levels, menus, screens between levels, etc) and polishing (colours, animation, etc).

In fact, this Arkanoid game looks like shit. The first thing I'd do after finishing the game mechanics is give it a touch of colour (via materials, and put in a point light to brighten the colours):


...and here's what it looks like in-game:


This colouring took a couple of minutes to do, and I think you'll agree with me when I say that the game looks much more alive. Making the game vibrant and fun is just as important as programming the game mechanics, so don't overlook it!

Thanks for reading, and I hope you found this useful! :)

Friday, June 7, 2013

Unity3D: Pong

Hi folks! :)

Today we're going to see how to create a game like Pong, one of the earliest classic arcade video games, using Unity3D. The approach for movement is very similar to the one we used in "C# Threading: Bouncing Ball", although we don't have to worry about threads in this case.

After creating a new project, use the GameObject -> Create Other menu to set up the scene using four cubes and a sphere. After scaling the cubes to be elongated, put one on each side: at the left and right as paddles, and at the top and bottom as walls that the ball can then bounce on:


One thing you'll notice is that the paddles don't look like straight lines - they are seen as if from the side. That's because we're using a perspective camera. For a game like Pong, where we don't care about perspective, an orthographic camera is probably better.

Select the Main Camera from the Hierarchy panel, and change the Projection property from Perspective to Orthographic. Change the Size property until the game objects fit the camera's view comfortably (check this by pressing Play in Unity, not from the camera preview, since the resolution is different):


Now, let's make the ball move. Right click in the Project panel and select Create -> C# Script. Name it Ball and drag it onto the Sphere. Double-click the script to open it in MonoDevelop.

Just like in "C# Threading: Bouncing Ball", we now give the ball a direction and a speed with which to move (Physics people will know they are together called velocity):

public class Ball : MonoBehaviour
{
    private Vector3 direction;
    private float speed;
 
    // Use this for initialization
    void Start ()
    {
        this.direction = new Vector3(1.0f, 1.0f).normalized;
        this.speed = 0.1f;
    }
 
    // Update is called once per frame
    void Update ()
    {
        this.transform.position += direction * speed;
    }
}

The normalized part is something we do for convenience. A normalised vector has a magnitude of 1, making it easy to work consistently with it. We then modify the speed using the speed variable.

In order to implement the bounce effect, we have the ball detect collisions, and change trajectory when a collision occurs:

    void OnCollisionEnter(Collision collision)
    {
        Vector3 normal = collision.contacts[0].normal;
        direction = Vector3.Reflect(direction, normal);
    }

Take a look at this diagram to understand what's happening here:


In order to make the ball bounce, we need to find where it hits a wall or paddle, and change its direction. We reflect the direction in the surface normal, which is at 90 degrees to the surface itself. In Unity, we get that surface normal from the point of contact with the surface, which is available from collision.contacts.

Although it is good to know the vector mathematics behind vector reflection, in Unity3D this is as easy as using Vector3.Reflect() and passing in the incident direction and the surface normal.

In order for this to work. You will need to add a rigidbody to the Sphere, via Component menu -> Physics -> Rigidbody.

Now, just add another script for the paddle movement, and attach it to the paddles:

public class Paddle : MonoBehaviour
{
    private float speed = 0.1f;
 
    // Use this for initialization
    void Start ()
    {
 
    }
 
    // Update is called once per frame
    void Update ()
    {
        if (Input.GetKey(KeyCode.UpArrow))
            this.transform.position += Vector3.up * speed;
        if (Input.GetKey(KeyCode.DownArrow))
            this.transform.position += Vector3.down * speed;
    }
}

Enjoy the game!


In this article, we created a simple Pong game and learned about orthographic vs perspective cameras as well as vector reflection (used to bounce an object off a wall).

This simple game mechanic can be used for various classic games including Pong and Arkanoid.

The only thing we didn't do is handle when the ball leaves the area, in which case the player should lose the game. I'll leave that as an exercise since it's quite trivial (you can do something like how we handle bullets in "Unity3D: Space Invaders (Part 4 - Collisions)", and when the ball leaves the area, you change to a different scene showing a loser's screen - see "Unity3D: Scenes and Building").

In the next article, we will revisit the bouncing ball theme and make an Arkanoid clone. So check back! :)

Tuesday, June 4, 2013

Unity3D: Scenes and Building

Hi people! :)

Today we're going to learn about scenes in Unity. Scenes allow us to have different levels, both for gameplay as well as to incorporate things like the game menu, credits screen, etc.
  • Create a new project in Unity, and press Ctrl+S to save your first scene. Call it "Level1".
  • Bring a cube into the scene via GameObject menu -> Create Other -> Cube.
  • Then, right click in the Assets panel and select Create -> C# Script. Call it "NextLevel".
  • Drag the "NextLevel" script onto the cube.
  • Double-click the "NextLevel script to open it in MonoDevelop.
In the Update() method, put this:

        if (Input.GetMouseButtonDown(0))
        {
            int levelCount = Application.levelCount;
            int currentLevel = Application.loadedLevel;
            
            if (currentLevel < levelCount - 1)
                Application.LoadLevel(currentLevel + 1);
        }

This will allow you to move to the next level (if there is one) when the user clicks the left mouse button. I'll explain this in a minute.

First, let's create another two scenes (levels). You can do this either via the File menu -> New Scene, or else by selecting a scene in your Assets panel, and pressing Ctrl+D to duplicate it. When you double-click another scene in the Assets panel, Unity will open that scene instead of your old one, so make sure you always save before changing scene.

Create another two scenes using whichever method you prefer. Put a sphere in level 2, and a cylinder in level 3. Drag the "NextLevel" script onto each of these objects. In each scene, adjust the position of the objects so that they are visible to the camera.

Once you are ready, it's time to set up the order of the scenes in the game. Go to File -> Build Settings...:


From the Assets panel, drag the scenes into the "Scenes in Build" area of the Build Settings window:


The scenes are automatically ordered, as you can see from the corresponding number on the right. This means that Level1 is the first scene to be loaded, and the next one is Level2. You can reorder the scenes by dragging them up or down, and you can remove them by selecting them and pressing Delete.

Now, you can test this by opening Level1 in Unity and pressing Play. Level1 (the one with the cube) is loaded first. By clicking the left mouse button, you can transition to the two other scenes.

Back to the code above, Application.levelCount gives you the total number of scenes in your game, in this case 3 (note that they must be listed in the Scenes in Build for them to be considered). Application.loadedLevel gives you the index of the currently loaded level (the ones on the right hand side of Scenes in Build, starting from zero). Application.LoadLevel allows you to transition to any scene you want, by specifying its index.

For the record, it is also very easy to reload the current scene in cases where the player wants to restart the current level.

Finally, the Build Settings screen is also the place to go if you want to distribute your game. From here, you can create executable versions of the game. There are many supported platforms, and recently Unity is also allowing developers to build on iOS and Android for free - something that until recently would have cost several hundred dollars.

In summary, scenes are a great way to split up your game into several different levels that don't depend on each other. You can use them for different game levels, a main menu, credits/help screens, etc. The Application class provides methods and properties allowing you to work with scenes.

Thanks for reading, and stay tuned for more! :)

Saturday, June 1, 2013

Unity3D: Space Invaders (Part 5 - Behaviour)

Hi all! :)

In yesterday's article - Unity3D: Space Invaders (Part 4 - Collisions) - we learned how to handle collisions in Unity. At the end of the article, we listed several items that are still missing from Ranch Invaders.

Today's article deals with some of those issues, mainly relating to Player and Alien behaviour.

Player Movement

In Space Invaders, the Player's ship moves only left and right. If you've read "Unity3D: Moving an Object with Keyboard Input", you'll know that this is really easy to do. Open the Player script with MonoDevelop. You should currently have the code for shooting:

    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(bullet, this.transform.position, Quaternion.identity);
        }
    }

Change it as follows to allow the Player to move using the left and right arrows:

    void Update ()
    {
        Vector3 pos = this.transform.position;
       
        if (Input.GetKeyDown(KeyCode.Space))
            Instantiate(bullet, this.transform.position, Quaternion.identity);
        if (Input.GetKeyDown(KeyCode.LeftArrow))
            this.transform.position = new Vector3(pos.x - 0.1f, pos.y, pos.z);
        if (Input.GetKeyDown(KeyCode.RightArrow))
            this.transform.position = new Vector3(pos.x + 0.1f, pos.y, pos.z);
    }

Great, you can now move the Player's ship left and right. There's a problem, however. If you hold down an arrow key, the Player's ship does not continue moving. We can fix this by using Input.GetKey() instead. Also, we need to set constraints to prevent the Player's ship from leaving the screen:

    void Update ()
    {
        Vector3 pos = this.transform.position;
       
        if (Input.GetKey(KeyCode.Space))
            Instantiate(bullet, this.transform.position, Quaternion.identity);
        if (Input.GetKey(KeyCode.LeftArrow) && pos.x > -2.5f)
            this.transform.position = new Vector3(pos.x - 0.1f, pos.y, pos.z);
        if (Input.GetKey(KeyCode.RightArrow) && pos.x < 2.5f)
            this.transform.position = new Vector3(pos.x + 0.1f, pos.y, pos.z);
    }

Cooldown

As it is, the Player can fire as many bullets as it likes, with no gap between one and another. In order to implement a cooldown, we use an approach similar to this. When a bullet is fired, the time is recorded and no bullet may be fired before the cooldown period has passed. To do this, declare the following variables in the Player class:

    public float cooldown = 1.0f; // minimum time between bullets
    private float nextFire = 1.0f; // next time when a bullet can be fired

Then, adjust the firing code as follows:

        if (Input.GetKey(KeyCode.Space) && Time.time >= nextFire)
        {
            nextFire += cooldown;
            Instantiate(bullet, this.transform.position, Quaternion.identity);
        }

Then, try it out, and adjust cooldown as you like:


Then, rejoice.


Alien Movement

In Space Invaders, aliens move right, down, left, down, etc. Making this work properly takes a bit of work, so I'll just give you the code:

public class Alien : MonoBehaviour
{
    public float horDistance = 1.0f;
    public float verDistance = 0.5f;
    public float speed = 0.4f;
    private float startTime;
    private Vector3 startingPosition;
    private Vector3 target;
   
    // Use this for initialization
    void Start ()
    {
        this.startTime = Time.time;
        this.startingPosition = this.transform.position;
        this.target = this.startingPosition + new Vector3(this.horDistance, 0, 0);
    }
   
    // Update is called once per frame
    void Update ()
    {
        Vector3 currentPosition = this.transform.position;
        Vector3 newPosition = Vector3.MoveTowards(currentPosition, this.target, speed * Time.deltaTime);
        this.transform.position = newPosition;
       
        //print (this.target);
       
        if (newPosition == target)
        {
            if (newPosition.x == startingPosition.x)
            {
                if (((newPosition.y - startingPosition.y) / verDistance) % 2 == 0)
                    this.target = newPosition + new Vector3(this.horDistance, 0, 0);
                else
                    this.target = newPosition - new Vector3(0, this.verDistance, 0);
            }
            else
            {
                if (((newPosition.y - startingPosition.y) / verDistance) % 2 != 0)
                    this.target = newPosition - new Vector3(this.horDistance, 0, 0);
                else
                    this.target = newPosition - new Vector3(0, this.verDistance, 0);              
            }
        }
    }
}

Don't fret about what the code is doing... just use it. Tweak the public variables as you like.

More Aliens

Since we need a lot of aliens, it's a good idea to make the Alien object a prefab. To do this, drag it from the Hierarchy panel to the Assets panel. If you did it right, its listing in the Hierarchy panel should turn blue. This way, if you make any changes, you can apply them across all Aliens.

To make multiple Aliens, you can either press Ctrl+D (duplicate) to create additional objects, or else instantiate all the aliens in code using for loops. In my case, I just duplicated a handful of Aliens, just for testing:


Don't get too fussy about the Alien placement and all that. The reason we're still working with cubes and spheres is that you should first concentrate on making sure that your game mechanics work correctly. Only once that is done should you spend some time (a lot of time, actually) making it look good.

Aliens Shooting

Allowing Aliens to shoot the Player is no different from allowing the Player to shoot the Aliens. However, you now need a different bullet that moves downwards and that can destroy the player.

Once you attach a rigidbody to the Player (Component -> Physics -> Rigidbody, and remember to turn off "Use Gravity"), you will find some unexpected behaviour: at times, when the Player shoots a bullet, the Player itself is destroyed! That's because we don't yet have any code in the Bullet script that distinguishes between objects it can destroy. So far it worked correctly only because the Player didn't have a rigidbody, in which case the collision doesn't happen.

An easy way to solve this is to tag the object. Select the Player. At the top of the Inspector is a section where you can select a tag to assign to the object. For the Player, you can choose the predefined Player tag:


For the Aliens, you will need to add a new tag. From the drop-down list containing tags (shown above), select "Add Tag...".


In the resulting interface (shown above), expand the "Tags" node. Next to "Element 0", type "Alien". This creates the "Alien" tag, but does not assign it to the object.


To tag the Alien as such, select an Alien object, and select the newly available "Alien" tag from the drop-down list. Remember to click "Apply" to make this work for all Alien objects (since it's a prefab).

The Bullet script's collision code now becomes:

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "Alien")
        {
            GameObject.Destroy(collision.gameObject);
            GameObject.Destroy(this.gameObject);
        }
    }

The Player's bullets should now destroy only Aliens.

For the aliens to shoot at the player, you will first need to create another bullet prefab (e.g. "AlienBullet") with the same script as the Bullet, except for two key differences. First, the bullet needs to go downwards instead of upwards. So:

    void Start ()
    {
        this.target = this.transform.position - new Vector3(0, 20, 0);
    }

Secondly, it needs to collide with the Player instead of the Alien:

void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "Player")
{
GameObject.Destroy(collision.gameObject);
GameObject.Destroy(this.gameObject);
}
}


Finally, the code for shooting (in the Alien script) will be a little different from that of the Player. Instead of shooting when the user presses a key, the Alien will shoot with a random delay. First, declare the following variables in the Alien class:

    public GameObject bullet;
    public float minShootDelay = 1.0f;
    public float maxShootDelay = 7.0f;
    private float nextShootTime = 0.0f;

In the Unity editor, set the AlienBullet prefab in the Alien script's bullet slot.

In the Start() method, add code to initialise nextShootTime:

        this.nextShootTime = Random.Range(minShootDelay, maxShootDelay);

Unity's Random.Range() method is similar to .NET's Random.Next() method, but not quite the same.

Change the code that handles when bullets leave the game area, since these bullets are going down instead of up:

        if (this.transform.position.y < -3.0f)
            GameObject.Destroy(this.gameObject);

Finally, in the Update() method, we add code for actual shooting:

        if (Time.time > nextShootTime)
        {
            Instantiate(bullet, this.transform.position, Quaternion.identity);
            nextShootTime = Time.time + Random.Range(minShootDelay, maxShootDelay);
        }

If you try it now, things will get a little bit messy as the Aliens' bullets will collide with themselves:


Explaining how to solve this requires an article in itself. Notwithstanding this, in this (long) article we have taken care of several behaviour issues with both the Player and the Aliens, and brought the game much closer to a working Space Invaders clone.

This is the last article in the Ranch Invaders series. I hope you'll return to the Ranch to read about other interesting topics! :)