2D Game Programming In C++ Under Windows: Doing Cool Things With Allegro

In This Tutorial Series

I: 2D Game Programming In C++ under Windows.

II: 2D Game Programming in C++ under Windows: Allegro Basics (For developing Simple Games)

III: 2D Game Programming In C++ under Windows: Doing Cool Things With Allegro

In the Last tutorial of this Game Programming tutorial series, we learned the basics of Allegro.

We discussed:

  1. How to initialise Allegro System in DevC++ IDE
  2. How Elements are drawn on Screen
  3. Loading Images
  4. Outputting Text
  5. Handling Keyboard Inputs

And if you remember, from my first article in this series, that we decided that when we've learned enough, we'll test our knowledge by creating a super cool (Okay.. mayn't be as cool) n' basic 2D Game.

We've come this far, and by now, we've seen a few things. Its time to do something that actually counts! In this tutorial, I'll show you how to animate your game characters and set up things in motion.

Before you can start Coding!

Well, before you can start coding, and I assume, you've got DevC++ Compiler, and Allegro DevPaks, as I discussed in the first tutorial. If not, get them!

Now, we can formally BEGIN!


Starting Up..

To start with, create a new project in Dev C++ (fig-1-1)

1. From the Menu, select File->New->Project. Now give it a good name. Say 'AllegroSample'.

2. Select Empty Project. (fig-1-2)

3. From the Project Explorer on Left, Select 'AllegroSample' or whatever name you gave, and RIGHT Click->New File

fig-1-1
fig-1-1 | Source
fig-1-2
fig-1-2 | Source

Setting up Project Parameters

WARNING: If you skip this step, you'll be haunted forever by mysterious 'Linker' errors!

Every programming Library has files, that have to be linked at the time of compiling.

From Menu, select Project Options. Now click the 'Parameters' tab. In the text-field for under 'Linker' label, add the following three:

-lalfont -lalleg -lalpng

Now, click 'Add Library or Object'. Browse to your 'lib' folder in the DevCpp main Directory. Select ' liballeg.dll.a '. Click Open.

Now the above file will be there as a fourth entry in the Linker list.

You're done, Click 'OK' .


Project Parameters
Project Parameters | Source

Inside The Code

Now you're ready to code something Real! If you remember (No worries even if you don't) from the last tutorial, I showed you the program structure in Allegro.

Essential Header Files & Program structure

#include<allegro.h> /* Once inside Allegro system, this is all we'll need */
#include<alpng.h>
#include <alfont.h>

int main()
{
//We'll write more here inside

return 0; //Just for the customs, skip it anyway :D

}
END_OF_MAIN() /*this one's important, believe me, they say
	       it'll keep you away from troubles */

A Sample Code To Bring up a Colored Surface for Test!

int main()
{
    int w=900,h=700,x=0,y=0;
    
    BITMAP *buffer;	
    
    allegro_init();	//Initialise Allegro
    install_timer();	//Install Timer
    
    set_color_depth(desktop_color_depth());	//Set Color depth
    
    set_gfx_mode(GFX_DIRECTX_WIN,w,h,0,0);	//Set Graphics Mode

    
    buffer=create_bitmap(w,h);	/*Create a buffer Bitmap surface in RAM */
    
    clear_to_color(buffer,makecol(0,94,255));  
  /* Recolor Bitmap to a RGB vale */    

    draw_sprite(screen,buffer,x,y); /* Draw buffer on Screen (lies in Video memory,stands for the drawing surface) */
    
    rest(1000);	//Pause for 1000 milli secs
    
    allegro_exit(); //Exit Allegro System.
}
END_OF_MAIN()
The Blue Screen the code generates
The Blue Screen the code generates

Moving On..

Now we've a surface to draw on, let's bring up a character, and let's try to make it move, using Keyboard!

We take a Ball, a simple basketball. Make sure that the picture dimensions are proper. Take a 60x60 dimension png file. (Yes 'png', as we want transperancy!)

Bring up a ball at coords (x,y)

//(0,0) is top-left corner
int main()
{
       BITMAP *ball, *buffer;
       PALLETE pal;
 	
       int w,h,x=0,y=0;
       allegro_init();
       
       set_color_depth(desktop_color_depth());
       w=900;h=700;
              
       set_gfx_mode(GFX_DIRECTX_WIN,w,h,0,0);

       install_timer();     
       
       buffer=create_bitmap(w,h);
   
       ball=load_png("ball.png",pal);   /* replace 'ball.png' with the 
picture file you have */
  
       set_alpha_blender();    /*This is a must if you load a picture with alpha layers, i.e transparent layers, as in png images */
   

        clear_to_color(buffer,makecol(0,94,255));  //Nothing New
        draw_trans_sprite(buffer,ball,x,y);        /* Draw the transparent png on the buffer, at coords (x,y)
        
        draw_sprite(screen,buffer,0,0); /*Finally draw the buffer on the screen */
        
        rest(1000); /*Pause, for as long as you want. Its in milli secs! */
    
        allegro_exit();
}
END_OF_MAIN()

Its time to take control!

Now we'll take Keyboard Inputs, and move the ball accordingly. Like before, we discussed the keyboard scancodes, in my last tutorial. The Code below, when added to existing code, will move the ball wherever you want!

Just for a Quickie:

key[KEY_LEFT]-> Left Arrow Key

key[KEY_RIGHT]-> Right Arrow Key

key[KEY_UP]-> Up Arrow Key

key[KEY_DOWN]-> Down Arrow Key

key[KEY_ESC]-> Escape Key

Move your ball!

int main()
{
       BITMAP *ball, *buffer;
       PALLETE pal;
       
       int w,h,x=0,y=0,ballD=100; /*ballD is ball size, as in image */
       allegro_init();
       
       set_color_depth(desktop_color_depth());
       w=900;h=700;
              
       set_gfx_mode(GFX_DIRECTX_WIN,w,h,0,0);

       install_timer();     
       install_keyboard();  //We install Keyboard

       buffer=create_bitmap(w,h);
   
       ball=load_png("ball.png",pal);  
  
       set_alpha_blender();    
   
        
        while(!key[KEY_ESC])
        {
                          clear_to_color(buffer,makecol(0,94,255));  
                          draw_trans_sprite(buffer,ball,x,y);    
                          draw_sprite(screen,buffer,0,0);   
                          
                          if(key[KEY_LEFT])
                           {
                                           if(x>0)
                                           x--;
                           }
                           
                          if(key[KEY_RIGHT])
                           {
                                            if(x<w-ballD)
                                            x++;
                           }
                           
                          if(key[KEY_UP])
                           {
                                         if(y>0)
                                         y--;
                           }
                           
                          if(key[KEY_DOWN])
                           {
                                           if(y<h-ballD)
                                           y++;
                           }  
        }
    
        allegro_exit();
}
END_OF_MAIN()

Balls don''t do that way!

That's not the natural behavior of a basketball! It can't move up or down in that manner, you'd say..

Okay then?

It should bounce, n' well let it go left and right!

Al'ryt then, once the specified button for 'bounce' is pressed, the ball will bounce, go to some height, and return Down To Earth. Now we can again use the 'rest()' function to control the motion of the ball. But rest() will block evrything else, as well! But we want the ball's motion to continue asynchronously within the Game World. So?

Timers To The Rescue, Sir (or ahmm, Ma'm) !

We'll use a timer to control the upward motion of the ball, to make it more natural. Once up, the ball's speed should decrease with time, until it comes to halt. If your Game World has gravity, the value of acceleration will determine this timing, but here we arbitrarily decide one.

Also, the ball's speed will increase as it comes down. (Conservation of Energy :D)

And for still more realistic animation, we can set up resultant bounces, as on a tough surface. i.e. say, 2 more times the ball will bounce, to lower heights, if you don't give another bounce command, once it comes down.

For now, we just implement, one bounce per Space pressed. To implement multiple bounces, just make a bounce() function, and pass maxHeight parameters, as decided in the 'bounce' sequence.

(For a brief discussion on Timers in Allegro, visit my last Tutorial on Allegro Basics)

I'm posting the whole code, as changes are hard to keep track of otherwise!

#include<allegro.h>
#include<alfont.h>
#include<alpng.h>

time_t secs;
      
      
volatile int t=0; //volatile tells the compiler not to optimize the 
          //variable, as it can be changed 
             
 
void inc_t(void)
 {
     t++;
 }

int main()
{
       
       PALLETE pal;
       BITMAP *ball, *buffer;
       int w,h,x=0,y=0,ballD=100;
       allegro_init();
       
       set_color_depth(desktop_color_depth());
       w=900;h=700;
              
       set_gfx_mode(GFX_DIRECTX_WIN,w,h,0,0);

       install_timer();     
       install_keyboard();
       
       LOCK_VARIABLE(t);
       LOCK_FUNCTION(inc_t);
      
       install_int(inc_t,1000);
       
       buffer=create_bitmap(w,h);
   
       ball=load_png("ball.png",pal);  
  
       set_alpha_blender();    
       
       bool bounceSeqOff=true,goingUp=false,goingDown=false;
       int stime=0,sy,maxHeightAllowed=200;
       x=0; y=h-ballD;
        
        while(!key[KEY_ESC])
        { 
                          
                 if(key[KEY_LEFT])
                    {
                      if(x>0)
                      x--;
                     }
                               
                  if(key[KEY_RIGHT])
                    {
                      if(x<w-ballD)
                       x++;
                    }
                               
                  if(key[KEY_SPACE] && bounceSeqOff)
                    {
                     bounceSeqOff=false;   
                     goingUp=true; 
                     stime=t;
                     sy=y;
                    }
                              
                   if(!bounceSeqOff&& y>0)
                    {
                     if(goingUp)
                      {
                                                               
                           //Bounce Sequence Handler
                            //First 400 ms
                           if(t-stime<=400&& y>=sy-maxHeightAllowed)
                              y-=5;
                                               
                            //Next 400 ms
                           else if(t-stime<=800&&y>=sy-maxHeightAllowed)
                              y-=3;
                                                  
                                                   
                           else if(t-stime>800&&y>=sy-maxHeightAllowed)
                               y-=2;
                                                    
                           else if(y<=sy-maxHeightAllowed)
                               {goingUp=false; goingDown=true; stime=t; }
                         }
                                             
    
                         if(goingDown)
                           {
                            //Bounce Sequence Handler
                            //First 400 ms
                            if(t-stime<=400&& y<sy)
                             y+=2;
                                               
                            //Next 400 ms
                            else if(t-stime<=800&& y<sy)
                             y+=3; 
                                              
                             else if(t-stime>800&& y<sy)
                               y+=5;
                                                
                              else 
                               {goingDown=false; bounceSeqOff=true; y=sy; }
                             }
                                              
                              if(y>sy) {y=sy; bounceSeqOff=true;}
                             }
	//Update Changes On Screen
                               
                   clear_to_color(buffer,makecol(0,94,255));  
                   draw_trans_sprite(buffer,ball,x,y);    
                   draw_sprite(screen,buffer,0,0);  
            }
        
        allegro_exit();
}
END_OF_MAIN()

A ball up!

To bounce the ball, we're basically, slowing its speed, when it goes up, and speeding it up as it comes down. As accurately you can program the logic as pointed in the code, using more timing logic, more realistic the bouncing ball will look .

It has just begun. A ball always rotates (Almost always..) Now we'll Rotate the ball.

Only the changed part of the code is included

  fixed angle=0; //The Angle of rotation
  bool  linearMotion=false,RlinearMotion,LlinearMotion;
  int rot=0;
        
        while(!key[KEY_ESC])
        { 
                          
                 if(key[KEY_LEFT])
                    {
                      if(x>0)
                      x--;
                      
                      linearMotion=true;
                      
                      RlinearMotion=false;
                      LlinearMotion=true;
                      
                      angle-=20000;	//Rotate counter-clock
                     }
                               
                  if(key[KEY_RIGHT])
                    {
                      if(x<w-ballD)
                       x++;
                       
                       linearMotion=true;
                       
                      RlinearMotion=true;
                      LlinearMotion=false;
                      
                      angle+=20000;	//Rotate Clock
                    }
                               
                  if(key[KEY_SPACE] && bounceSeqOff)
                    {
                     bounceSeqOff=false;   
                     goingUp=true; 
                     stime=t;
                     sy=y;
                     
                     linearMotion=false;
                     RlinearMotion=false;
                      LlinearMotion=false;
                    }
                              
                   if(!bounceSeqOff&& y>0)
                    {
                     if(goingUp)
                      {
                                                               
                           //Bounce Sequence Handler
                            //First 400 ms
                           if(t-stime<=400&& y>=sy-maxHeightAllowed)
                              y-=5;
                                               
                            //Next 400 ms
                           else if(t-stime<=800&&y>=sy-maxHeightAllowed)
                              y-=3;
                                                  
                                                   
                           else if(t-stime>800&&y>=sy-maxHeightAllowed)
                               y-=2;
                                                    
                           else if(y<=sy-maxHeightAllowed)
                               {goingUp=false; goingDown=true; stime=t; }
                         }
                                             
    
                         if(goingDown)
                           {
                            //Bounce Sequence Handler
                            //First 400 ms
                            if(t-stime<=400&& y<sy)
                             y+=2;
                                               
                            //Next 400 ms
                            else if(t-stime<=800&& y<sy)
                             y+=3; 
                                              
                             else if(t-stime>800&& y<sy)
                               y+=5;
                                                
                              else 
                               {goingDown=false; bounceSeqOff=true; y=sy; }
                             }
                                              
                              if(y>sy) {y=sy; bounceSeqOff=true;}
                             }
                               
                    
                    clear_to_color(buffer,makecol(0,94,255));  
                    
                    if(linearMotion)
                    //rotate
                      rotate_sprite_trans(buffer,ball,x,y,angle);
   
                    
                    else
                     
                     {
                      draw_trans_sprite(buffer,ball,x,y); 
                     }
                   
                   draw_sprite(screen,buffer,0,0);  
            }

Let's decorate a bit!

By now, we've a ball that can be controlled by Keyboard. Let's now add a background picture. Just for the decoration ;) ...You've learned some important things by now.

The order of drawing the sprites, is the order in which elements appear on screen, hmm This one's important to remember ..

//Out of while loop, place
       
       BITMAP *bg;
       bg=load_bitmap("bg.bmp",NULL);  /*Replace 'bg.bmp' by your own file name */


//Inside the loop, Replace clear_to_color(..) line by this

draw_sprite(buffer,bg,0,0);

And we talked about Text too!

Ya, and its the easiest part! In my last tutorial, I showed how to print text using Allegro's default system. But for True Type Fonts, we got AllegroFonts library. If you went through the previous instructions, I assume, you've all set now, just for the coding part.

The code below, prints colored lines for movement actions of the ball!

The additions to the existing code

//Just for simplicity, I'll #define the messages

#define leftMsg "Going Left"
#define rightMsg "Going Right"
#define jumpMsg "Jumpin'"

//Add the above, after #include lines.

//Inside Main(), add these
       alfont_init();
       ALFONT_FONT *Ufont=alfont_load_font("Sylfaen.ttf");
       alfont_set_font_size(Ufont,20);
/*Assuming you've a font file of format .ttf, in your working directory */



/*Inside the loop, add just before 'draw_sprite(screen,buffer,0,0); ' */

                   if(RlinearMotion)
                   alfont_textout_ex(buffer,Ufont,rightMsg,540,100,makecol(0,0,255),-1);
                   
                   else if(LlinearMotion)
                   alfont_textout_ex(buffer,Ufont,leftMsg,540,100,makecol(0,255,0),-1);
                   
                   else
                   alfont_textout_ex(buffer,Ufont,jumpMsg,540,100,makecol(255,0,0),-1);

Finally, we've, umm, just a Bouncing ball, against a fine art, by some talented artist, and some old style colored Text!

Source

By Now..

By now, we've produced code to,

1. Set up Display

2. Create Sprites/Objects for Game.

3. Moving sprites with Keyboard.

4. Displaying Text.

Now what if you had a cartoon sprite? Like 'Tom' the cat? How'll you animate the cat?

Okay, then you'll need frames, the frames of motion at different times. Then using timer, you'll change image source for your 'Tom' BITMAP structure. It'll be more complicated then what we just did. But its just extending what you've learned this far.

What about Other Game character/Objects? Just place them! Computer will do fine, every thing will be almost concurrent to see.

All the codes I've written, are written in a procedural manner. We could have done things much better using OOP (Object Oriented Programming under C++). But then things would have complicated.

We did things for a simple character. You can add multiple, principles will stay the same!


Goodbye..

Wasn't that easy? I bet it was, if you're really into it, but I'm sure you can do amazing things, everyone can :)

Allegro is easy, pretty low level, and can accompolish amazing things. What I've shown is the bare basic, rather a Template you may use anywhere. The Game Programming Library is really worth looking into.

Official Website: https://www.allegro.cc/

One of the sites, which helped me to write my first Allegro Codes, God Bless the Owner :) http://www.cppgameprogramming.com/cgi/nav.cgi?page=allegbasics

A few other 2D Game Programming Libraries:

SDL: Simple DirectMedia Layer. Its more common among the pros. Its comparatively standard, and a bit more difficult. Lay your hands onto it, if you want to, its free, and documentation is good as well. www.libsdl.org

SMFL: Just heard the name, No experience with it . http://www.sfml-dev.org/

For now, that's all. Happy Coding! See ya'll again :)

More by this Author


2 comments

Lautaro 2 years ago

Dude, this is... Dude!

awesome tutorials im starting in allegro so this is really helpful, thanks for the data :D ur awesome


MysticPrince profile image

MysticPrince 2 years ago from The Source Code Author

Really glad that the tutorial was helpful to you.

I hope you find Allegro simple and intuitive :)

Happy Coding! :)

    Sign in or sign up and post using a HubPages Network account.

    0 of 8192 characters used
    Post Comment

    No HTML is allowed in comments, but URLs will be hyperlinked. Comments are not for promoting your articles or other sites.


    Click to Rate This Article
    working