2D游戏引擎Allegro 系列教程(三) 加载并显示图片!

作者:袁全伟 邮箱: qq573011406@126.com 欢迎邮件交流编程心得 2012-12-11
本系列文章由sky编写,转载请注明出处。

http://blog.csdn.net/qq573011406/article/details/8220208

作者:袁全伟   邮箱: qq573011406@126.com    欢迎邮件交流编程心得

本系列教程索引:

2D游戏引擎Allegro 系列教程(一) 配置allegro开发环境
2D游戏引擎Allegro 系列教程(二) Hello world!
2D游戏引擎Allegro 系列教程(三) 加载并显示图片!
2D游戏引擎Allegro 系列教程(四) 文字渲染及显示汉字的方法

一:基本步骤

这一章的目标是在窗口中显示图片,下面是运行结果图,我用的是从梦幻西游中提取的一张地图图片.下面来看一下显示一张图片需要哪些步骤.





基本的步骤如下:

Step1:包含用户加载图片用的image插件的头文件
Step2:链接用于加载图片用的image插件的lib
Step3:定义一个指向ALLEGRO_BITMAP类型的指针,用来指向创建或加载的图片.
Step4:使用al_init_image_addon()函数初始化image插件.
Step5:使用al_load_bitmap("文件名")  函数加载图片.
Step6:使用al_draw_bitmap()将图片渲染到屏幕上.
Step7:释放ALLEGRO_BITMAP所占用的资源.

二:具体步骤

下面咱们看看具体的的步骤:


Step1:包含用户加载图片用的image插件的头文件
这个image的头文件就是 allegro5/allegro_image.h
别要忘记包含这个头文件就行了

Step2:链接用于加载图片用的image插件的lib
接着就是链接库文件了,对应的库文件为 allegro_image-5.0.7-mt-debug.lib
可以用下面这行代码直接链接这个库文件
[cpp] view plaincopy
#pragma comment(lib,"allegro_image-5.0.7-mt-debug.lib")//链接image库,用以加载图片  

Step3:定义一个指向ALLEGRO_BITMAP类型的指针,用来指向创建或加载的图片.
ALLEGRO_BITMAP :
作为一个游戏程序库,图像处理方面是相当重要的。allegro给出了BITMAP的概念,这也是几乎所有和图像有关的程序都支持的概念.
中文将其翻译为位图,意即由位数据构成的图片
ALLEGRO_BITMAP是一个结构,里面包含了一个矩形图片的内存块,这块内存以连续字节的形式储存.当然,这块内存不一定是内存,也可以是显存.
甚至直接映射到屏幕,或者可以共享另一张位图的一部分.——《游戏之旅 我的编程感悟 》云风著

对于BITMAP的概念,有了上面这些就不用多说了吧.我们继续。
用下面的代码声明一个ALLEGRO_BITMAP的指针。
[cpp] view plaincopy
ALLEGRO_BITMAP *bmp=NULL;  

Step4:使用al_init_image_addon()函数初始化image插件.
这一步也是相当的重要,没有这一步的话,加载图片的函数根本无法正常工作。
把这个函数放到你的游戏初始化函数里,并且要放到al_init()函数之后.
还记得我们上一章所写的框架程序吧,其中我们写了game_init()函数. 它负责大部分的游戏初始化工作.
现在我们把这个al_init_image_addon()这个函数放到game_init()里.
[cpp] view plaincopy
al_init_image_addon();  

Step5:使用al_load_bitmap("文件名")  函数加载图片.
[cpp] view plaincopy
ALLEGRO_BITMAP *al_load_bitmap(const char *filename)  

加载一个图片到ALLEGRO_BITMAP里,成功则返回该ALLEGRO_BITMAP的指针,失败就返回NULL.

同样,把这个函数也放到game_init()里.
[cpp] view plaincopy
bmp=al_load_bitmap("bmp.jpg");  
if(!bmp)return 3;  

你可以把图片文件放到工程目录下的debug目录下.

Step6:使用al_draw_bitmap()将图片渲染到屏幕上.
[html] view plaincopy
void al_draw_bitmap(ALLEGRO_BITMAP *bitmap, float dx, float dy, int flags)  

将ALLEGRO_BITMAP渲染到目标BITMAP的指定位置上(dx,dy).
最后一个参数可以暂时先填0就可以了.

我们在game_render()中使用这个函数.

[html] view plaincopy
int game_render(){  
    //用指定的颜色填充屏幕  
    al_clear_to_color(al_map_rgb(0,0,0));  
    //翻转  
    al_draw_bitmap(bmp,0,0,0);  
    al_flip_display();  
    return 0;  
}  

Step7:释放ALLEGRO_BITMAP所占用的资源.
[cpp] view plaincopy
void al_destroy_bitmap(ALLEGRO_BITMAP *bitmap)  

在game_destory()中使用这个函数来释放BITMAP所占用的内存.
[cpp] view plaincopy
int game_destory(){  
    al_destroy_bitmap(bmp);  
    return 0;  
}  


三:完整的源码及图片

[cpp] view plaincopy
//头文件  
#define ALLEGRO_NO_MAGIC_MAIN  
#include <Windows.h>  
#include <allegro5/allegro.h>  
#include <allegro5/allegro_image.h>  
#pragma comment(lib,"allegro-5.0.7-mt-debug.lib") //链接Allegro的库  
#pragma comment(lib,"allegro_image-5.0.7-mt-debug.lib")//链接image库,用以加载图片  
////////////////////////////////////////////////////////////////////////////////////////////  
  
//函数  
int game_init();    //初始化游戏  
int game_run();     //进入游戏循环  
int game_frame();   //逻辑处理函数  
int game_render();  //渲染函数  
int game_destory(); //释放资源  
int game_msg();     //消息处理  
  
//常量  
const int WIN_WIDTH     =800; //窗口宽度  
const int WIN_HEIGHT    =600; //窗口高度  
//全局变量  
ALLEGRO_DISPLAY *display;     //显示设备  
ALLEGRO_EVENT_QUEUE *queue;   //事件队列  
ALLEGRO_EVENT my_event;       //事件  
  
ALLEGRO_BITMAP *bmp=0;  
  
////////////////////////////////////////////////////////////////////////////////////////////  
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd )  
{  
    int error=0;  
  
    //把游戏初始化的代码写在我们的 game_init()函数里  
    //然后放到这里执行  
    //把game_init()的返回值赋给error  
    //error如果为0的话表示一切正常,初始化成功了!  
    //如果不为0的话,表示初始化的时候,发生了意外。  
    //需要立即结束程序,并返回错误码  
    error=game_init();  
    if(error!=0)return error;  
      
  
    //初始化完成后,开始进入游戏的主循环,  
    //在主循环里将循环执行,消息处理,逻辑处理,和渲染函数  
    error=game_run();  
    if(error!=0)return error;  
      
  
    //游戏结束后,销毁所占用的资源  
    error=game_destory();  
    if(error!=0)return error;  
  
    return 0;  
}  
  
int game_init(){  
  
    if (!al_init())return 1;  
    /************************************************************************/  
    /*  使用al_init()来初始化Allegro系统
        al_init实际上是一个宏,他实际上调用了
        al_install_system(ALLEGRO_VERSION_INT,atexit)
        该函数的返回值是布尔型,初始化成功则返回true,否则返回false                                                                   */  
    /************************************************************************/  
  
  
    al_install_mouse();  
    al_install_keyboard();  
  
    al_init_image_addon();  
    /************************************************************************/  
    /* 初始化鼠标,和键盘设备,以便Allegro可以接收到鼠标和键盘消息                                                                     */  
    /************************************************************************/  
  
    //al_set_new_display_flags(ALLEGRO_FULLSCREEN);//如果取消掉本行注释就是全屏模式  
    display = al_create_display(WIN_WIDTH, WIN_HEIGHT);  
    if (!display)return 2;  
    bmp=al_load_bitmap("bmp.jpg");  
    if(!bmp)return 3;  
  
  
    /************************************************************************/  
     /*ALLEGRO_DISPALY *al_create_display(int w,int h)   创建显示设备
    参数 w 为要创建的窗口的宽度
    参悟 h 为窗口的高度
    成功则返回一个disply的指针,否则返回NULL
    /************************************************************************/  
    //设置Windows的标题  
    al_set_window_title(display, "2D游戏引擎Allegro 系列教程(三) 如何加载并显示图片!");  
  
    //初始化事件队列,接受到的消息将存储在该队列里  
    queue = al_create_event_queue();  
    //指定要接收哪个设备的消息  
    al_register_event_source(queue, al_get_keyboard_event_source());  
    al_register_event_source(queue, al_get_display_event_source(display));  
  
    return 0;  
}  
int game_msg(){  
  
    al_wait_for_event(queue,&my_event);  
    /************************************************************************/  
    /*  函数原型   
    void al_wait_for_event(ALLEGRO_EVENT_QUEUE *queue,ALLEGRO_EVENT *ret_event)
    等到队列里有新事件时,将新事件的内容复制到 ret_event里,并从事件队列里移除它
    */  
    /************************************************************************/  
    if(my_event.type==ALLEGRO_EVENT_DISPLAY_CLOSE)return 98; //当窗口被关闭时  
    if (my_event.type == ALLEGRO_EVENT_KEY_CHAR) {  
        if (my_event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)//当按下 ESC键时  
            return 99;  
    }  
    return 0;  
  
}  
  
int game_frame(){  
    return 0;  
}  
  
  
  
int game_render(){  
    //用指定的颜色填充屏幕  
    al_clear_to_color(al_map_rgb(0,0,0));  
    //翻转  
    al_draw_bitmap(bmp,0,0,0);  
    al_flip_display();  
    return 0;  
}  
  
  
  
int game_run(){  
  
    //下面的变量用来记录时间,单位是秒  
    //用以控制帧率(FPS),也就是每秒画面刷新多少帧,  
    //这里我们设FPS为30,用 1秒的时间单位/FPS     
    //也就是0.033,也就是说,每次刷新的间隔时间不能小于0.033秒  
    double t_now=0.0; //当前时刻  
    double t_pre=0.0;   
    int error=0;  
    while (true)   
    {  
        if(!al_is_event_queue_empty(queue)){ //先检测事件对了中是否有新事件  
  
            error =game_msg(); //有 则先处理事件  
            if(error!=0)return error;  
        }else{  
            //如果 事件队列中没有新事件 则  
            //计算事件间隔时候大于0.033  
            t_now=al_get_time();  
            if(t_now-t_pre>=0.033){  
  
                //如果时间间隔合适的话就  
                //更新一帧的游戏逻辑  
                error=game_frame();  
                if(error!=0)return error;  
                //刷新画面  
                error=game_render();  
                if(error!=0)return error;  
                t_pre=t_now;  
            }else{  
                //当CPU可以处理游戏逻辑的能力超过我们的需要时  
                //调用Sleep(0)  
                //这个Windows API 将使当前的线程释放出自己的控制权,  
                //这一点对Windows平台很重要,可以使游戏不至于占用全部  
                //的CPU,每次切换游戏的进程,都把可以用的时间片用完了  
                Sleep(0);  
            }  
        }  
  
    }  
    return 0;  
}  
  
  
int game_destory(){  
    al_destroy_bitmap(bmp);  
    return 0;  
}  




最新评论
暂无评论
参与评论

商务合作 查看更多

编辑推荐 查看更多
【爆款新游】【潜力佳作】分析系列
推广