Gigi Labs

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

Saturday, March 29, 2014

SDL2: Displaying text with SDL_ttf

Hello again! :)

[Update 2015-11-14: This article is out of date. Check out the latest version at Gigi Labs.]

In this article, we're going to learn how we can write text in our window. To do this, we'll use the SDL_ttf library.

First, we need to set up a project to work with SDL2. To do this, follow the instructions in my earlier article, "SDL2: Setting up SDL2 in Visual Studio (2013 or any other)".

Next, we need to actually download and use the SDL_ttf library. This is very similar to what we did with SDL_image in "SDL2: Loading Images with SDL_image". First, download the Visual C++ Development Libraries from the SDL_ttf 2.0 homepage:


From the archive you just downloaded, you need to do the same as in "SDL2: Loading Images with SDL_image" to:

  1. Copy SDL_ttf.h to the include folder where your other SDL2 files reside.
  2. Copy SDL2_ttf.lib to the lib\x86 folder where your other SDL2 files reside.
  3. After compiling your project (as it is, without using SDL_ttf just yet), copy the DLL files from the lib\x86 folder, as well as the regular SDL2.dll, to the Debug folder where your project's executable is created.

Then, in your project's properties, go to Linker -> Input and add the following: SDL2_ttf.lib in the Additional Dependencies field. This field should now contain the following:

SDL2.lib; SDL2main.lib; SDL2_ttf.lib

Good. Now, let's start with the following code which is a modified version of the code from about halfway through "SDL2: Displaying an Image in the Window":

#include <SDL.h>

int main(int argc, char ** argv)
{
 bool quit = false;
 SDL_Event event;

 SDL_Init(SDL_INIT_VIDEO);

 SDL_Window * window = SDL_CreateWindow("SDL_ttf in SDL2",
  SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640,
  480, 0);
 SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);

 while (!quit)
 {
  SDL_WaitEvent(&event);

  switch (event.type)
  {
  case SDL_QUIT:
   quit = true;
   break;
  }
 }

 SDL_DestroyRenderer(renderer);
 SDL_DestroyWindow(window);
 SDL_Quit();

 return 0;
}

The first thing we need to do in order to use SDL_ttf is include the relevant header file:

#include <SDL_ttf.h>

Then, we initialise the SDL_ttf library right after we call SDL_Init():

 TTF_Init();

...and we clean it up just before we call SDL_Quit():

 TTF_Quit();

Right after we initialise our renderer, we can now load a font into memory:

 TTF_Font * font = TTF_OpenFont("arial.ttf", 25);

TTF_OpenFont() takes two parameters. The first is the path to the TrueType Font (TTF) that it needs to load. The second is the font size (in points, not pixels). In this case we're loading Arial with a size of 25.

A font is a resource like any other, so we need to free the resources it uses near the end:

 TTF_CloseFont(font);

We can now render some text to an SDL_Surface using TTF_RenderText_Solid(). which takes the font we just created, a string to render, and an SDL_Color which we are passing in as white in this case:

 SDL_Color color = { 255, 255, 255 };
 SDL_Surface * surface = TTF_RenderText_Solid(font,
  "Welcome to Programmer's Ranch", color);

We can then create a texture from this surface as we did in "SDL2: Displaying an Image in the Window":

 SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,
  surface);

And yet again, we should not forget to release the resources we just allocated near the end, so let's do that right away:

 SDL_DestroyTexture(texture);
 SDL_FreeSurface(surface);

Now all we need is to actually render the texture. We've done this before; just add the following just before the end of your while loop:

  SDL_RenderCopy(renderer, texture, NULL, NULL);
  SDL_RenderPresent(renderer);

Okay, now before we actually run this program, we need to put our Arial TTF font somewhere where our program can find it. Go to C:\Windows\Fonts, and fron there copy the Arial font into the Debug folder where your executable is compiled. This will result in several TTF files, although we're only going to use arial.ttf.

Now if you've read my SDL_image tutorials before, you'll know that the program runs from a different directory when running from Visual Studio and when running directly from the executable - in fact if you run the program now from Visual Studio, it will crash; but if you run the executable directly it will work fine. Rather than replicating our TTF file across folders to satisfy both scenarios, here's a little trick to make it work without further ado.

Go into your project properties, and then under Configuration Properties -> Debugging, there's a field called Working Directory. Change this from $(ProjectDir) (the default setting) to $(SolutionDir)$(Configuration)\ :


Great, now let's admire the fruit of our work:


Nooooooooooooooo! This isn't quite what we were expecting, right? This is happening because the texture is being stretched to fill the contents of the window. The solution is to supply the dimensions occupied by the text in the dstrect parameter of SDL_RenderCopy() (as we did in "SDL2: Displaying an Image in the Window"). But how can we know these dimensions?

If you check out Will Usher's SDL_ttf tutorial, you'll realise that a function called SDL_QueryTexture() can give you exactly this information (and more). So before our while loop, let's add the following code:

 int texW = 0;
 int texH = 0;
 SDL_QueryTexture(texture, NULL, NULL, &texW, &texH);
 SDL_Rect dstrect = { 0, 0, texW, texH };

Finally, we can pass dstrect in our call to SDL_RenderCopy():

  SDL_RenderCopy(renderer, texture, NULL, &dstrect);

Let's run the program now:


Much better! :)

In this article, we learned how to use the SDL_ttf to render text using TTF fonts in SDL2. Using the SDL_ttf library in a project was just the same as with SDL_image. To actually use fonts, we first rendered text to a surface, then passed it to a texture, and finally to the GPU. We used SDL_QueryTexture() to obtain the dimensions of the texture, so that we could render the text in exactly as much space as it needed. We also learned how we can set up our project to use the same path regardless of whether we're running from Visual Studio or directly from the executable.

Below is the full code for this article. Come back again for more! :)

#include <SDL.h>
#include <SDL_ttf.h>

int main(int argc, char ** argv)
{
 bool quit = false;
 SDL_Event event;

 SDL_Init(SDL_INIT_VIDEO);
 TTF_Init();

 SDL_Window * window = SDL_CreateWindow("SDL_ttf in SDL2",
  SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640,
  480, 0);
 SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);

 TTF_Font * font = TTF_OpenFont("arial.ttf", 25);
 const char * error = TTF_GetError();
 SDL_Color color = { 255, 255, 255 };
 SDL_Surface * surface = TTF_RenderText_Solid(font,
  "Welcome to Programmer's Ranch", color);
 SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,
  surface);

 int texW = 0;
 int texH = 0;
 SDL_QueryTexture(texture, NULL, NULL, &texW, &texH);
 SDL_Rect dstrect = { 0, 0, texW, texH };

 while (!quit)
 {
  SDL_WaitEvent(&event);

  switch (event.type)
  {
  case SDL_QUIT:
   quit = true;
   break;
  }

  SDL_RenderCopy(renderer, texture, NULL, &dstrect);
  SDL_RenderPresent(renderer);
 }

 SDL_DestroyTexture(texture);
 SDL_FreeSurface(surface);
 TTF_CloseFont(font);

 SDL_DestroyRenderer(renderer);
 SDL_DestroyWindow(window);
 TTF_Quit();
 SDL_Quit();

 return 0;
}

Thursday, February 13, 2014

SDL2: Pixel Drawing

Greetings! :)

[Update 2015-11-14: This article is out of date. Check out the latest version at Gigi Labs.]

In yesterday's article, "SDL2: Keyboard and Mouse Movement (Events)", we saw how we could handle keyboard and mouse events to allow the user to interact with whatever we are displaying on the screen. In today's article, we'll learn how to draw individual pixels onto our window, and we'll use mouse events to create a drawing program similar to a limited version of Microsoft Paint.

You'll first want to create a project in Visual Studio and set it up for SDL2 (see "SDL2: Setting up SDL2 in Visual Studio (2013 or any other)"). We'll then need a bit of code to start off with, so let's take the code from "SDL2: Empty Window" and adapt it a little bit:

#include <SDL.h>

int main(int argc, char ** argv)
{
    bool quit = false;
    SDL_Event event;

    SDL_Init(SDL_INIT_VIDEO);

    SDL_Window * window = SDL_CreateWindow("SDL2 Pixel Drawing",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);

    while (!quit)
    {
        SDL_WaitEvent(&event);

        switch (event.type)
        {
        case SDL_QUIT:
            quit = true;
            break;
        }
    }

    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

As always, don't forget to put SDL2.dll in the same folder as your executable before running the program.

Since we're going to draw pixels directly rather load an image, our course of action in this article is going to be a little different from past articles. First, we need a renderer, so we use SDL_CreateRenderer() as we have been doing all along:

    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);

But then, rather than creating a texture from a surface, we're now going to create one from scratch using SDL_CreateTexture():

    SDL_Texture * texture = SDL_CreateTexture(renderer,
        SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, 640, 480);

We pass in several parameters. The first one is the renderer, and the last two are the width and height of the texture.

The second parameter, which we have set to SDL_PIXELFORMAT_ARGB8888, is the pixel format. There are many possible formats (see SDL_CreateTexture() documentation), but in this case we're saying that each pixel a 32-bit value, where there are 8 bits for alpha (opacity/transparency), 8 bits for red, 8 bits for green and 8 bits for blue. These four items are collectively known as channels (e.g. the alpha channel), so each channel consists of one byte and it can range between 0 and 255. The arrangement below thus represents a single pixel:

Alpha Red Green Blue
8 bits 8 bits 8 bits 8 bits

The SDL_TEXTUREACCESS_STATIC defines a method of accessing the texture. Since we're storing our pixels in CPU memory and then copying them over to the GPU, static access is suitable. On the other hand, streaming access is used to allocate pixels in a back buffer in video memory, and that's suitable for more complex scenarios.

Finally, we initialise a set of pixels that we'll be copying onto the window. When we draw stuff, we'll modify these pixels, and then they'll be copied onto the window to reflect the update.

    Uint32 * pixels = new Uint32[640 * 480];

We'll need to clean up all the stuff we just allocated, so add the following just before the other cleanup calls at the end of the code:

    delete[] pixels;
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);

At the beginning of the while loop, we may now add the following call:

        SDL_UpdateTexture(texture, NULL, pixels, 640 * sizeof(Uint32));

In this code, we are using SDL_UpdateTexture() to copy our pixels onto the window. We pass it our texture, a region of the texture to update (in our case NULL means to update the entire texture), our array of pixels, and the size in bytes of a single row of pixels (called the pitch). In our case, our window has a width of 640 pixels. Therefore a single row consists of 640 4-byte pixels, hence the multiplication.

At the end of our while loop, we may now render our texture as we have done in previous articles:

        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, texture, NULL, NULL);
        SDL_RenderPresent(renderer);

Great. So far, we have... uh... this:


Let's clear the background to white, so that we can draw black pixels over it. We could do that using SDL_SetRenderDrawColor() as we did in yesterday's article, "SDL2: Keyboard and Mouse Movement (Events)". But since we can now manipulate pixels directly, let's try something. First, add this at the top:

#include <iostream>

Now, we can use the standard function memset() to overwrite our pixels. Add this right after the declaration of pixels:

memset(pixels, 255, 640 * 480 * sizeof(Uint32));

Good, it's white now:


Now, let's add some code to draw black pixels when the mouse is clicked. First, add the following flag at the beginning of main():

    bool leftMouseButtonDown = false;

Then, add this inside the switch statement:

        case SDL_MOUSEBUTTONUP:
            if (event.button.button == SDL_BUTTON_LEFT)
                leftMouseButtonDown = false;
            break;
        case SDL_MOUSEBUTTONDOWN:
            if (event.button.button == SDL_BUTTON_LEFT)
                leftMouseButtonDown = true;
        case SDL_MOUSEMOTION:
            if (leftMouseButtonDown)
            {
                int mouseX = event.motion.x;
                int mouseY = event.motion.y;
                pixels[mouseY * 640 + mouseX] = 0;
            }
            break;

Right, so we're keeping track of whether the left mouse button is pressed. When it's pressed (SDL_MOUSEBUTTONDOWN), leftMouseButtonDown is set to true, and when it's released (SDL_MOUSEBUTTONUP), leftMouseButtonDown is set to false.

If the mouse is moving (SDL_MOUSEMOTION) and the left mouse button is currently down, then the pixel at its location is set to black (or zero, which is the same thing). Note that I intentionally left out a break statement at the end of the SDL_MOUSEBUTTONDOWN case, so that the drawing code in SDL_MOUSEMOTION is executed along with its own.

So now we can draw our hearts out:


Sweet! That was all we needed in order to draw pixels directly onto our window. Before I wrap up, here's the full code I'm using:

#include <iostream>
#include <SDL.h>

int main(int argc, char ** argv)
{
    bool leftMouseButtonDown = false;
    bool quit = false;
    SDL_Event event;

    SDL_Init(SDL_INIT_VIDEO);

    SDL_Window * window = SDL_CreateWindow("SDL2 Pixel Drawing",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);

    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Texture * texture = SDL_CreateTexture(renderer,
        SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, 640, 480);
    Uint32 * pixels = new Uint32[640 * 480];
    memset(pixels, 255, 640 * 480 * sizeof(Uint32));

    while (!quit)
    {
        SDL_UpdateTexture(texture, NULL, pixels, 640 * sizeof(Uint32));
        SDL_WaitEvent(&event);

        switch (event.type)
        {
        case SDL_MOUSEBUTTONUP:
            if (event.button.button == SDL_BUTTON_LEFT)
                leftMouseButtonDown = false;
            break;
        case SDL_MOUSEBUTTONDOWN:
            if (event.button.button == SDL_BUTTON_LEFT)
                leftMouseButtonDown = true;
        case SDL_MOUSEMOTION:
            if (leftMouseButtonDown)
            {
                int mouseX = event.motion.x;
                int mouseY = event.motion.y;
                pixels[mouseY * 640 + mouseX] = 0;
            }
            break;
        case SDL_QUIT:
            quit = true;
            break;
        }

        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, texture, NULL, NULL);
        SDL_RenderPresent(renderer);
    }

    delete[] pixels;
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

Fantastic! In this article, we learned how to draw pixels directly using SDL2. This involved first creating an SDL2 texture with a specified pixel format, then allocating an array to store those pixels, and finally copying the pixels from the array to the texture. We also used a variety of mouse events to allow the user to actually draw pixels onto the window with the mouse, which is like a simplified version of Microsoft Paint.

I hope you find this useful. Check back for more SDL2 and programming goodness! :)

Sunday, November 17, 2013

SDL2: Displaying an Image in the Window

Hello! :)

[Update 2015-11-14: This article is out of date. Check out the latestversion at Gigi Labs.]

In this article we're going to learn how to load a bitmap image from disk and display it in an SDL2 window. In order to follow along, you'll need to set up a project to work with SDL (see "SDL2: Setting up SDL2 in Visual Studio 2010"), and start off with the basic empty window code from SDL2: Empty Window, which is this:

    #include <SDL2/SDL.h>        
            
    int main(int argc, char ** argv)        
    {        
        bool quit = false;        
        SDL_Event event;        
            
        SDL_Init(SDL_INIT_VIDEO);        
            
        SDL_Window * screen = SDL_CreateWindow("My SDL Empty Window",
            SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480,
            0);        
            
        while (!quit)        
        {        
           SDL_WaitEvent(&event);        
            
           switch(event.type)        
           {        
           case SDL_QUIT:        
               quit = true;        
               break;        
           }        
        }        
            
        SDL_Quit();        
            
        return 0;        
    }

Build the application. Remember to place SDL2.dll into your bin\Debug folder. The empty window should appear if you run the application, and you should be able to close it by clicking on the "X" at the top-right corner.

Let's first change the window declaration a little bit (I changed the name of the variable and the window title):

    SDL_Window * window = SDL_CreateWindow("SDL2 Displaying Image",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);

After that, let's create an SDL_Renderer:

    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);

We use SDL_CreateRenderer() to get an instance of SDL_Renderer. This renderer represents the output device (usually your graphics card) to which your code will be drawing. In fact it's the final destination of our image, because we'll be following the steps below:


SDL_CreateRenderer() takes three parameters. The first is the window where we are drawing. The second allows us to select different rendering drivers; in our case we don't care, and we can set it to -1 and get the default one. The last parameter allows us to set SDL_RendererFlags to control how the rendering occurs. We can set it to zero to default to hardware rendering. If any of this sounds confusing, don't worry about it and just use SDL_CreateRender() as it is here.

We can now load the image from disk using the SDL_LoadBMP() function, which takes a path to a bitmap and loads it into an SDL_Surface:

    SDL_Surface * image = SDL_LoadBMP("image.bmp");

I'm using the following photo of the Grand Harbour in Valletta, Malta, which I took back in 2005, and which has a width of 320 pixels and a height of 240 pixels:


Place the image in your bin\Debug folder, where your executable is located.

Next, we need to create a texture.

    SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,
        image);

A texture is memory close to the graphics card (see image below), and we use SDL_CreateTextureFromSurface() to directly map our surface (which contains the image we loaded) to a texture.


Now that we have a texture, let's display it in the window. At the end of the while loop, just after the switch statement, add the following:

        SDL_RenderCopy(renderer, texture, NULL, NULL);
        SDL_RenderPresent(renderer);

We use SDL_RenderCopy() to copy the texture to the output device. There are also a couple of other parameters that we're setting to NULL - more on these in a minute. Finally, SDL_RenderPresent() is what commits the texture to the video memory, displaying the image.

Before we run the program, we must always remember to clean up every resource that we initialise. In our case, that means adding the following just before the call to SDL_Quit():

    SDL_DestroyTexture(texture);  
    SDL_FreeSurface(image);  
    SDL_DestroyRenderer(renderer);  
    SDL_DestroyWindow(window);

If you now run the program from within Visual Studio, surprisingly enough, you get a blank window:


...whereas if you run the program directly from the executable in your solution's bin\Debug folder (where image.bmp is also located), it works:


We'd know more about what's going on if we had proper error handling in place. With every call to the SDL2 API, we should be checking the return values, and displaying an error if any of them fail. SDL_ShowSimpleMessageBox() is great for displaying simple error messages, while SDL_GetError() gives us the actual error text of the last thing that failed. Let's refactor our initialisation code to check for errors and display them:

    SDL_Window * window = SDL_CreateWindow("SDL2 Displaying Image",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
    if (window == NULL)
        SDL_ShowSimpleMessageBox(0, "Window init error", SDL_GetError(),
            window);
    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
    if (renderer == NULL)
        SDL_ShowSimpleMessageBox(0, "Renderer init error",
            SDL_GetError(), window);
    SDL_Surface * image = SDL_LoadBMP("image.bmp");
    if (image == NULL)
        SDL_ShowSimpleMessageBox(0, "Image init error", SDL_GetError(),
            window);
    SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,
        image);
    if (texture == NULL)
        SDL_ShowSimpleMessageBox(0, "Texture init error",
            SDL_GetError(), window);

When we run this code, the first error we get is the following:


That's it - the program can't find the image. Remember how it worked when running from the executable, but not from Visual Studio? That's because Visual Studio starts at a different directory. As a quick workaround, just copy image.bmp into your source folder (where main.cpp is located). Hit F5, and it now works:


Fantastic! The image is right there in the window! But... can you see what happened? The image, which has dimensions 320x240, has been stretched to fill the window, which has dimensions 640x480. That's sometimes convenient, because we get scaling for free. However, it makes photos look messy. Let's change our call to SDL_RenderCopy() to fix this:

        SDL_Rect dstrect = { 5, 5, 320, 240 };
        SDL_RenderCopy(renderer, texture, NULL, &dstrect);

Remember those two parameters at the end of SDL_RenderCopy() that we were setting to NULL? If you look at the documentation for SDL_RenderCopy(), you'll see that the last one defines a destination region (which part of the texture will the image be copied to). If it's set to NULL, then the image is stretched to fill the texture - which is what happened above.

By setting dstrect (the last parameter), we can render to only a portion of the window. We set it to an SDL_Rect, with x and y set to 5, and width and height corresponding to the dimensions of the image. When we run the program, we get this:


Excellent! :) In this article we looked at how to create renderers, surfaces and textures. We used these to load bitmaps and display them on the screen. A glimpse into error handling allowed us to troubleshoot issues with loading the image from Visual Studio. Finally, we saw the difference between copying the image to a region of the window, and making it fill the entire window.

I hope you enjoyed this. Come back for more! :)

Monday, May 27, 2013

Unity3D: Space Invaders (Part 1 - Navigation and Materials)

Hello, fellow game developers! :)

In today's article we're going to start working on a clone of the arcade classic, Space Invaders. To prevent Tomohiro Nishikado from suing my ass off, we'll instead call this Ranch Invaders. Through this game we'll learn a number of important concepts including prefabs, linear interpolation, materials, and more. Since we can't learn all this in a single article, this will be spread out over several articles.

If you've been following my previous Unity3D articles, the last project you used will automatically open when you launch Unity. Create a new project from File menu -> New Project... and find a place to put it:


You don't need to import any packages. Once Unity relaunches with your new project, press Ctrl+S to save your .unity (scene file) somewhere.

Great. Now, we'll begin working on the alien, and we'll use it to learn some basics about working with Unity. For the time being, we'll use a simple cube as the alien, so go to GameObject menu -> Create Other -> Cube, just the same as we did in the previous two articles. You should now have a cube sitting in your game world (left portion of the screen):


You can see from the Inspector that the cube is at (0, 0, 0). You will also notice three arrows (red, green and blue) shown on the cube in the game world. You can click and drag one of the arrows to move the cube, and you will see the Position values in the Inspector change. You can also drag one of the squares between the arrows in order to move the cube in two directions (e.g. X and Y) at once.

In the Hierarchy section, there's also an object called Main Camera apart from the Cube you placed. If you select it, you'll see a little preview window:


If you press the Play button at the top of the Unity interface, you'll see the same thing. The main camera represents what the player is seeing.

Select the Cube again. Using the mouse, you can navigate the scene in order to work with the objects in it. If you press Alt and click and drag the left mouse button, you can rotate the view around the currently selected object (the Cube in our case). A middle-click (click the mouse's scroll wheel) and drag pans (moves sideways) the view relative to the selected object. By scrolling the mouse wheel, you can zoom the view towards or away from the camera. Finally, you can use the gizmo at the top-right of the world view to view the scene from particular directions (e.g. from the top).

You can manipulate the object itself by moving, rotating, or scaling it. We have already seen how to move an object (by using the arrows). You can use the W, E and R keys (or the buttons at the top-left of the Unity interface, just below the File menu) to switch between movement, rotation and scaling mode. When you do this, the arrows will change:


The screenshot above shows how the arrows change when you are scaling. You can drag one of the coloured boxes to scale in one direction, or the small box at the centre in order to scale uniformly (in all directions). Rotation has yet another thingy you can drag in order to rotate in different directions.

Once you're comfortable with navigating the scene using these controls, it's time to customise our Alien (Cube) a little bit.

With the Cube selected in the Hierarchy panel, press F2 and rename it to Alien.

Next, right click on the Assets panel and select Create -> Material. Name it Alien as well. Click on the white box next to "Main Color" and select whatever colour you want your alien to be:


Drag the material from the Assets panel onto the cube in the world view:


Other than using a solid colour, you can also select an image that you think would make it look more like an alien. To do this, right click in the Assets panel, select Import New Asset... and find the image you want on your filesystem. Once the image appears in your Assets panel, you just need to select the Alien's material and drag the image into the area that says "None (Texture)":


That's about as alien-like as it can get. This technique of wrapping an image around a 3D object is called texturing, and the image is called a texture.

Great! :) We covered some basic navigation controls in this article, as well as how to apply a material to a 3D object. The material may be either a solid colour or an image (texture).

In the next article, we will learn about linear interpolation, and use it to script the alien's sideways-moving behaviour. Until next time! :)