Tutorial 02 IND Surface

From IndieLib
Jump to: navigation, search

The previous tutorial was a bit boring. So let's start with something visual that will be more much interesting!


Download the tutorials

Download the IndieLib SDK in order to have all the tutorial files with the sources for vc2008, and all the example tutorials compiled, so you can try them directly

Note: This tutorial uses an sprite created by the talented 2d artist Derek Yu from his pixel art tutorial. If you like gamming don't forget to try his latest game: Aquaria.


In this tutorial you will learn some of the most useful things of IndieLib. After reading this tutorial you will be able to draw sprites and backgrounds. You will also know how to change their attributes easily using entity objects: translation, rotation, scaling, alpha blending, aliasing, tint, fades, etc. The classes covered in this tutorial are:


IND_Surface and IND_SurfaceManager

With IND_Surface objects you can make sprites, backgrounds, scrolls, etc. IND_SurfaceManager it's just a manager that stores these type of objects.

A really beautiful feature of an IND_Surface object is that it can stores images of any size, they don't need to be power of two images and you can create really BIG scrolls (like 10000x10000 pixels) without problems. IndieLib will take care of everything internally cutting your images in blocks, and the good news is that all the blocks outside the viewport will be discarded (also when your camera or sprites will be rotated or scaled).

A IND_Surface object can be created from two sources:

When creating the surface, there are some important parameters you need to know. You can read about them in the Api Reference:

IND_Entity2d and IND_Entity2dManager

In order to render the IND_Surface objects (and also other graphical objects that you will learn about later like fonts) they have to be joint to a IND_Entity2d. An entity is an object that can have a graphical object associated to it. Using the methods of this class you will be able to change the attributes of the graphical object that it contains in a really easy way.

For example, in a game, a bullet can be a IND_Entity2d that has a IND_Surface associated to it. You can have as many bullets (IND_Entity2d objects) in the screen as you want, all of them sharing the same IND_Surface (the sprite). The cool thing is that you can change the attributes of each of these different IND_Entity2d objects. For example, you can change the size, rotation, color or transparency of the bullets. So, having only one sprite, you can have lot of different bullets in the screen, with different sizes, colors, positions, and in your system memory there will be only one instance of your graphical object.

IND_Entity2dManager it's just a manager that stores/deletes these type of objects.

You can take a look to all the attributes of the object that you can change seeing the methods of IND_Entity2d in the Api Reference.

Let's start with the source code

Take it easy, I know it's a lot of information. But once you see how easy to understand is the source code, you will see that all this staff is in fact really easy to manage and really powerful. So, let's go!

We will follow this tutorial reading from the "Main.cpp" file of the "a_02_IND_Surface" project of the SDK. So, go to the folder and open the project.

The first thing we are going to do is loading some images from the disk and creating the IND_Surface objects. So, double click in you "Main.cpp" file, read this lines:

// Loading Background
IND_Surface mSurfaceBack;
if (!mI->SurfaceManager->Add (&mSurfaceBack, "..\\resources\\blue_background.jpg", IND_OPAQUE, IND_32)) return 0;
// Loading sprite of a warrior
IND_Surface mSurfaceWarrior;
if (!mI->SurfaceManager->Add (&mSurfaceWarrior, "..\\resources\\derekyu_sprite.png", IND_ALPHA, IND_32, 255, 0, 255)) return 0;
// Loading sprite of a star
IND_Surface mSurfaceStar;
if (!mI->SurfaceManager->Add (&mSurfaceStar, "..\\resources\\star.png", IND_ALPHA, IND_32)) return 0;

We have just created three surfaces, and we have added them to the surface manager. All the surfaces are created using IND_32 quality, this is the bigger quality. The background is created using a IND_OPAQUE type, because it hasn't got transparent areas. The other two sprites, are created using IND_ALPHA, that it's used for having really nice sprites with antialiased edges. One important thing is that the the warrior sprite hasn't got a transparent background. Actually, it has a background with an RGB color equal to(255, 0, 255). So, in order to make this color transparent, we pass it as a parameter when creating the surface.

The following lines of code you have to notice are:

// ----- Set the surfaces into 2d entities -----
// Creating 2d entity for the background
IND_Entity2d mBack;				
mI->Entity2dManager->Add (&mBack);					// Entity adding
mBack.SetSurface (&mSurfaceBack);					// Set the surface into the entity
// Creating 2d entity for the warrior
IND_Entity2d mWarrior;					
mI->Entity2dManager->Add (&mWarrior);					// Entity adding
mWarrior.SetSurface (&mSurfaceWarrior);					// Set the surface into the entity
// Creating 2d entity for the star 1
IND_Entity2d mStar1;					
mI->Entity2dManager->Add (&mStar1);					// Entity adding
mStar1.SetSurface (&mSurfaceStar);					// Set the surface into the entity
// Creating 2d entity for the star 2 (big and a bit orange)
IND_Entity2d mStar2;					
mI->Entity2dManager->Add (&mStar2);					// Entity adding
mStar2.SetSurface (&mSurfaceStar);					// Set the surface into the entity
// Creating 2d entity for the star 3 
IND_Entity2d mStar3;					
mI->Entity2dManager->Add (&mStar3);					// Entity adding
mStar3.SetSurface (&mSurfaceStar);					// Set the surface into the entity

What we do here is to create some 2d entities and joint them with the IND_Surface objects. One entity will be the background, another one will be the warrior. And the last entities, will some stars that are sharing the same IND_Surface.

Now, lets change the attributes of these entities:

// ----- Changing the attributes of the 2d entities -----
// Warrior
mWarrior.SetPosition (400, 170, 0);					// Set the position of the entity
// Original Star without chaning it's attributes
mStar1.SetPosition (100, 270, 0);					// Set the position of the entity
// We change the attributes of this entity in order 
// to create a big rotated semitransparent star with 
// an orange tint
mStar2.SetPosition (280, 200, 0);					// Set the position of the entity
mStar2.SetScale	(2, 2);							// Set the scale of the entity
mStar2.SetTint	(240, 160, 230);					// Set tint to color RGB = (240, 160, 230)
mStar2.SetTransparency (200);						// Level of transparency 200 (255 will be opaque)
mStar2.SetAngleXYZ	(0, 0, 45);					// Rotation in Z angle = 45º
// A bigger star than the original, faded to pink. We only draw a region of 50x50 pixels
mStar3.SetHotSpot (0.5f, 0.5f);						// We change the reference point of the entity
mStar3.SetPosition (400, 470, 0);					// Set the position of the entity
mStar3.SetScale	(1.5f, 1.5f);						// Set the scale of the entity
mStar3.SetFade	(230, 0, 230, 128);					// Set fade to pink color, the amout of fade is 128 (255 will be complety pink)
mStar3.SetRegion (20, 20, 50, 50);					// Region we want to draw

This is what I call easy coding, isn't it? Here we set all the attributes of our entities. We don't change anything of the background entity because it's position is (0, 0) by default. From the warrior sprite and the star, we change only the position using SetPosition(). You can chose which surfaces will render on top off others using the third parameter "z" of SetPosition(): the entity which higher "z" will render on top.

There are some entities that are sharing the IND_Surface of the star sprite. The first one only suffers a translation. We scale the second one to the double of it's original size using SetScale() method. Later, we apply a tinting to a given color. We also change the transparency level to 200 using SetTransparency() (255 will be complety opaque). Finally we change the Z angle to 45º using SetAngleXYZ() (try to rotate it in "x" or "y" angles to have a funny "paper" effect).

With the final star, we make a smaller scaling than the previous one. We also set a fade to given color (pink) of medium intensity (0 will fade the entity completly to pink and 255 will keep the entity equal). SetInk() and SetFade() methods achives different results. With SetFade() you can change all the pixels of your sprite completly to the given color. With SetInk() the effect it's like if we were seeing the sprite trought a colored glass. The SetHotSpot() method allows you to choose the reference point from the transformations will be applied to the entity. By default the Hot Spot is (0, 0), this is the upper-left corner of the entity. A Hot Spot of (1, 1) will change the reference point to the lower-right corner. So the Hot Spot we use in the tutorial (0.5f, 0.5f) will be the very center of the 2d entity. Finally, using SetRegion(), we don't blit the whole sprite but only a region that starts in (20, 20) (from the upper-left corner of the sprite) and has an area of 50x50 pixels.

The rest of the source code is the main loop that we already saw in previous tutorials.

So, what you can do now it trying to create your own sprites, joinning them to entities and changing their attributes. Just imagine a huge world, plenty of different surfaces, each one a bit different just changing it's attributes (rotation, color, scale, etc)... something like in Aquaria game? Wow!

Check IND_Entity2d methods in the Api Reference to see other attributes you can change, the differences between SetFade() and SetInk(), etc.

You are ready for the next tutorial.

Template:Category Tutorials

Personal tools