首页 | 教程 | 人才 | 资源 | 视频 | 外包 | 培训 | 论坛  
游戏教程 美术基础 3D设计 平面软件 影视后期 建筑效果 网站设计 精选教程
 
网络学堂   2D美术   3D美术   游戏动作   次时代游戏   游戏策划   游戏程序   理论   其它
 您现在的位置:首页 > 教程频道 > 游戏教程 > 游戏程序
     深入WINDOW字型

深入WINDOW字型
编辑:大磊 发布时间:2009-05-12 查看:4947 次   
   文档简介:
  在探讨更深入的剧情处理以前,我们必须拥有输出文字的能力。这次我们的目标是撷取WINDOW系统资源,并且与DirectX
全萤幕游戏相结合,你将会学习到如何有效快速地将字型套用到你的游戏上面。

目录:
  
掌握正确方向
  WINDOW的字型
  取得字型资讯
  将字型设定给DC
  规画秀字的方式
  整合一下
  末语

文档内容:

掌握正确方向

  记得我曾经说过,在DOS下开发游戏,与WINDOW下的差别是很大的,曾经令人苦恼的问题,在WINDOW下都有更方便的解决方式,最明显的例子就是音乐播放,以及我们这次讨论的字型使用。在很多较老旧的游戏书籍里面,都会教你如何秀中文,比较常见的方法就是利用倚天中文的字型档。并且还需要利用文字索引的技巧,以节省记忆体空间。这一切都过去了,等等你会看到我们在WINDOW下面的实作方式。这边所谓「正确的方向」是指有效率的解决方式,当然早期的作法仍然可以适用于WINDOW环境。只是要额外付出许多代价就是了。

WINDOW的字型

  在中文的WINDOW里面,一安装完毕就会有许多字型可以套用,其中的中文字型至少有明体与标楷体,这些字型属于系统资源的一部份,任何应用程式皆可大方地使用。该如何使用呢?写过WIN32 APP的人大抵上都知道WINDOW API中,有一个字型对话方块,可以很方便的取的某个字型的资料,不过我不打算使用这个对话方块函示,实际上自己动手更有弹性,也不会浪费多少时间,以下开始实作。

取得字型资讯

  一个应用程式如果没有指定字型,则使用系统内定的字型。如果要使用标楷体字型的话,必须先取得此种字型的资讯,当然还可以指定字型的大小等等。打开字型对话方块,你会发觉字型的种类很多,但是我们需要的只有中文字型而已,所以我们忽略其他资讯,专注于我们需要的部份。这里我要强调的是,如果只强调秀出中文,你大可不必管他字型怎么来的(毕竟,我们的WINDOW环境本身就是中文的),使用内定字型即可,如果你还要强调系统字型的美观,就需要选择一种比较容易搭配的字型,更进一步如果要让使用者在游戏内自由选择系统任一种字型,则需要列举出所有可用的字型。并且将这些资讯收集起来,提供程式使用。

好的,我们先介绍如何列举出所有的系统字型,首先介绍这个函示:

int EnumFontFamilies(
    HDC
hdc,                        // handle to device control
    LPCTSTR lpszFamily,
            
// pointer to family-name string
    FONTENUMPROC lpEnumFontFamProc,
// pointer to callback function
    LPARAM lParam                   // address of application-supplied data
); //
取自VC线上说明

  这个函示需要的参数共有四个,第一个参数是绘图使用的设备代码,在一般应用程式,我们会使用GetDC()来取得他的设备代码,而在DirectX里面,我们必须使用IDirectDrawSurface3::GetDC(),由这个函示取得的DC才能保证与GDI的函示相容。第二个参数设定为NULL则会取得所有的字型,包括固定宽度字型与向量字型。第三个参数是一个CALLBACK函示指标,他的原型固定,系统会自动呼叫这个函示,而实作此函示的我们,正好可以将系统字型撷取下来,第四个参数用不到,设为NULL即可。

至于FONTENUMPROC的原型是这样子的:

int CALLBACK EnumFontFamProc(
    ENUMLOGFONT FAR* lpelf,
        
// pointer to logical-font data
    NEWTEXTMETRIC FAR* lpntm,     
 
// pointer to physical-font data
    int FontType,
                  // type of font
    LPARAM lParam                   // address of application-defined data
); // 取字VC 线上说明

这个函示的四个参数由系统传给我们,里面包含我们所需要的一切资讯,现在我们就看看实际上该如何使用,底下撷取自CFONT类别的实作内容:

//此成员函示呼叫以后,会开始取得系统字型

void CFont::QueryFont()
{
   
lpFrontBuffer->GetDC(&hdc);     //取得前景DC
    EnumFontFamilies(hdc, (LPCTSTR)NULL,(FONTENUMPROC) EnumFamCallBack,(LPARAM)NULL);
    lpFrontBuffer->ReleaseDC(hdc);  //释放DC
}

CFont::QueryFont()仅设定好初始的资料,真正接收字型资料的部份在CALLBACK函示,而CALLBACK函示我们应该怎么实作呢?底下便是:

首先我们配置三个结构以存放「细明体」「新细明体」与「标楷体」的字型资料, LOGFONT logfont[3];

这个结构可以存放字型的细部资料,其内容相当繁杂,且不是所有的资料都派上用场,更详细的资料可以在VC线上说明取得。需要的话,你可以配置更多的空间以存放各式各样的字型资料,这边我只示范三种常用字型。接著我们看一下该怎么在CALLBACK函示里面接收这些资料:

BOOL CALLBACK CFont::EnumFamCallBack(LPLOGFONT lplf,LPNEWTEXTMETRIC lpntm ,DWORD FontType,LPARAM aFontCount)
{
   
if(strcmp(lplf->lfFaceName,"细明体")==0)         //仅找明体与标楷体
       
memcpy(&logfont[0],lplf,sizeof(LOGFONT));    //资料存放到logfont[]阵列
   
if(strcmp(lplf->lfFaceName,"新细明体")==0)
       
memcpy(&logfont[1],lplf,sizeof(LOGFONT));
   
if(strcmp(lplf->lfFaceName,"标楷体")==0)
       
memcpy(&logfont[2],lplf,sizeof(LOGFONT));

    return TRUE;

}

刚刚有说到这个CALLBACK函示的四个参数是系统传给我们的,其中的LPLOGFONT包含了一种字型的资料,我们藉由判断其名称来决定这个字型是不是我们需要的,如果是的话,将他拷贝到我们预先配置好的LOGFONT结构里面。这个函示事实上会持续呼叫,直到找完所有的字型为止,所以在这个过程中,我们只接收三种字型的资料,其他的都忽略不处理。当这个函示完成以后,我们配置的LOGFONT[3]这个阵列里面,已经包含我们所需要的资料了。大事已经完成一半了,接著我们应该做什么事情呢?

将字型设定给DC

取得字型资料以后,实际上什么事情也没发生,我们必须根据字型的资料,来产生一个字型代码给API函示使用,这个处理过程我将他包在成员函示CFont::SetFont(HDC hdc,int FontType,int width,int height)里面,实作内容如下:

void CFont::SetFont(HDC hdc,int FontType,int width,int height)
{
    switch(FontType)
    {
        case MINGLIU:
            logfont[0].lfHeight=height;
            logfont[0].lfWidth=width;
            hFont = CreateFontIndirect (&logfont[0]);
            break;

        case NEWMINGLIU:
            logfont[1].lfHeight=height;
            logfont[1].lfWidth=width;
            hFont = CreateFontIndirect (&logfont[1]);
            break;

        case KAIU:
            logfont[2].lfHeight=height;
            logfont[2].lfWidth=width;
            hFont = CreateFontIndirect (&logfont[2]);
            break;
    }

    SelectObject(hdc,hFont);
}

这个成员函示接收四个参数,第一个参数是欲设定字型的目的DC,第二个参数决定要设定何种字型,第三第四个参数决定字型的大小。多方便阿,连字型大小都可以自由设定,不过还是要适中才会好看。所以实际呼叫的时候,我们是这样做的:

SetFont(hdc,NEWMINGLIU,10,15); //将前景DC与字型相结合

为了美观起见,我把三种字型另外定义其名称:

#define KAIU 5                 //标楷体
#define MINGLIU 6              //细明体
#define NEWMINGLIU 7           //新细明体

共2页 首页  上一页   [1] [2]    下一页  末页
相关文章:
本月教程排行
全部教程热点 全部推荐教程
· 老外的经典(少女贞德)从.
· Zbrush的行业应用之游戏篇.
· 3DMAX汽车三视图建立到使用.
· ZBrush3官方中文教程
· 3ds MAX基础教程:碗和杯子.
· MAYA材质教程:制作天鹅绒.
· 经典简单室内建模方法(新手.
· 用3ds max结合photoshop制.
· 【painter 8 手绘教程】《.
· Painter 8实例:时尚插画绘.
· Maya教程_3D制作足球模型教.
· 3ds MAX教程:室内空间夜景.
· 3D MAX教程:楼梯间的立体.
· 3dsMAX基础教程 直筒水杯的.
· 《山海经》奢比兽的制作
· PS 绘画 性感美女(国外)教.
· 美术基础--原画底稿上色篇.
· [分享]结构素描
· 贴图教程_PS滤镜快速制作草.
· 原动画运动规律基础教程(翻.
DOGAME游戏兵工厂 | 交流论坛 |关于我们| 广告联系 | 联系我们
DOGAME游戏兵工厂2009-2014HNYU GAME 京ICP备13045305号