Viser innlegg med etiketten Tutorial. Vis alle innlegg
Viser innlegg med etiketten Tutorial. Vis alle innlegg

mandag 14. juli 2014

[ SDL2 - Part 10 ] Text rendering.

Rendering text


In the previous parts, we've look at how to render rectangles and images, both with and without transparency. Now it's time to look at how we can render text.


Rendering text is tricky. You'll want to be able to render any font, in any size and preferably every possible character. Luckily, with the SDL ttf library, this is easy.

SDL2_ttf


SDL2_ttf, just like SDL2_image, is an additional library for SDL2. It can use just about every font, and you can set the size too!

What's TTF?


TTF, or TrueType Fonts is a type of fonts developed by Apple and Microsoft in the late 90's. True Type Fonts offers a high degree of control on how the font looks. The internals of TTF fonts and how they work isn't important here. The important part is that they're easy to use, will look really nice ( even scaled up. ) And they're also widely used, so finding fonts shouldn't be a problem.

SDL2 TTF?


As with SDL2_image, SDL2_ttf is a addon for SDL2 that deals with rendering text and makes it very easy. It is based on libfreetype, a library for writing text using TTF fonts. However, it's not very practical to use. SDL2_TTF makes using it a lot easier. But if you do want to use it yourself, you can take a look at their tutorial.

Setting up SDL2_TTF


Setting up SDL2 requires a tiny bit more work than SDL2_image, but don't be scared, it's still very easy. First we need to install the ttf library.

Installation


Installing SDL2_ttf is done exactly like SDL2_image. Just replace SDL2_image with SDL2_ttf

Linux


For Linux you can use need to install -lSDL2_ttf or -libSDL2_ttf or -SDL2_ttf ( the actual name might be different in different distributions. )

The linker flag is -lSDL2_ttf

The process is more or less identical to that of setting up SDL2_image.

If you can't find SDL2_ttf in any repositories and it's not installed by default, you might have to compile it yourself. For more information, see my blog post about setting up SDL2.

Windows


Similar to setting up SDL2 base.

The difference is that you have to download the development files for SDL2_ttf

And similarly add SDL2_ttf.lib to library includes and add SDL2_ttf.lib to the library flags ( where you previously added SDL2_image.lb )

And with that, it should work.

Mac


See the first part of my tutorial. Just install SDL2_ttf instead of SDL2

Initialization


Unlike SDL2_image does need to be initialized. Why? Because libfreetype, the library that SDL2_ttf builds upon needs to be initlaized, so naturally SDL_ttf needs to be initalized too.

Initializing SDL2_ttf requires a single function :
int TTF_Init()
Just like SDL_Init(Uint32 flags) this function returns -1 on error.

And just like with SDL_Init(Uint32 flags), we should print an error if the function fails. SDL2_TTF has its own function for printing errors :

char *TTF_GetError()
This means our routine for initializing SDL2_ttf will be the same as SDL2, just with the two functions above ( see full code for details. )

Loading fonts


This is the central structure of SDL2_ttf. It holds the font itself, the size and some other style information ( I'll go into this in the next part ). So, in order for us to use an TTF_Font we need to load it. This is done using a load function :
TTF_Font *TTF_OpenFont
(
    const char *file,
    int ptsize
)
So, the arguments are
  • const char *file - a pointer to the .ttf file
  • int ptsize - the size of the font
The function returns a NULL pointer of it can't find the file, or there is another error ( like SDL2_ttf isn't initialized. So this too should be handled by priting the error using TTF_GetError(), just like when initializing ttf

Cleaning up fonts


Just like we with SDL_Texture* and SDL_Surface*, we need to clean our fonts when done. This is just as easy for TTF_Fonts as with SDL_Texture* and SDL_Surface*. We simply call a function that does it for us :
TTF_CloseFont
(
   TTF_Font* font
);

Rendering text


There are three functions you can use to render text, depending on what you want. Let's start with the first one :

TTF_RenderText_Solid


This function is used for quick and simple rendering of a text, using a specific font and a font color. The background of this is transparent. Here's the signature:
SDL_Surface *TTF_RenderText_Solid
(
    TTF_Font *font,
    const char *text,
    SDL_Color fg
)
The arguments are :
  •  TTF_Font *font - the font to use
  • const char *text - the text to render
  • SDL_Color fg -  the color to use for the text

The function returns the finished SDL_Surface*, or NULL if something went wrong ( like supplying a NULL pointer for font )

The result will look something like this :


TTF_RenderText_Blended


This function has the exact same signature as TTF_RenderText_Solid, so I'll just show it without explaining it parameter by parameter :
SDL_Surface *TTF_RenderText_Blended
(
    TTF_Font *font,
    const char *text,
    SDL_Color fg
)
So what's the difference between TTF_RenderText_Solid and TTF_RenderText_Blended? The difference is that TTF_RenderText_Solid is very quick, but TTF_RenderText_Blended produces a better result. In our game, we won't be updating our text surfaces all that often, and there's not a lot of them either, so TTF_RenderText_Blended is a good choice.

Here's what TTF_RenderText_Blended looks like :

And here's a comparison between TTF_RenderText_Solid and TTF_RenderText_Blended :

The difference is not huge, but in the actual game it will be more clear. And the difference might also vary from font to font.

The third version is a tiny bit different :

TTF_RenderText_Shaded


This function will render the text, but with a specified background color.
SDL_Surface *TTF_RenderText_Solid
(
    TTF_Font *font,
    const char *text,
    SDL_Color fg,
    SDL_Color bg
)
The arguments are :
  •  TTF_Font *font - the font to use
  • const char *text - the text to render
  • SDL_Color fg -  the color to use for the text
  • SDL_Color bg -  the color to use for the background

So it's almost the same as the other two, just with a third argument for the background color. The return value is also the same as the other two.

The result will look something like this :

An example


Below is a simple example that should run and compile out of the box. For compilation details, look below.



Running it!


Running it is just as simple as with SDL2_image. So that means compilation on Windows is already set up when you installed TTF

Linux / Mac


If you are compiling using the compiler, you have to add -lSDL2_ttf to the compile string like so :
clang++ main.cpp -std=c++11 -o Game -lSDL2 -lSDL2_image -lSDL2_ttf

If you want to run it, you simply do
./Game

Updated game code


I have done a bit of cleaning up in the game code. I've added a new Texture class for text, cleaned up include, removed ( and added ) comments, improve delta calculation++ Everything should be explained in comments, but, of course, if you have any questions of any kinds, just comment or contact me, I'll be happy to help.

You can find the code here.


For a full list of my tutorials / posts, click here.

Feel free to comment if you have anything to say, any suggestion or any questions. I always appreciate getting comments.


lørdag 5. juli 2014

[ SDL2 - Part 9 ] No more delays!

Getting rid of SDL_Delay


Up until now, we've been regulating movement by just setting a delay of 16 milliseconds at the end of each frame like so : SDL_Delay( 16 )


This is bad because sometimes a frame takes a bit longer. In our code, there is so little going on, so the frames usually take less than on MS. So we've added a delay of 16 ms. But things may happen, and suddenly a frame takes 5 ms. What happens then? Well, your animations will jump. And if this happen regularly, your animation will be choppy. We don't want choppy animations, we want smooth animations.How do we achieve this?

Method 1 - our current solution


We've set an aim for 60 frames per second. Since there is 1000 millisconds ( ms ) in a second, each frame should take 1000 ms / 60 frames = 16 ms.

Since our code is very light, we've just assumed that each frame takes less than 1 ms, so we've added a delay.

Problem : what if one or more frames uses more than 1 ms to run? Our animations will get choppy and we don't want that

Method 2 - using delta


Another, better way we could limit framrate is to calculate delta time and use that to set the delay, of. Delta time is the time between each frame ( or update. ) If a frame takes 3 ms, delta will be 3 ms. In method 1 we had a 16 ms delay and assumed the frame took 0 ms to run. But if the frame took 3 ms, we "loose" 3 ms of the delay time and end up with a delay tie of 16ms - 3ms = 13 ms.

This is a valid solution, and your game will run relatively smoothly in 60 fps.

Method 3 - using delta, no delay


Method 1 and 2 has worked by limiting frame rate. But why limit it? We can just skip the delay altogether and just use the delta time to adjust animation. Most modern games works this way. Since we adjust movement with delta time, it doesn't matter if we run in 60 fps or 6000 fps. For smooth animation, this method is superior to the ones above. Waiting 16 ms between frame can make objects jump a tiny bit. Better to eliminate this delay at all.

It's also very simple, just multiply the movement with the delta time.

Implementation


Implementing frame independent movement is quite simple, but there are a few things you need to be aware of in order to get it right.

Delta time


Probably the most important point. In order to get animations right, the delta tie needs to be accurat. Very accurate, preferably with microsecond ( µs ), or nanoseconds ( ns )

There are various ways to do this.
  • The C way</li>
    • - Confusing ( functions takes a struct and fills it with time / date )
    • - Not always accurate
    • - Hard to use correctly
    • - Platform dependent ( no one way to do it in Linux and Winows ) 
    • + No library needed,
    • + Doesn't need C++11 support
  • Boost
    • - You'd need to download, and link with boost
    • - Adds and a dependency, just for time
    • + Cross-platform
    • + Doesn't need C++11 support
  • C++11
    • - Syntax can be hard to understnad
    • + Does everything you need easily
    • + Cross platform
    • + Well documented
Both boost and C++11 are good alternatives. In this tutorial, we'll cover the C++11 way. The main reason for this is that it means we don't have to install boost. And the C++11 way is well documented, though lacking of examples.

std::chrono


Chrono is the C++11 way for everything related to time and timing. It's quite large and complex, but I'll try to give a short explanation of how we get the delta tie using chrono. std::chrono::time_point is the basic C++11 time structure. It contains std::chrno::duration, which contains information about a point in time. More specific it contains a tick variable that contains the number of time units since 1.1.1970, and a std::ration which says what unit of time the ticks are in ( secnds, monutes, milliseconds, etc... )

This might be kinda confusing, but all you need to remember is that std::chrono::time_point represent a point in time. So let's implement our delta function. First of all, we're gonna make things a lot easier for ourselves by adding using namespace std::chrono;. This is not necessary, but it means we don't have to add std::chrono:: in front of everything.

So now we need to get the point in time, this can be done using high_resolution_clock::now(); which returns a std::chrono::time_point

time_point timeCurrent = high_resolution_clock::now();

This will be done at the beginning of our GetDelta() function. We also need a variable to store the previous point in time ( the last tie GetDelta() goy called. We'll set this at the end of our GetDelta() like this ( timePrev is just a time_point )

timePrev = timeCurrent;

Now that we have our two time_points, we can calculate the time between them ( the delta time. ) time_point supports arithmetic operations such as - and + so we can easily find the time difference between them by doing time_point timeDiff = ( timeCurrent - timePrev ).

auto timeDiff = timeCurrent - timePrev;

So now we have a third time_point that contains the difference between the two frames. This is essentially the delta time represented as a time_point. But there is anther problem : we have no idea what time unit the duration object uses. So to be certain we get the time as nanoseconds, we need to cast the duration inside the time_point to be using nanoseconds. To do this, we use a duration_cast<> we can simplify it a little to calculate timeDiff and cast it in the same line :

auto timeDiff = duration_cast< nanoseconds >( timeCurrent - timePrev );

To get the actual number of time unites, we use the count() member function :

double delta = duration_cast< nanoseconds >( timeDiff ).count();

And finally we have the delta. But since it's in nanoseconds, we need to convert it into seconds :
delta /= 1000000000;

There! It's a bit complicated with all the different variables types, but we now have a function for getting delta time. And it will work on any platform as long as it supports C++11, not extra libraries needed. Here is the finished function :


Using the delta time


Now that the worst part is over, it's time for some minor details on how to implement frame independent movement.

First of all, the animated objects needs to have speed. And for better precision, we use doubles. Let's make a simple struct for holding the speed. Our speed will have values between -1.0 and 1.0.
struct Speed
{
     double x;
     double y;
};
We also need an Update( double delta ) functions that's used to update the position of the object.

rect.x += speed.x * delta;
rect.y += speed.y * delta;

There's a few things wrong with this, though. First of all, delta values will be really small, and our speed is between-1.0, and 1.0 so the resulting movement will be really small. We can solve this by multiplying with a constant.

rect.x += speed.x * delta * 300;
rect.y += speed.y * delta * 300;

But there is a second issue here : both speed and delta are likely to do decimal numbers. So the result of the multiplication will almost always be a decimal number as well. But we just put it into an int and this means we'll loose the decimal precision. So if the result is 0.8, we'll end up adding 0 to x or y. And if the same things happen in the next frame, we've "lost" 1.6 worth of movement. A while pixel! It might seem like a small thing, but it would make the movement really choppy. So instead we introduce two new member variables to our Texture struct to hold the result of the multiplication. So here's our final Update function:

double x;
double y;

// .......

void Update( double delta )
{
     x += speed.x * delta * 100;
     y += speed.y * delta * 100;
  
     rect.x = x;
     rect.y = y;
}

Conclusion


That concludes the tutorial on delta timers. I've made a few updates, put things into different classes and other minor improvements. The code is too big to include in this blog post, but you can find a full zip of it here.

 I've added a new .cpp file, so you need to add that to the compilation string if you're using clang or gcc

clang++ main.cpp Texture.cpp -std=c++11 -lSDL2 -lSDL2_image -o Game

As always, feel free to post a comment or message me if you have a question.

fredag 20. juni 2014

[ SDL2 - Part 8 ] It's TIME for another update!

Introduction


In the last tutorial we learnt how to load and render png files with alpha layers. This time we're gonna dive into rotating textures. Or more presicely ; rendering them rotated.

Today e'll be making a simple, but working, analog clock.  This will show how to rotate textures in SDL2. We'll also improve how we represent textures

SDL_RenderCopyEx


Until now, we have been rendering using SDL_RencerCopy. But in order to rotate, we need a different function ;  int SDL_RenderCopyEx it takes a couple more arguments. I'll try to explain all of them.

SDL_RenderCopyEx
(
   SDL_Renderer* renderer,
   SDL_Texture* texture,
   const SDL_Rect* srcrect,
   const SDL_Rect* dstrect
   const double angle,
   const SDL_Point* center,
   const SDL_RendererFlip flip
)

  • renderer - the SDL_Renderer we always use for rendering
  • texture  - the SDL_Texture we want to render
  • srcrect  - which part of the SDL_Texture to render. null for everything.
  • dstrect  - where to render it. Used exactly like in SDL_RenderFillRect)
  • angle     - angle of rotation
  • center    - the center of rotation
  • flip      - flipping of texture ( vertical, horizontal, no flip )
Return value
  • 0 on success

As you can see, the first four parameters are identical to SDL_RenderCopy you can read more about them in part 6.

Texture flip


Texture flip is represented as an SDL_TextureFlip

It is simply an enum with the following three values :
  • SDL_FLIP_NONE              - don't flip at all
  • SDL_FLIP_HORIZONTAL   - flip horizontaly
  • SDL_FLIP_VERTICAL         - flip vertically

For now, we will just be using SDL_FLIP_NONE.

Center of rotation


The center of rotation is given as a position seen from the top-left of the texture ( remember; in SDL 0,0 is the top-left of a texture. ) So a center of 0,0 will mean you rotate it from the top-left corner.

Finding the center of rotation is usualy quite simple, it'll usually just be the center of the texture you are using. For a circle, like a spinning wheel, the center of rotation will simply be the center of the wheel. Or for a Tetris piece it will be the center of the retris piece. The center of a texture is easy to find. Since a center of any rectangle will be halfway along its x axis and halfway along its y axis, the position can be calculate as follows ;


// The rect of the texure.
// Assume it is filled out with pos(x, y) and size( w, h )
SDL_Rect textureRect;
SDL_Point center;

// Calculate center pos by setting
// ->x pos to half of witdh
// ->y pos to half of height
center.x = textureRect.w / 2;
center.y = textureRect.h / 2;

The type of center is one we haven't used before, SDL_Point. But an SDL_Point is simply just a struct with an x and y value.

In our case we are going to make a working analog wall clock. So we can't rotate it around the middle ( that would be a weird clock! ) What we need to do, is find the base of the hands.


Here is a picture of on our clock hands. The white hole in the middle is where we want the center of rotation to be. All three hands look very similar to this, all hands have a hole in the base, and all of them rotate around that point.

If you look closely at the green dots, you'll see that the distance to the hole from either of the sides and the bottom is all the same ( three green dots. ) The green dots span the entire width of the base. So to find the center x value, we simply take half of the width. Looking at the picture, you'll see that the distance from the bottom to the hole is the same as the distance from the sides subtract half of the width to find the y position of the hole.

So the code for finding the center of rotation will be something like this :


// Assume textureRect is filled out with pos and size
SDL_Rect textureRect;
SDL_Point textureCenter;

int halfWidth = textureRect.w / 2;
textureCenter.x = halfWidth;

// Center.y  = half of the width above texture bottom.
textureCenter.y = textureRect.h - halfWidth;

Putting things together


Previously we have worked with simply storing the SDL_Texture and SDL_Rect as separate objects in our main.cpp. But now we also need to store the center of rotation and the angle. So that's four variables for each texture. With so many variables, it's a good idea to split it into a separate struct :



We also need to change main to make the clock work



As you can see, there is very little code needed in main since a lot of it is moved into Texture.h


Conclusion


The full code can be downloaded here.


Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

For a full list of my tutorials / posts, click here.

lørdag 14. juni 2014

[ SDL 2 - Part 7 ] Using PNG files

Using PNG


In the previous post we learned how to load .bmp files. Which is not optimal. The .bmp format means the files grow large and there is no alpha layer ( no transparency. ) Which means you end up with ugly single-colored edges instead of transparency

Original with .bmp images


SDL2_image


Up until now, we've only been using the standard SDL2.0. But the standard SDL2.0 doesn't support loading of .png files. But fortunately, there is a second SDL library that does this. And since it's still SDL, it will work perfectly with or other SDL code!

Installing is almost exactly the same as installing SDL2 itself; you just follow the instructions in part 1 of my tutorial. But instead of installing SDL2, you install SDL2_image.

New version with png files.
Note: I apologize for vague and not very thorough descriptions in the below points. I will update them when I have access to Windows and Mac. I also apologize for the horrible background and sprites.

Linux


For Linux you can use need to install -lSDL2_image- or -libSDL2_image- ( the actual name might be different in different distributions. )

The linker flag is -lSDL2_image

The process is more or less identical to that of setting up SDL2 base. For more information, see my blog post about setting up SDL2.

Windows


Similar to setting up SDL2 base.

The difference is that you have to download the development files for SDL2_image

And similarly add SDL2_image.lib to library includes and add SDL2_image.lib to the library flags ( where you previusly added SDL2.lb )

And with that, it should work.

Mac


See the first part of my tutorial. Just install SDL2_image instead of SDL2

Again; I apologize for my poor description on this. I don't run Mac and have no experience with it. I hope my short descriptions is of any hope, though.

Loading PNGs using SDL2_image


In order to use SDL2_image, you need to add the header file, like so :

#include

The actual loading of .png files is just as easy as loading .bmp files. But since it uses an extension library, we have to use a different function :

SDL_Texture* IMG_LoadTexture
(
     SDL_Renderer* renderer,
     const char *file
);


This function will load a file and return it as a SDL_Texture*. This means we don't have to convert it, so we can just do:



Note that this function, unlike the one for loading bmps, needs a pointer to the SDL_Renderer this is because it returns an SDL_Texture SDL_Textures are hardware optimized, and SDL2 needs the SDL_RendererIMG_LoadTexture() can handle several types of images. And because I'm lazy and didn't change the .bmp files that don't need transparency.

Running it


Just like last time, I'm not gonna show the entire code as one long gist ( too much code, and there are images too. )

Here is a link to the code in .zip form

Linux / Max


If you are compiling using the compiler, you have to add -lSDL2_image to the compile string like so :
clang++ main.cpp -std=c++11 -o Game -lSDL2 -lSDL2_image

If you want to run it, you simply do
./Game

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

For a full list of my tutorials / posts, click here.

tirsdag 6. mai 2014

[ SDL2 - Part 6 ] Loading textures

Loading textures


In this tutorial you will learn how to load images ( just bmp for now, the next part wil cover .png ). First of all, a little info about the two new structs we'll be using

SDL_Surface


This is part of the old SDL ( < 2.0. ) It was used for just about everything related to rendering.

SDL_Surface is used for holding the raw texture data. Basially it says what the color for every pixels is. Sort of like this :
  • pixel( 0, 0 ) = 128, 64, 255, 255 ( 128 red, 64 green, 255 blue, 255 alpha )
  • pixel( 1, 0 ) = 255, 32, 128, 128 ( 255 red, 32 green, 128 blue, 128 alpha )
..etc

( This  might not be 100% true for all cases, but it's generally how SDL_Surface stores the pixels. )

The SDL_Surface structure also holds other data about the texture.
  • width/height ( these are read-only )
  • the pixel format, stores as an SDL_PixelFormat
  • clip_rec, a SDL_Rect used for bliting ( similar to rendering )
d
These values are useful to know about if you want to create your own SDL_Surfaces using code or want to use the old form of rendering ( bliting ). I do, however, not recommend learning about it. Bliting is less intuitive and it uses only software rendering. This basically means that the CPU will be doing the rendering, somthing CPUs are really bad at. We want optimized hardware rendering on the GPU. And that's where the second struct comes in.

SDL_Texture


Like SDL_Surface, SDL_Texture holds texture data. But unlike SDL_Surface, SDL_Texture holds an optimized, driver specific representation of the pixel data. This means rendering will be executed on the GPU, where it belongs. And THAT means it is really, really fast!

So what's the point of SDL_Textures?

Well, as I said, the pixel data in SDL_Texture is optimized. And what's more, it can be very different depending on your driver ( nVidia vs ATI. ) Basically this means that you can't use the pixel data for anything other than rendering. A second reason will come up when we dive into another new part of SDL, namely image loading.

Loading images


Loading a BMP image in SDL is very easy. It can be done using the following function
SDL_Surface* SDL_LoadBMP
(
    const char* file
)
Parameters
  • file - the file we want to load
Return value
  • SDL_Surface* - the loaded image as a SDL_Surface. null if failed. 

But we're not gonna use the SDL_Surface*, we want a SDL_Texture* instead. To get it, we need to use a second function :
SDL_Texture* SDL_CreateTextureFromSurface
(
   SDL_Renderer* renderer,
   SDL_Surface* surface
)
Parameters
  • renderer - our SDL_Renderer
  • surface - the surface we want to make a SDL_Texture from
Return value
  • SDL_Texture* - The resulting SDL_Texture. null if failed. 

Since we won't be using the SDL_Surface, we can delete it and free the memory :
void SDL_FreeSurface
(
   SDL_Surface* surface
)

Parameters
  • surface - the SDL_Surface to delete
Return value
  • none

Now that all of this is in place, we can wrap it all up in a nice little function :



Getting the images on screen



Now that we have loaded the textures, we need to render then on screen. That means no more SDL_RenderFillRect() and THAT means no more rectangles and squares. Finally! To render them, we just need a simple function :


int SDL_RenderCopy
(
   SDL_Renderer* renderer,
   SDL_Texture* texture,
   const SDL_Rect* srcrect,
   const SDL_Rect* dstrect
)


Parameters
  • renderer - the SDL_Renderer we always use for rendering
  • texture - the SDL_Texture we want to render
  • srcrect - which part of the SDL_Texture to render. null for everything.
  • dstrect - where to render it. Used exactly like in SDL_RenderFillRect)
Return value
  • 0 on success

Even though this function has a few parameters, it's really quite simple. We can use null for srcrect and the SDL_Rects we used for SDL_RenderFillRect() as dstrect. And then we can remove the SDL_SetRenderDrawColor and end up with a LOT shorter Render() function.



Putting it all together


I'm not gonna put the entire code on the blog anymore since this creates a whole wall of text to scroll through. And now there is added images too. But you can download the images and the source code here.



Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

For a full list of my tutorials / posts, click here.

tirsdag 29. april 2014

[ SDL2 - Part 5 ] Collision detection and our first game!

Collision detection


Collision detection is one of the key aspects of game programming. For all non-rectangular objects it gets harder and harder the more accurate you want it to be. But today we're gonna continue just using rectangles. This part describes a simple algorithm to check for intersections.


After we've created a functions that does rectangle-rectangle collision detections, we'll use all of what we've learned so far and make a simple game!

Rectangle - rectangle collisions


Instead of checking if two rectangles are inside or touching each other, we're gonna check for the opposite; if they are outside of each other. The algorithm to do so consists of two steps.

  1. Find the x coordinate of the left and right and the y coordinate for top and bottom.


    Say we have two rectangles, rect1, and rect2.
    SDL_Rect rect1;
    SDL_Rect rect2;
    Finding the x/y of left/right/top/bottom is very easy.
    int left1 = rect1.x;
    int right1 = rect1.x + rect2.w;
    int top1 = rect1.y;
    int bottom1 = rect1.y + rect2.h;
    The process is exactly the same for the second rect.

  2. Use the 8 edges to check if they are not colliding


    Take a look at the below drawing

    As you can see, the red rectangle is farther to the right than the blue one. But how do can we easily check that? Simply by checking if redLeft is further to the right than blueRight. If it is ( like it is in our case ) there is no collision. Then it's just a simple matter of repeating it for the other edges. So we end up with something like this :

    SDL_Rect rect1;
    SDL_Rect rect2;

    // Find edges of rect1
    int left1 = rect1.x;
    int right1 = rect1.x + rect1.w;
    int top1 = rect1.y;
    int bottom1 = rect1.y + rect1.h;

    // Find edges of rect2
    int left2 = rect2.x;
    int right2 = rect2.x + rect2.w;
    int top2 = rect2.y;
    int bottom2 = rect2.y + rect2.h;

    // Check edges
    if ( left1 > right2 )// Left 1 is right of right 2
        return false; // No collision

    if ( right1 < left2 ) // Right 1 is left of left 2
        return false; // No collision

    if ( top1 > bottom2 ) // Top 1 is below bottom 2
        return false; // No collision

    if ( bottom1 < top2 ) // Bottom 1 is above top 2
        return false; // No collision

    // None of the above test were true, collision! return true;

The resulting function


So here's the final function for you to copy and test out.

If you want to shorten the code, you can remove the comments and replace the variables with the rect x / y / w / h values like so :

if ( rect1.x > ( rect2.x + rect2.w ) )// Left 1 is right of right 2
    return false; // No collision

I chose to not do this as the longer version is a bit easier to read and understand.

Our first game!


Our first game is of the "lead the chicken safely across the road" kind of things. Or, as in our case, "lead the square from the rectangle, past all the other square and to the other rectangle." You control the square with the arrow keys. If you hit a red square, you'll end up where you started. If you make it to the other side, you'll also end up where you started, but at least you have that tiny sense of victory for helping our poor little square!


The code just uses the different things we've learned so far, so I won't explain it other than in code comments and ( hopefully ) descriptive names.

So without further ado, here's the code :




Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

For a full list of my tutorials / posts, click here.

tirsdag 22. april 2014

[ SDL2 - Part 4 ] Making things happen

Make things happen!

Games without any input would be really boring. Actually it wouldn't be a game at all, just a movie. So let's look at how we can get input so that the player can actually play the game. But before we do that, we need to take a look at how we do the things updates every frame. ( A frame is a single image of the game, basically each SDL_RenderPresent(..) is the end of a frame. )

The game loop


In a game ( and many other applications ) things need to happen over and over again. So you need a big loop that does all of these things. A minimal game loop covers :
  • Objects needs to be moved
  • Input handling
  • Collision detections
  • ....

Today we'll focus on the two first points, we'll cover collision detection later.

The game loop itself is usually a form of infinite loop :

bool loop = true;
while ( loop )
     ....

So in order to exit the loop, we need a way of setting the loop bool to yountrue inside the loop.This will make the loop condition ( if ( loop ) ) false and the loop will stop. We could just use a break; to quit the loop. But this won't work when we start handling input. We'll see why in a few moments. But first, we need to move on to the next SDL object :

Events in SDL2


All events in SDL2 is in the form of a SDL_Event struct. A SDL_Event is a huge structure with tons of member variable with names that generally don't say a lot about what they're for. It is used for just about everything ;

  • Quit event
  • Mouse events
  • Keyboard events
  • Window events( resize, minimize, move, focus, ...  )
  • Phone events ( touch, scale, flipping, ... )
  • ...And the list goes on...

The type of the event is contained int the .event. This is an enum of the type SDL_EventType If you take a look at the documentation, you'll see that it has a lot of fields. But to start out, we'll only look at SDL_Quit and SDL_KeyDown.

Event polling


Now that we know about the SDL_Event, let's see how we get the event from SDL. The method for doing this is :
int SDL_PollEvent
(
    SDL_Event* event
)

As you can see, it's pretty straight forward. Just pass it a pointer to a SDL_Event and it will populate the structure. If it returns 0, there are no more events. There will most likely be more than one SDL_Event in each iteration, so we'll need to put this function in a loop.

bool loop = true;
while ( loop ) ....
{
    SDL_Event event;
    while ( SDL_PollEvent( &event )
    {
        // Handle events here....
    }
}

SDL_Quit


The first SDL_EventType we'll be handling is SDL_QUIT. Which occurs when the user quits our game. Either using the x on the top of the window or Alt + F4

bool loop = true;
while ( loop ) ....
{
    SDL_Event event;
    while ( SDL_PollEvent( &event )
    {
        if ( event.type == SDL_QUIT )
            loop = false;
    }
}

And there we go! Now the user can exit the program. Which is rather important...

SDL_KeyDown


Let's handle a more interesting event. Namely keyboard presses. These have the event type
SDL_KeyDown. All possible key presses is stored within the enum called SLD_KeyCode. If you want to see all possible values, you can look at the documentation. We won't dive into the details of the where the SDL_KeyCode is stored right now because, as I said, it's stored deep inside the SLD_Event. Instead we'll just tell you were to find the SDL_KeyCode.

event.key.keysym.sym

Where the last sym is the actual SDL_KeyCode

Moving things


And now we've come to the highpoint of this part, namely moving something based on user input. Doing this is fairly easy, we already have most code for it. All we need to do is to store the location ( SDL_Rect ) of what we are trying to move somewhere ( for now we'll let it be a global variable along with SDL_Renderer and SDL_Window. )

We can render a rectangle normally like in the last part and move it around based on user input. We'll use the following SLD_KeyCode values for movement
  • SDLK_LEFT    - left arrow key
  • SDLK_RIGHT - right arrow key
  • SDLK_UP       - up arrow key
  • SDLK_DOWN - down arrow key

As you can see, the names are very self-explanatory. And moving the item is as simple as incrementing the x and y of the SDL_Rect. So we get



This will handle arrow key presss and move the object accordingly.


Feel free to comment if you have anything to say or have any issues/questions. I always appreciate getting comments.

For a full list of my tutorials / posts, click here.

tirsdag 15. april 2014

[ SDL2 - Part 3 ] Drawing rectangles

Drawing rectangles



This part will teach you the basics of the coordinate system in SDL( it's the same for the "old" SDL and SDL2 ). It will also teach you about a new and very important struct, SDL_Rect. You'll be using it a lot! And finally we'll draw something!

Note


This part assumes you have SDL2 up and running on your computer, and that you have read the previous part. If you haven't, please scroll down to part1 and use it to install SDL2 before reading on.

The coordinate system


The SDL coordinate system is defined as ( 0, 0 ) being the ( top, left ). This means that a higher y value means further down.

This also means that if you tell SDL2 to draw a rectangle, you'll specify the top-left position of the rectangle instead of the bottom left rectangle. More about this later

The basic rectangle


In order to draw something, be it textures or plain rectangles or text or anything, you need a rectangle to specify where to draw it and the size of what you are going to draw. And to hold the size and position we use an SDL_Rect

SDL_Rect


Data members :
  • uint16 x - the x position of the rectangle
  • uint16 y - the y position of the rectangle
  • uint16 w - the width of the rectangle
  • uint16 h - the height of the rectangle

And that's it. It's a really simple struct, but it's very important in SDL2 rendering.

Drawing a rectangle


Now you have enough knowledge to draw some rectangles in SDL2. Let's start off by looking at a the function for rendering a simple rectangle 

    int SDL_RenderDrawRect
    (
        SDL_Renderer* renderer,
        SDL_Rect rectangle
    )

Parameters
  • SDL_Renderer* - the SDL_Renderer we created in the previous part
  • SDL_Rect*  - the position and size of the rectangle we want to draw.
Return value
  • 0 on success

Not that it also takes a pointer to the SDL_Rect, and not the SDL_Rect itself.

"But what about the color?" you might ask. Remember how in last function we look at
int SDL_SetRenderDrawColor()? Well, basically, the color you set with this function will also be the color you render your objects with. ( For simplicity, I will refer to this color as SDL_DrawColor from now on. )

And now the fun stuff


Let's say you have just created and set up your window and renderer like so:



But wait! It's just a red screen?! As you might have guessed, we forgot to change the color after calling SLD_RenderClear() So the rectangle was drawn with the same color as the background. To make the rectangle visible, we need to change SDL_DrawColor in between SDL_RenderClear() and SDL_RenderDrawRect()

This gives us something like this :



And now we have a nice little rectangle on our screen.

Filling it up...


The function I showed you earlier will only render the edges of the rectangle. What if you want to render the whole rectangle, and not just the edges? Well there is a nearly identical function for that :


int SDL_RenderFillRect
(
    SDL_Renderer* renderer,
    SDL_Rect rectangle
)
Parameters
  • SDL_Renderer* - the SDL_Renderer we created in the previous part
  • SDL_Rect*  - the position and size of the rectangle we want to draw.
Return value
  • 0 on success

As you can see, the only thing that separates the two us the name. If you switch SDL_RenderDrawRect() with SDL_RenderFillRect() in the example above, you will get the same rectangle with the same color, but this time it will be the whole rectangle and not just the edges.

Conclusion


That's it for today! Feel free to experiment with two new functions. You can draw as many rectangles as you want, both filled and edges. You can also change the color as often as you want. The only thing you need to remember is to put it all between your SDL_RenderClear( renderer ); and SDL_RenderPresent( renderer );

Have fun! Below is a full working example to experiment with. I have taken the liberty of putting things in different functions to make it easier to read. =)



The comments in the code should explain most of what's going on. But you need to run the program to really see what's going on. The code will draw a green-red check board pattern with 2 x 2 tiles inside a blue rectangle. Under the check board, there will be a rectangle that's twice as long to show that the SDL_Rect doesn't have to be a square.


Feel free to comment if you have anything to say or have any issues/questions. I always appreciate getting comments.

For a full list of my tutorials / posts, click here.

søndag 13. april 2014

[ SDL2 - Part 2 ] Your first SDL2 application

Your first SDL2 application


This part assumes you have SDL2 up and running on your computer. If you haven't, please read part 1 and use it to install SDL2 before reading on.

SDL2 structures


The SDL2 library has a substantially improved rendering structure from SDL2. The new structure is very simple and easy to understand This is a short tutorial / reference guide that will teach you everything you need to know in order to start programming SDL2 applications.

The two major objects you need to know :

SDL_Window


This is the physical window you see on your screen. One SDL_Window represents one physical window on your screen. You can have as many SDL_Windows as you like. The structs holds info about the window like position, size, window state and window style.

SDL_Renderer


The SDL_Renderer is basically what you use to render to the screen. The renderer is usually tied to a window. One renderer can only render within one window. The SDL_Renderer also contains info about the rending itself like hardware acceleration and v-sync prevention.

This tutorial will focus on creating and setting up these so we can start drawing to our screen.

Setting up SDL2


Before you can use SDL2, you must set it up by initializing it and creating a SDL_Window and a SDL_Renderer This section will help you to just that.

Initializing SDL2


The first thing you need to do is to initialize SDL. This is done using the following function :
int SDL_Init(Uint32 flags)
Parameters :
  • flags - specifies what you want to initialize. Set it to SDL_INIT_EVERYTHING to initialize everything.
Return value
  • 0 on success -1 oterwise

Since the function can fail ( though it probably won't ) you should add code that handles this. I also recommend you print an error message with SLD_GetError() because it will tell you what went wrong. This tutorial will do this for the most important setup functions.

This makes our code so far look something like this :



Setting up the SDL_Window


Now that we have initialized SDL2, we can can start creating our window, this is done by using the following function :
SDL_Window* SDL_CreateWindow
(
    const char* title,
    int posX,
    int posY,
    int sizeW,
    int sizeH,
    Uint32 flags
)
Parameters :
  • title -the window caption/title that appears on the top of the window
  • posX - x position of the window.
  • posY - y position of the window.
  • sizeW - width of the window
  • sizeH - height of the window
  • flags - specifies window state or properties. More info here
Return value
  • valid pointer on success. nullptr/NULL on oterwise
We'll set the flag parameter to 0 for now. This simply means we'll end up with a standard window that's not maximized, minimized or fullscreen.

Remember to handle it if the function returns NULL. So we end up with something like this :



Creating the SDL_Renderer


Now for the last object we need to start rendering. This time it's a little bit more work involved, but nothing too scary. We begin by creating the renderer. This is done using the following function :
SDL_Renderer* SDL_CreateRenderer
(
    SDL_Window* window,
    int index,
    Uint32 flags
)
Parameters :
  • window - the SDL_Window this renderer will be attached to. In our case, this is the SDL_Window we just created.
  • index - specifies which rendering driver to use. It sounds complicated, but we can just specify -1. This means we'll use the first driver we can find.
  • flags - species how the rendering should be done. For now, we'll just use SDL_RENDERER_ACCELERATED which lets us use the graphics card to render quickly. You can read more here.
Return valueWindow
  • a valid pointer on success. Otherwise NULL.
As always ; remember to handle any return of 0.



Setting up the renderer


Now that we have created the SDL_Renderer we are technically ready to start rendering. But there are a few more things we should do first...

First of all we should set the resolution of the renderer :
int SDL_RenderSetLogicalSize
(
    SDL_Renderer* renderer,
    int width,
    int height
)
Parameters :
  • window - the SDL_Window this renderer will be attached to. In our case, this is the SDL_Window we just created.
  • index - specifies which rendering driver to use. It sounds complicated, but we can just specify -1. This means we'll use the first driver we can find.
  • flags - species how the rendering should be done. For now, we'll just use SDL_RENDERER_ACCELERATED which lets us use the graphics card to render quickly. You can read more here.
Return value
  • 0 on success, -1 oterwise
This is pretty straight forward, the first argument is the renderer on which to set the resolution on. The second and third is the width and height. Normally these are the same as the width and height of the SDL_Window.

And now the time has come to set the color. Here is the function for doing that :
int SDL_SetRenderDrawColor
(
    SDL_Renderer* renderer,
    Uint8 red,
    Uint8 green,
    Uint8 blue,
    Uint8 alpha
)
Parameters :
  • renderer - the SDL_Renderer on which to set render color
  • red - specifies amount of red ( 0 - 255 )
  • green - specifies amount of green ( 0 - 255 )
  • blue - specifies amount of blue ( 0 - 255 )
  • alpha - specifies amount of alpha ( 0 - 255 ) 0 = completely transparent
Return value
  • 0 on success, -1 oterwise

That's it! We're done with the setup. And now we can start using the renderer for fun stuff!



Rendering something


Now it's time to get started on the renderng.
The first thing we need to do before drawing something, is to clear our window. This means we fill our window with the color we set using SDL_SetRenderDrawColor() This is done by calling :
int SDL_RenderClear
(
    SDL_Renderer* renderer
)
Parameters :
  • renderer - the SDL_Renderer on which clear
Return value
  • 0 on success, -1 oterwise
This function should be called at the beginning on every frame to clear the screen and make it ready for more stuff.

But... SDL_RenderClear ( and any other SDL_Render functions ) works behind the scenes. They don't actually draw anything on the screen. So, in order for he drawing ( including SDL_RenderClear ) to take effect, we need to call another function.
int SDL_RenderPresent
(
    SDL_Renderer* renderer
)
Parameters :
  • renderer - the SDL_Renderer on which to render
Return value
  • 0 on success, -1 oterwise
This function takes whatever you have drawn to the screen using SDL_Render* and actually puts it on the screen. So that after calling this, the screen will be all nice and red. And that's it for now. In the next part I'll go into rectangles and actually rendering something interesting ( yes, I assume red screens doesn't catch your interest. )


That's if for part 1. We now have a nice red window. Next time we'll be rendering rects and other neat stuff.

Here is all the code so far. You should be able to just copy paste and compile.




Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

For a full list of my tutorials / posts, click here.

lørdag 12. april 2014

[ SDL2 - Part 1 ] Setting up SDL2

Introduction


This tutorial will teach you how to program your own games using C++ and SDL2! This first part will just teach you how to set up SDL2. Don't worry, it's very easy. And when you're done, you can jump ahead to part 2 where we will get something on screen.

This series is a little fast-paced and is mostly aimed at people who knows the basics of programming in C++, but I will try to explain everything. The series will also explain the various types and functions in SDL2, what they do, and what they are for. By the end of the series, you will have a good understanding of SDL2.

During the series we will be making several small games, but I recommend that you play around with the code and have fun. The best way of learning is to experiment.

So what is SDL2?


SDL is a cross-platform multimedia development library. You can use SDL to access your keyboard, for graphics, play sounds and for communication over Internet. SDl2 can also be used alongside with SDL2. You can also, for instance, use SDL2 to create the window and for window and OpenGL for rendering ( I'll probably go into that in a later guide. )

SDL2 brings on a set of changes from SDL1.2. First of all, SDL2 has support for hardware acceleration, which means it'll be very fast compared to SDL1.2. It also has an improved rendering structure with an object representing the window and an object for dealing with the rendering. I will cover these in more detail in the next post. For now, let's just install it.

Installation


Installing SDL2 can be a bit tricky, especially on some operating systems where you might have to compile it yourself ( though this is becoming more and more rare. )

Linux


Linux comes in all shapes and sizes. Below are guides on how to install on most distributions of Linux.

Debian ( Ubuntu, Debian, Mint )


Depnding on your distro and version, you might be able to install SDL2 using the package manager. I.e :
sudo apt-get install libsdl2

If your package manager does have SDL2. it will be installed and you're done. If not, you'll have to compile SDL2 yourself Don't worry, it's easy. Just follow this excellent guide :
Installing SDL2 on Linux

Arch


Probably the easiest. Simply use pacman :
sudo pacman -S sdl2
And that's all, SDL2 is installed now.

Fedora


Just as easy as Arch :
sudo yum install sdl2
Note: Since I'm not running Fedora, I haven't been able to test this. But it should work, and if it doesn't, feel free to post a comment ( you'll be the first, you lucky bastard! )

Other distros?


If you are using other distributions, there are three things you can try.
  1. Simply use your package manager and see if it has SDL2, libsdl2 or lSDL2 or something like that.
  2. Try Google! Yes, I know it's kinda obvious, but chances are someone else has had the same issue, it's worth a shot.
  3. If 1 and 2 doesn't work, you could still try the guide for Debian. You will have to switch sudo apt-get install with the command for install packages on your distribution.

Windows


Note: the names and menus might mentioned in this guide might be slightly wrong since I don't have access to a Windows machine at the moment.

Installing on Windows is actually a bit more elaborative than installing on Linux. The upside is that you can set it up in the same way on any version of Linux! This guide assumes you have any version of VisualStudio installed.

1. Download SDL2 development libraries


Go to the SDL2 download page.
And download SDL2-devel-2.x.x-VC.zip (Visual C++ 32/64-bit) Once you have downloaded the .zip file, you can unzip it anywhere you like.

2a. Moving development files


1
The .lib and .h files are used during linking and compiling. This means that VisualStudio needs to know where you have placed them. I suggest you copy the files from where you have unzipped them and move them to a place you will remember. For instance
C:/Libraries/lib/SDL2/
for .lib files.

And
C:/Libraries/include/SDL2/
for header files.

Now that you have the development files in a secure location, it's time to move on to the next step.

2b Specifying development file locations in VisualStudio


As I said earlier, VisualStudio needs to know where you .lib and .h files are.

Open
Tools -> Options -> Projects and Settings -> VC++ Directories -> Include Directories
Under here, add the folder containing the folder you copied your project to. I.e
C:/Libraries/include/
and not
C:/Libraries/include/SDL2/

Under Include directories you should see
Library Directories

Here you need to add the library (.lib ) files. This time though, you add the directory where the .lib files are. So in my example, it'll be
C:/Libraries/lib/SDL2/

And finally, navigate to Input and add SDL2.lb and SDL2main.lib

Now you should be able to build SDL2 applications! But we're not quite done yet.

3 Copying .dll files


The .dll files are needed to run SDL2 applications. When it comes to placing them you have two options :
  1. In the project directory  ( same folder as your .exe file. ) This means you have to copy them every time you create a new project.
  2. In your Windows system directories. 
    • In x86 this directory is C:/Windows/system32/
    • In x64 this directory is C:/Windows/SysWOW64/ though you might have to place them in System32/ as well.
Personally I would go for option 1. This also makes it easier to share your application ; all you have to do is copy the folder. Whereas if you went with option 2, you would also have to find the .dll files and copy them along with your .exe anyways.

And you're done. You can now create your own SDL2 applications in VisualStudio.

Mac


This will be the shortest guide and it will only cover homebrew since I don't have the access to any computer running OS X.

In terminal simply type
brew install SDL2

Note: Since I haven't actually tested this, I can't guarantee that it will work.

Testing it


Now we come to the fun part, we get to actually use it and run or SDL2 application. Our end result isn't terribly exiting this time, it just creates an empty window with a red background. But things will get better, I promise!

Compiling on Linux and Mac using terminal


To compile on Linux, simply add lSDL2 to your compilation string. To compile main.cpp you can do

clang++ main.cpp -lSDL2 -o SDLTest

If you are using GCC, the compilation string is

g++ main.cpp -lSDL2 -o SDLTest

Compiling on Linux and Mac without terminal


If you're not using the terminal, you need to set up your IDE to use the SDL2 libraries. This should be a simple process, check the documentation for you IDE to find exactly how to do this. I do recommend using the terminal, though. It's much simpler.

Compiling on Windows in VisualStudio


If you have followed my guide, you shouldn't have to do anything in order to compile.

If you get any compile errors you need to check your include directory. Remember that you should add the folder that has the SDL2 folder, but not the SDL2 folder itself. This is because the example code uses #include

If you get linker errors, make sure you have added the folder with the SDL2.lib file.

If you get runtime errors, make sure you have all the .dll files in an appropriate directory.

Sample code


To test it, simply replace the content with your main.cpp with the following code snippet. If it displays a window, SDL2 is working properly on your window. Don't worry about the code just now, I'll explain it in the next part.




Feel free to comment if you have anything to say or have any issues/questions. I always appreciate getting comments.

For a full list of my tutorials / posts, click here.