Gigi Labs

Please follow Gigi Labs for the latest articles.
Showing posts with label vectors. Show all posts
Showing posts with label vectors. Show all posts

Sunday, August 4, 2013

Unity3D: Changing game speed and pausing

Hi!

Today's article is a little break from the OOP tutorials. Instead, we revisit the Unity3D game development engine (at the time of writing, version 4.2 was recently released) and learn about controlling time. This allows us to easily pause the game, slow it down, or speed it up.

Create a new project and add a sphere to your scene via GameObject menu -> Create Other -> Sphere. Next, create a new C# script by right clicking in the Project panel, and selecting Create -> C# Script. Name it Ball, and drag it onto your Sphere in the Hierarchy panel. Double-click the script to open it in MonoDevelop.

We're going to make a very basic bouncing ball just to be able to see the effects of our change in speed. Start off with the following code for the Ball script:

public class Ball : MonoBehaviour
{
    private Vector3 velocity;
   
    // Use this for initialization
    void Start ()
    {
        this.velocity = new Vector3(1.0f, 1.0f, 0.0f);
    }
   
    // Update is called once per frame
    void Update ()
    {
        this.transform.position += this.velocity * Time.deltaTime;
       
        if (this.transform.position.x > 5.0f)
            velocity.x = -velocity.x;
        else if (this.transform.position.x < -5.0f)
            velocity.x = -velocity.x;
        else if (this.transform.position.y > 6.0f)
            velocity.y = -velocity.y;
        else if (this.transform.position.y < -5.0f)
            velocity.y = -velocity.y;
    }
}

This will make the ball bounce when it reaches the sides of the screen. This may vary depending on your monitor so use whichever values work best.

We've used Time.deltaTime before. Games look interactive because they generate a certain number of images (frames) per second, usually something between 30 and 60. Time.deltaTime is the time between one frame and the next; multiplying this by the velocity makes the ball move pretty uniformly.

Another important property of the Time class is Time.timeScale. This is a measure of how quickly scripts and animations run, and is set to 1.0f by default. We can change this to make the game run at different speeds. To try it out, add the following code to the Ball script's Update() method:

        if (Input.GetKeyDown(KeyCode.P))
            Time.timeScale = 0.0f;
        else if (Input.GetKeyDown(KeyCode.N))
            Time.timeScale = 1.0f;
        else if (Input.GetKeyDown(KeyCode.F))
            Time.timeScale = 2.0f;
        else if (Input.GetKeyDown(KeyCode.S))
            Time.timeScale = 0.5f;

What we're doing here is:

  • If the player presses 'P' (pause), we set the time scale to zero, effectively stopping any movement in the game.
  • If the player presses 'N' (normal speed), we set the time scale to the default of 1.0f.
  • If the player presses 'F' (fast), we set the time scale to double the normal speed.
  • If the player presses 'S' (slow), we set the time scale to half the normal speed.
This simple property allows you to not only pause the game, but also to play the game at different speeds. Several games including Starcraft and Warcraft 2 have settings that allow you to tweak the game speed in order to make it more challenging or less frenetic.


This article showed how a single line of code in Unity3D is enough to change the speed of a game or pause it. Although this was a very easy tutorial, I hope you will also find it very useful in any games you make!

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! :)

Friday, May 24, 2013

Unity3D: Moving an Object with Keyboard Input

Hi! :)

Today we're going to take a first look at the Unity3D game development engine. This engine is pretty easy to use and has gained a lot of popularity in recent years. It supports multiple languages (including C#) and multiple operating systems (including PC, Mac, Linux. Android, iOS, and others). Therefore, aside from Programming on Linux with MonoDevelop, this is one other way you can use C# on non-Windows platforms. You will learn in this article that Unity actually uses MonoDevelop anyway.

The first thing you will need to do is to download and install Unity from their website.

Once you have installed it and gone through the initial registration screens (you should normally opt to use the free version if you're just learning), you will be asked to open or create a new project:


In the "Create New Project" tab, select a folder where your project will be created. You do not need to import any packages for this tutorial.


You are then taken to the Unity interface, and shown a welcome screen. You can close the welcome screen. From the Layout drop-down menu at the top-right, select "Tall" to switch to a different layout.

Next, from the GameObject menu, select Create Other -> Cube to place a cube into the game world.


The cube will now be listed in the Hierarchy section - this section shows you a list of objects in your game world. You can also see the objects in the game world itself, in the left portion of the screen. If you click on the cube, you can see its properties (e.g. position in the game world) in the Inspector:


The Inspector shows information about the game object, such as its position in the game world. You can move it around by either changing values in the Inspector, or dragging the coloured arrows drawn over the object in the game world.

Underneath the Hierarchy section, you have a Project section. Right click on the Assets panel in the right-hand-side of the Project section and create a new C# script:


The script appears under Assets. Call the script "Movement". Then, double-click the script to edit it. When you do this, MonoDevelop (bundled with Unity) opens as the default editor:


In the Update() method, add the following code:


        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            Vector3 position = this.transform.position;
            position.x--;
            this.transform.position = position;
        }


What are we doing here? In Unity, you can attach scripts to objects in order to make them do stuff. In our case, we will attach this script to the cube to be able to move it with the arrow keys.

The "this" in a Unity script refers to the object that the script is attached to (e.g. the cube). Each object has a transform property, which contains stuff like its position in the world. The position consists of a Vector3 which contains the x-, y- and z- coordinates of the object in the world.

The code above simply makes the object move left when the left arrow key is pressed, by varying the x-coordinate of the object's position. While it would normally make sense to modify x directly, you can't do that in Unity. Also, note that we are using different code from previous articles (such as "C#: ASCII Art Game (Part 1)"), because Unity has its own classes to handle this sort of stuff.

In MonoDevelop, press F8 to make sure that the code compiles. Then, switch back to Unity. Drag the Movement script onto the Cube object in the Hierarchy section. Once you click on the Cube in the Hierarchy section, you should see the Movement script in the Inspector:


Now, Press the Play button at the top of the Unity interface to start playing. The world view changes into an interactive rendering of the game:


Test the game by pressing the Left Arrow key. Doing this should move the cube to the left:


Press the Play button again to stop the game. In MonoDevelop, update the code to handle movement in all four directions:


        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            Vector3 position = this.transform.position;
            position.x--;
            this.transform.position = position;
        }
        if (Input.GetKeyDown(KeyCode.RightArrow))
        {
            Vector3 position = this.transform.position;
            position.x++;
            this.transform.position = position;
        }
        if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            Vector3 position = this.transform.position;
            position.y++;
            this.transform.position = position;
        }
        if (Input.GetKeyDown(KeyCode.DownArrow))
        {
            Vector3 position = this.transform.position;
            position.y--;
            this.transform.position = position;
        }


Press Play again in Unity to test it. Note that the cube returned to its original position. That is because each time you press Play, a new session is started with all objects having their default values.

Great! :) In this article, we learned about the Unity interface, and wrote a small script to move a cube in the game world. I have intentionally skipped certain details (e.g. navigation in the game world), as they will be covered in other articles. So check back later! :)

Thursday, May 16, 2013

C# Threading: Bouncing Ball

Hi all! :)

I hope you've enjoyed the articles so far, and found the little ASCII art games both entertaining and mentally stimulating. Towards the end of yesterday's article, C# Basics: Snake Game in ASCII Art (Part 2), we discussed the problems with the Snake game. One of them was that the snake wouldn't move on its own - you had to press a key in order to make the program do something.

In today's article, we're going to begin learning about threads, and use them to overcome this limitation. This time we're going to draw a ball bouncing all over the console window.

Start a new console application, and add the following struct before the class Program:

    struct Vector
    {
        public int X;
        public int Y;
       
        public Vector(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
    }

You'll notice this is exactly the same as the Location struct in C# Basics: Snake Game in ASCII Art (Part 1). Instead of just using it just as a location, we're also going to use it as a direction. You'll see what I mean in a minute. Add the following for starters:

            Console.OutputEncoding = System.Text.Encoding.GetEncoding(1252);
            Console.Title = "Bouncing Ball";
           
            Vector ballLocation = new Vector(40, 12);
            Vector direction = new Vector(-1, -1);

So ballLocation is the location in the console window where we're going to draw our ball. The direction represents where the ball will go next, relative to ballLocation. In this case, the ball starts at (40, 12) and moves in a northwest direction, so the next position will be (39, 11), and then (38, 10), and so on.

[This paragraph is a bit more advanced... feel free to skip it.] The Vector struct is simply a code representation of a mathematical vector, where a vector such as (3, 1) means "three steps to the right, one step down" (depending on what coordinate system you're using). I'm not going to get into the mathematics, but if you're interested, check out my "A Concise Introduction to Vectors" [PDF].

We're now going to add a loop to show the ball and then move it:

            while (true)
            {
                Console.Clear();
                Console.SetCursorPosition(ballLocation.X, ballLocation.Y);
                Console.Write((char) 4);
               
                ballLocation.X += direction.X;
                ballLocation.Y += direction.Y;
                Thread.Sleep(100);
            }

At the beginning, add the following which is needed by Thread:

using System.Threading;

The code above is an infinite loop; there no condition for which the while loop will end. In this loop, we show an ASCII diamond as our ball, and then simply add the direction to the ballLocation in order to move it. The Thread.Sleep() at the end is simply a delay (in milliseconds) so that you can see the ball move; otherwise it would move quickly. Try changing the value of 100 and use something else (e.g. 1000, which means 1 second) to see what happens.

Press F5 to see the ball move:


You will get an exception once the ball moves off the edge. Add the following to fix this and make the ball change direction when it hits an edge (note || means "OR"):

                if (ballLocation.X == 0 || ballLocation.X == 79)
                    direction.X = -direction.X;
                if (ballLocation.Y == 0 || ballLocation.Y == 24)
                    direction.Y = -direction.Y;

The infinite loop allows the ball to move on its own without user intervention - just as we wanted with Snake. However, there is a problem: we cannot accept any user input like this. In fact, you can only exit by actually closing the window. If you try to add a

Console.ReadKey(true);

at the end of the while loop, we're back to square one: the user must press a key for anything to happen. Clearly, in order to accept input, we need the program to do two things at the same time: let the ball move, and handle user input. Fortunately, such godlike powers are not unique to Chuck Norris and Multiple Man.

A program (or process to be more precise) can do several things at the same time. It can be composed of multiple threads which run at the same time but do different things. This area of programming is called multithreading. Let's see how we can exploit this to allow user input while the ball is moving on its own.

First, move the while loop and the vectors to a new method outside of Main():

        public static void Move()
        {
            Vector ballLocation = new Vector(40, 12);
            Vector direction = new Vector(-1, -1);
           
            while (true)
            {
                Console.Clear();
                Console.SetCursorPosition(ballLocation.X, ballLocation.Y);
                Console.Write((char) 4);
               
                ballLocation.X += direction.X;
                ballLocation.Y += direction.Y;
                Thread.Sleep(100);

                if (ballLocation.X == 0 || ballLocation.X == 79)
                    direction.X = -direction.X;
                if (ballLocation.Y == 0 || ballLocation.Y == 24)
                    direction.Y = -direction.Y;
            }
        }

In what remains of the Main() method, add the following code:

            Thread thread = new Thread(Move);
            thread.IsBackground = true;
            thread.Start();
           
            Console.ReadKey(true);

When you press F5 and run the program, you will now end up with two threads:


The new thread is created in the first line of code above. A thread executes the code in a particular method, so we supply the name of the Move() method (without brackets) as a parameter.

In the second line, we set thread.IsBackground = true. A process (running instance of a program) runs as long as there is a foreground thread (such as the main thread) running. Since our new thread is designated as a background thread, the process will terminate once the main thread has exited.

The rest of the Main() method then starts the secondary thread and waits for a keypress. When the keypress is received, Main() ends, and with it the process. If we didn't set the secondary thread as a background thread, the process would keep on running anyway. Try that out. :)

Fantastic. :) In this article, we learned how to use a simple thread in order to allow a program to do two things at the same time. We used this to allow a game to run, while at the same time waiting for user input.

Stay tuned for more! :)