热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

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

本系列文章由sky编写,转载请注明出处。http:blog.csdn.netqq573011406articledetails8263966作者:袁全伟邮箱:qq573011406

本系列文章由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:包含头文件


需要包含下列的头文件:
#include 
#include

Step 2:链接库


需要链接以下库:
#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类型的指针

ALLEGRO_FONT *fOnt=0;



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



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

Step 5:加载字体到ALLEGRO_FONT上


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


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




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



渲染文本的函数有以下几个:
渲染一个字符串
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) //要渲染的字符串


渲染一个格式化字符串.
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与文本的宽度相等的话,那么这个字符串会平铺这个区域.


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)


格式化....
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这个函数就可以了.
al_draw_text(font,al_map_rgb(255,0,0),0,0,0,"hello你好");




Step 7:释放占用的资源



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


eg:
al_destroy_font(font);



我们来看一下运行结果.




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

然而,却只显示了英文部分,“你好” 没有显示出来。
这是因为
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类型的指针

ALLEGRO_USTR *ustr;


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


ustr=al_ustr_new_from_utf16( (uint16_t*)L"你好!");


Step 3:渲染字符串

al_draw_ustr(font,al_map_rgb(255,255,255),100,100,0,ustr);

Step 4:结束时销毁字符串所占用的资源

al_ustr_free(ustr);


三:运行结果


五:完整源码
//头文件
#define ALLEGRO_NO_MAGIC_MAIN
#include
#include
#include
#include
#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_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;
}




推荐阅读
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 如何去除Win7快捷方式的箭头
    本文介绍了如何去除Win7快捷方式的箭头的方法,通过生成一个透明的ico图标并将其命名为Empty.ico,将图标复制到windows目录下,并导入注册表,即可去除箭头。这样做可以改善默认快捷方式的外观,提升桌面整洁度。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文是一位90后程序员分享的职业发展经验,从年薪3w到30w的薪资增长过程。文章回顾了自己的青春时光,包括与朋友一起玩DOTA的回忆,并附上了一段纪念DOTA青春的视频链接。作者还提到了一些与程序员相关的名词和团队,如Pis、蛛丝马迹、B神、LGD、EHOME等。通过分享自己的经验,作者希望能够给其他程序员提供一些职业发展的思路和启示。 ... [详细]
author-avatar
爱你无丶止境空间
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有