游戏开发论坛

 找回密码
 立即注册
搜索
查看: 6586|回复: 0

2D游戏引擎Allegro 系列教程(四) 文字渲染及显示汉字的

[复制链接]

7867

主题

7909

帖子

1万

积分

论坛元老

Rank: 8Rank: 8

积分
19358
发表于 2012-12-11 14:24:00 | 显示全部楼层 |阅读模式
本系列文章由sky编写,转载请注明出处。

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

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

本系列教程索引:

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


一:介绍

Allegro渲染文字有两个方式,使用位图字体文件或者ttf字体文件。这里主要讲一下TTF。
TTF:
allegro使用freetype库来加载字体文件并提取字模,然后将其渲染出来。这也是比较常用的一种方法。这个方法支持如 TrueType, OpenType, Type1, CID, CFF, Windows FON/FNT, X11 PCF 等各种常用的字体文件。
在windows中字体文件被存放在"C:\Windows\Fonts\" 目录里


二:渲染文本的流程


Step 1:包含头文件
Step 2:链接库
Step 3:声明一个ALLEGRO_FONT类型的指针
Step 4:初始化ttf插件
Step 5:加载字体到ALLEGRO_FONT上
Step 6:将文本渲染到屏幕上
Step 7:释放占用的资源

三:步骤

Step 1:包含头文件

需要包含下列的头文件:
[cpp] view plaincopy
#include <allegro5/allegro_font.h>  
#include <allegro5/allegro_ttf.h>  

Step 2:链接库

需要链接以下库:
[cpp] view plaincopy
#pragma comment(lib,"allegro_font-5.0.7-mt-debug.lib")   
#pragma comment(lib,"allegro_ttf-5.0.7-mt-debug.lib")   

Step 3:声明一个ALLEGRO_FONT类型的指针
[cpp] view plaincopy
ALLEGRO_FONT *font=0;  



Step 4:初始化font插件和ttf插件


使用下面这两个函数可以分别初始化FONT 插件和TTF插件,TTF插件用来载入各种类型的字体文件
[cpp] view plaincopy
al_init_font_addon();  
al_init_ttf_addon();  

Step 5:加载字体到ALLEGRO_FONT上

[cpp] view plaincopy
ALLEGRO_FONT *al_load_font(  
            char const *filename   //字体文件地址  
            , int size             //字体文件的大小  
            , int flags)           //ALLEGRO_TTF_NO_KERNING 不使用字距调整  
                   //ALLEGRO_TTF_MONOCHROME 不使用抗锯齿  


[cpp] view plaincopy
ALLEGRO_FONT *al_load_font(  
            char const *filename   //字体文件地址  
            , int size             //字体文件的大小  
            , int flags)           //ALLEGRO_TTF_NO_KERNING 不使用字距调整  
                   //ALLEGRO_TTF_MONOCHROME 不使用抗锯齿  




Step 6:将文本渲染到屏幕上


渲染文本的函数有以下几个:
渲染一个字符串
[cpp] view plaincopy
void al_draw_text(const ALLEGRO_FONT *font,//字体指针  
         ALLEGRO_COLOR color      //颜色 可使用al_map_rgb(255,0,0) 这个函数获取颜色  
        , float x, float y        //把文本渲染到什么位置  
        ,int flags       //文本的对齐方式可以为0或以下值ALLEGRO_ALIGN_LEFT 左对齐(默认)ALLEGRO_ALIGN_CENTRE 居中对齐  
                        //ALLEGRO_ALIGN_RIGH 右对齐  
        , char const *text)    //要渲染的字符串  


渲染一个格式化字符串.
[cpp] view plaincopy
void al_draw_textf(const ALLEGRO_FONT *font, ALLEGRO_COLOR color,  
   float x, float y, int flags,  
   const char *format, ...)  


下面这个函数的功能跟al_draw_text差不多,只不过是把文本限定在了一个区域里.
其中 diff差数是指文本中各个单词的间距,如果diff与文本的宽度相等的话,那么这个字符串会平铺这个区域.


[cpp] view plaincopy
void al_draw_justified_text(const ALLEGRO_FONT *font,  
   ALLEGRO_COLOR color, float x1, float x2,  
   float y, float diff, int flags, const char *text)  


格式化....
[cpp] view plaincopy
void al_draw_justified_textf(const ALLEGRO_FONT *f,  
   ALLEGRO_COLOR color, float x1, float x2, float y,  
   float diff, int flags, const char *format, ...)  




做为例子我们就使用al_draw_text这个函数就可以了.
[cpp] view plaincopy
al_draw_text(font,al_map_rgb(255,0,0),0,0,0,"hello你好");  




Step 7:释放占用的资源


可以使用下面这个函数释放字体所占用的资源
[cpp] view plaincopy
void al_destroy_font(ALLEGRO_FONT *f)  


eg:
[cpp] view plaincopy
al_destroy_font(font);  



我们来看一下运行结果.





很奇怪吧,本来我们要渲染的字符串是
[cpp] view plaincopy
al_draw_text(font,al_map_rgb(255,0,0),0,0,0,"hello你好");  

然而,却只显示了英文部分,“你好” 没有显示出来。
这是因为
[cpp] view plaincopy
al_draw_text()  

这个函数,支持的字符串编码为UTF-8,而我们写在程序源文件(.cpp)里的字符串,会被VS自动转换为与系统环境一样的编码方式,所以这里只能显示中文,而中文显示不来。
要显示中文的话另有方法。

四:Allegro 5如何显示中文

显示中文的话主要有两种方法:

一是把字符串存储在一个文本文件里并把这个文本文件另存为UTF-8类型的。然后用程序加载这个字符串,然后再显示出来。。
但是这个方法太麻烦了,这里我们主要介绍另外一种方法。

即使用UTF-16,也就是wchar_t 类型的字符串。

在allegro里专门有一个库是用来出来UTF字符串的。

我们先来看一下使用这个库的步骤

一:步骤

Step 1:声明一个指向ALLEGRO_USTR类型的指针
Step 2:创建一个UTF-16的字符串
Step 3:渲染字符串
Step 4:结束时销毁字符串所占用的资源

二:实施

Step 1:声明一个指向ALLEGRO_USTR类型的指针
[cpp] view plaincopy
ALLEGRO_USTR *ustr;  


Step 2:创建一个UTF-16的字符串

[cpp] view plaincopy
ustr=al_ustr_new_from_utf16( (uint16_t*)L"你好!");  


Step 3:渲染字符串
[cpp] view plaincopy
al_draw_ustr(font,al_map_rgb(255,255,255),100,100,0,ustr);  

Step 4:结束时销毁字符串所占用的资源
[cpp] view plaincopy
al_ustr_free(ustr);  


三:运行结果





五:完整源码
[cpp] view plaincopy
//头文件  
#define ALLEGRO_NO_MAGIC_MAIN  
#include <Windows.h>  
#include <allegro5/allegro.h>  
#include <allegro5/allegro_font.h>  
#include <allegro5/allegro_ttf.h>  
#pragma comment(lib,"allegro-5.0.7-mt-debug.lib") //链接Allegro的库  
#pragma comment(lib,"allegro_font-5.0.7-mt-debug.lib") //链接Allegro的库  
#pragma comment(lib,"allegro_ttf-5.0.7-mt-debug.lib") //链接Allegro的库  
////////////////////////////////////////////////////////////////////////////////////////////  
  
  
  
  
//函数  
int game_init();    //初始化游戏  
int game_run();     //进入游戏循环  
int game_frame();   //逻辑处理函数  
int game_render();  //渲染函数  
int game_distory(); //释放资源  
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_FONT *font=0;  
ALLEGRO_USTR *ustr;  
  
  
  
  
////////////////////////////////////////////////////////////////////////////////////////////  
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_distory();  
    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_init_font_addon();  
    al_init_ttf_addon();  
    al_install_mouse();  
    al_install_keyboard();  
    /************************************************************************/  
    /* 初始化鼠标,和键盘设备,以便Allegro可以接收到鼠标和键盘消息                                                                     */  
    /************************************************************************/  
  
  
  
  
    //al_set_new_display_flags(ALLEGRO_FULLSCREEN);//如果取消掉本行注释就是全屏模式  
    display = al_create_display(WIN_WIDTH, WIN_HEIGHT);  
    if (!display)return 2;  
    /************************************************************************/  
     /*ALLEGRO_DISPALY *al_create_display(int w,int h)   创建显示设备
    参数 w 为要创建的窗口的宽度
    参悟 h 为窗口的高度
    成功则返回一个disply的指针,否则返回NULL
    /************************************************************************/  
    //设置Windows的标题  
    al_set_window_title(display, "Allrgro系列教程(四) 显示文字");  
  
  
  
  
    //初始化事件队列,接受到的消息将存储在该队列里  
    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));  
  
  
  
  
    font=al_load_ttf_font("simfang.ttf",24,1);  
    if(!font)return 3;  
    ustr=al_ustr_new_from_utf16( (uint16_t*)L"你好!");  
    if(!ustr)return 4;  
  
  
  
  
    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_text(font,al_map_rgb(255,0,0),0,0,0,"hello你好");  
    al_draw_ustr(font,al_map_rgb(255,255,255),100,100,0,ustr);  
    //翻转  
    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,每次切换游戏的进程,都把可以用的时间片用完了  
                al_rest(0);  
            }  
        }  
  
  
  
  
    }  
    return 0;  
}  
  
  
  
  
  
  
  
  
int game_distory(){  
    al_destroy_font(font);  
    al_ustr_free(ustr);  
    return 0;  
}  


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-5-16 17:24

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表