Allegro Hello World tutorial

From Guichan

Jump to: navigation, search

Purpose

The purpose of this tutorial is to give a quick start in how to set up Guichan with Allegro given a small guided Hello World application. For information regarding Allegro please read the official Allegro documentation.

Tutorial

To be able to use Guichan and Allegro in an application the Guichan header, the Guichan Allegro header and the Allegro header need to be included. The Guichan header contains everything needed from the core library, the Guichan Allegro header includes everything for the Allegro back end for Guichan.

#include <guichan.hpp>
#include <guichan/allegro.hpp>
#include <allegro.h>

Every application needs a main function, including this one. Apart from the main function it's good practise to add a function to initialise the application, a function to run the application and a function to halt the application. We let the main function simply first call the initialisation function followed by the run function and the halt function.

void init() 
{

}

void run()
{

}

void halt()
{

}

int main(int argc, char **argv)
{
    init();
    run();  
    halt();

    return 1;
}

Guichan throws exception as soon as an error is encountered, we therefore alter our main function slightly to catch exceptions and print their error message.

int main(int argc, char **argv)
{
    try 
    {
        init();
        run();  
        halt();
    }
    catch (gcn::Exception e)
    {
        std::cout << e.getMessage() << std::endl;
    }
    catch (std::exception e)
    {
        std::cout << "Std exception: " << e.what() << std::endl;  
    }
    catch (...)
    {
        std::cout << "Unknown exception" << std::endl;
    }

    return 1;
}
END_OF_MAIN()


To be able to use Allegro we need a bitmap for the screen. We add a declaration of a variable for a bitmap below the inclusion of the headers. To be able to use Guichan with Allegro we need a couple of objects from the Guichan Allegro back end to give Guichan the ability to use Allegro. The objects are a AllegroGraphics object, a AllegroInput object and a AllegroImageLoader object. We add declarations of variables for those objects below the other declared variables.

BITMAP *screenBuffer;

gcn::AllegroInput* input;
gcn::AllegroGraphics* graphics;
gcn::AllegroImageLoader* imageLoader;

As this tutorial shows a Hello World application we also need a couple of objects from Guichan in order to create a GUI. The objects are a Gui object, a Container object, a Label object and finally a Font object (in this case we use an ImageFont object).

gcn::Gui* gui;
gcn::Container* top;
gcn::ImageFont* font;
gcn::Label* label;

In the initialisation function we begin with initialising Allegro.

void init()
{
    allegro_init();

    int bpp = desktop_color_depth();
    if (bpp == 0)
    {
        bpp = 16;
    }

    set_color_depth(bpp);

    if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0))
    {
        if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0))
        {
            throw GCN_EXCEPTION("Unable to set graphics mode");
        }
    }

    screenBuffer = create_bitmap(SCREEN_W, SCREEN_H);

    if (screenBuffer == NULL)
    {
        throw GCN_EXCEPTION("Unable to create a screen buffer bitmap!");
    }

    install_keyboard();
    install_mouse();
    install_timer();
}

After Allegro has been initialised we initialise the Guichan Allegro back end. We first instantiate a AllegroImageLoader object. As all images in Guichan should use the AllegroImageLoader when loading themselves we use a static function in Image to provide the image loader. After AllegroImageLoader we instantiate the AllegroGraphics object. AllegroGraphics needs a bitap to draw to and we provide the object with the screen buffer bitmap as we want our GUI to be drawn to the screen. Finally we instantiate the AllegroInput object, an object with no need of initialisation.

imageLoader = new gcn::AllegroImageLoader();
gcn::Image::setImageLoader(imageLoader);
graphics = new gcn::AllegroGraphics();
graphics->setTarget(screenBuffer);
input = new gcn::AllegroInput();

After the Guichan Allegro back end has been initialised we initialise Guichan. As we need to display text in a Hello World application we need a font. In Guichan there exists an easy to use font called ImageFont which we will be using. The ImageFont uses a normal image containing glyphs separated with a certain colour. When initialising the ImageFont the file name of the image is proved along with a string with the characters the image contains. For convenience a static function in Widget exists to set a global font that all widgets should use unless a widget is given a specific font to use.

After the ImageFont has been instantiated an initialised we instantiate a Gui object. The Gui object is the core object in Guichan and it contains a GUI. After the initialisation we provide the Gui object with the AllegroGraphics object and the AllegroInput object so the Gui can utilise Allegro for drawing and grabbing user input.

font = new gcn::ImageFont("fixedfont.bmp", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
gcn::Widget::setGlobalFont(font); 

gui = new gcn::Gui();
gui->setGraphics(graphics);
gui->setInput(input);

Gui can actually only contain one widget, the widget is referred to as the top widget. To make Gui able to contain more than one widget the top widget has to be a container widget which is a widget that can contain other widgets. In this tutorial we are going to make a Hello World application that only needs one widget - Label widget - to display text, but for completeness we set a container as the top widget as that is the most common thing to do. To make the container as big as the screen we set it's dimension the dimension of the screen.

Finally we instantiate a Label widget, provide the label with the caption "Hello World" and add the label to the GUI by adding it to the top container. Before we add the container we set the label's position to be somewhere in the middle of the screen.

top = new gcn::Container();    
top->setDimension(gcn::Rectangle(0, 0, 640, 480));
gui->setTop(top);

label = new gcn::Label("Hello World");
label->setPosition(280, 220);
top->add(label); 

In the run function we begin by adding a while loop as the main application loop. As it would be nice to be able to quit the application by pressing the escape key we let the while loop loop as long as the escape key is not pressed. In the loop we tell the Gui object to perform logic and to draw itself. Finally we draw the mouse cursor and blit the screen bitmap to the screen so the screen will be updated.

void run()
{
     while(!key[KEY_ESC])
     { 
        gui->logic();
        gui->draw();

        draw_sprite(screenBuffer, mouse_sprite, mouse_x, mouse_y);
        blit(screenBuffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
    }
}

In the halt function we simply clean up all the instantiated objects and tell Allegro to destroy the screen buffer bitmap.

void halt()
{
    delete label;
    delete font;
    delete top;
    delete gui;
  
    delete input;
    delete graphics;
    delete imageLoader;
    
    destroy_bitmap(screenBuffer);
}

And that's all there is to it to make a Hello World application.

Complete code


#include <guichan.hpp>
#include <guichan/sdl.hpp>
#include <allegro.h>
 
BITMAP *screenBuffer;

gcn::AllegroInput* input;
gcn::AllegroGraphics* graphics;
gcn::AllegroImageLoader* imageLoader;

gcn::Gui* gui;
gcn::Container* top;
gcn::ImageFont* font;
gcn::Label* label;

void init()
{
    allegro_init();

    int bpp = desktop_color_depth();
    if (bpp == 0)
    {
        bpp = 16;
    }

    set_color_depth(bpp);

    if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0))
    {
        if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0))
        {
            throw GCN_EXCEPTION("Unable to set graphics mode");
        }
    }

    screenBuffer = create_bitmap(SCREEN_W, SCREEN_H);

    if (screenBuffer == NULL)
    {
        throw GCN_EXCEPTION("Unable to create a screen buffer bitmap!");
    }

    install_keyboard();
    install_mouse();
    install_timer();

    imageLoader = new gcn::AllegroImageLoader();
    gcn::Image::setImageLoader(imageLoader);
    graphics = new gcn::AllegroGraphics();
    graphics->setTarget(screenBuffer);
    input = new gcn::AllegroInput();

    font = new gcn::ImageFont("fixedfont.bmp", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
    gcn::Widget::setGlobalFont(font); 

    gui = new gcn::Gui();
    gui->setGraphics(graphics);
    gui->setInput(input);

    top = new gcn::Container();    
    top->setDimension(gcn::Rectangle(0, 0, 640, 480));
    gui->setTop(top);

    label = new gcn::Label("Hello World");
    label->setPosition(280, 220);
    top->add(label); 
}

void run()
{
     while(!key[KEY_ESC])
     { 
        gui->logic();
        gui->draw();

        draw_sprite(screenBuffer, mouse_sprite, mouse_x, mouse_y);
        blit(screenBuffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
    }
}

void halt()
{
    delete label;
    delete font;
    delete top;
    delete gui;
  
    delete input;
    delete graphics;
    delete imageLoader;
    
    destroy_bitmap(screenBuffer);
}

int main(int argc, char **argv)
{
    try 
    {
        init();
        run();  
        halt();
    }
    catch (gcn::Exception e)
    {
        std::cout << e.getMessage() << std::endl;
    }
    catch (std::exception e)
    {
        std::cout << "Std exception: " << e.what() << std::endl;  
    }
    catch (...)
    {
        std::cout << "Unknown exception" << std::endl;
    }

    return 1;
}
END_OF_MAIN()
Personal tools
community