游戏程式设计指南(HoHo篇)

 

游戏程式设计指南(HoHo篇)Lesson 1 — 基础篇  

 



  游戏程式设计是令人向往而神秘的学科,其中涉及到非常广的程式技术,同时还需要对数理算法有相当的认识,可以说游戏程式设计是一条非常艰苦而漫长的道路,想象一下,几个昼夜的学习只不过为了一个小小功能的实现,或者整周时间被一个顽强的Bug所牵扯,如果你感到痛苦并无法忍受,那建议还是放弃学习游戏程式设计的想法,因为游戏程式设计是一项艰苦的工作。

  为什么要用HoHo游戏引擎?因为它已经帮你完成了很多琐碎但又不得不用的东西,比如:计算机图形设备的初始化、访问、绘制,当然还包括了声音、网络等一系列2D在线游戏所需要的基础功能;可能有些人要问,HoHo到底隐藏了哪些细节?或者说为什么不告诉我们这些技术如何实现?我只能告诉你,现在已经是21世纪了,团队的协作开发才是最为重要,你无论进哪家游戏公司或者加入某游戏团队,只要是有实力的游戏团体,他们都会有一套相应比较成熟的游戏引擎,可能你在参与到游戏开发中根本就不会去触碰到这些底层的技术细节,你所需要的就是知道怎么用,然后用它来实现游戏;当然,除非你的工作就是进行底层的研究,但实际上有80%的人员都是在进行游戏程式的设计,因为游戏本身的程式才是游戏最重要的组成部分,此文的目的就是希望能通过对HoHo游戏引擎的介绍,让读者能尽快的成为真正的“游戏程式”。

(以下HoHo游戏引擎简称为HoHo)

注:本文所讲述的操作在Window2000、Visual Studio.Net 2003 简体中文版、DirectX 9.0 SDK、HoHo4.1(动态库版)下测试通过。


目录:
   安装篇   非常基础的操作,如果你觉得你HoHo的安装给你带来困扰,那就先看看这里。
   创建篇   对Win32的应用程序不熟悉吗?对VC++.Net的工程管理不熟悉吗?如果是,那就来看看吧。



安装篇

  作为初学者,可能在安装的过程就存在着很多这样那样的问题,可能这些问题会困扰你很久;此章节的目的就是希望你能快速的将HoHo安装好,进入真正的游戏设计环节。

  下载了HoHo解压缩后可以看到有Include和Library的文件夹,不用多说,和Microsoft DirectX SDK一样,把它设置到我们的Visual C++.Net的编译器中,什么?你不知道如何设置?那么就看看下面,知道的话请直接掠过。
   

选择菜单

 

 

 

加入包含文件

 

 

 

设置包含库

 

 

  好了,这样就设置完毕,记得点确定把设置保存下来。




创建篇

  安装好了之后,我们要开始进行使用了,由于MFC的框架在某种程度上会比较麻烦,所以这里就以Win32(也就是Windows API方式)应用程序为框架,来进行HoHo的应用。什么?你又不会如何创建工程?那就继续往下看,会的人请略过此部分。

创建工程选项

 

 

  不用我多说了吧,点几下鼠标,填入工程名称,点击确定,好这样就可以了。

应用程序设置

 

 

  没什么好说了,直接点击完成,如果你有兴趣,可以点击“应用程序设置”看看。

创建完成

 

 

  这里需要说明一下,到这里后我们的应用程序可以说是创建完毕,你只要按下“F5”就可以让程序运行起来,当然,这个只是普通的Win32应用程序,Microsoft已经帮我们做好了一切处理,谢谢Microsoft吧! 待会我们就可以让这个程序变成我们所需要的工程,并且在将来我们的游戏就是要建立在这个工程的基础上。

  看到上面图里我表明了MyGame.cpp和stdafx.h这两个文件吧,这里我们来说明一下这两个文件到底是干什么的,MyGame.cpp这个文件相信你们也能猜得到,这个就是我们程序的主代码文件,里面有WinMain函数等一系列Windows应用程序所需要的信息,记住!我们的游戏也属于 Windows应用程序的行列;stdafx.h这个文件是工程的预处理文件,这个文件可是非常重要的,少了它你的工程就无法正常编译通过,它装载了你的程序所需要包含的库文件等一些需要预先处理并且属于整个工程的任何地方都需要用到的东西,哎!这个文件太重要了,一旦修改它,你整个工程就需要重新编译,所以建议一般就放一些不需要经常改动的引用包含。

  到目前为止,我们已经将Win32的应用程序给创建好了,让我们把HoHo真正的引入其中;打开stdafx.h文件,加入下面三句代码:

    #include "hCommon.h"                     // HoHo的通用包含头文件
    #include "hPlane2D.h"                    // HoHo的2D图像模块包含头文件
    #pragma comment(lib,"HoHo.lib")          // HoHo的连接库文件
 

图例

 

 

好了,我们已经完成第一步,是不是感觉很像在使用DirectX SDK?

  接下来就是开始对MyGame.cpp这个主要的代码文件做个手术,首先是初始化图形设备,找到一支叫 InitInstance() 的函数,在这支函数返回前,将我们的图形初始化代码给加进去,如图:
 

初始化2D图形设备

 

 

  接下来让我们修改一下这个应用程序的循环部分,让它的循环能够适应我们游戏循环的需要,找到 _tWinMain() 函数,不要问我为什么WinMain函数前面还有个_t,反正这支函数就是我们程序的入口,也就相当于是Dos下C语言的main()函数;好了,我们要大刀阔斧的修改者至函数的循环部分,最简单的方法就用把下面的代码段覆盖原有的循环代码,代码段如下:

    // 主消息循环:
    while ( 1 ) 
    {
        if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
        {
            if( !GetMessage( &msg, NULL, 0, 0 ) )
            {
                break;
            }
            TranslateMessage( &msg ); 
            DispatchMessage( &msg );
        }

        GetGraphics()->ClearScreenMMX(0); // 用黑色清屏

        GetGraphics()->UpdateScreen( );   // 更新屏幕缓冲
        GetGraphics()->Present( );        // DDraw更新屏幕
    }

 

修改程序循环部分

 

 

这里就是传说中的游戏循环部分,实际上游戏在执行当中就是不停的进行循环,不停的刷新屏幕,这也就有了FPS(刷新速度)的概念,评价一个图形引擎好坏经常用到的指标,也就是每秒钟这种刷新能达到多少次。

  好了,现在你按下“F7”来编译程序,对了,别忘记了,把下载HoHo包里的HoHo.DLL文件拷贝到你的游戏程序执行目录中,不要告诉我你找不到 VC工程所编译出来的执行文件放在哪个文件夹中,否则你的程序是运行不起来的,会告诉你缺少hoho.dll动态库文件。现在总算能够运行我们的程序了,按“F5”看看,我们可以看到我们的应用程序窗口变成黑色,并且左上角会有一个“FPS=XX”的绿色字样,如果你看到这些,那证明你已经完成了最基本的初始化工作了,是不是觉得很简单? :-)

游戏程式设计指南(HoHo篇)Lesson 2 — 完善篇  

显示/隐藏应用程序菜单

  在MyGame.cpp文件中,找到MyRegisterClass()这支函数,这支函数是用来向Windows注册应用程序窗口,里面的 WNDCLASSEX结构就是保存了用户所需要的注册信息,此信息关系到你以后应用程序的属性设置;我们这里希望将原应用程序的窗口菜单关闭,因为游戏窗口一般不需要应用程序的菜单选项,找到:
    wcex.lpszMenuName = (LPCTSTR)IDC_MYGAME;
  改成:
    wcex.lpszMenuName = NULL;
   

关闭程序菜单

 

 

这样就能关闭掉游戏程序的窗口菜单。



让窗口不会被改变大小

  如果我们的窗口被改变大小,那么我们游戏的显示大小将受到改变,这是我们不希望看到的,现在,只要我们将程序窗口设定为不可改变大小,那么这个问题就自然而然的解决了。让我们回头看看我们程序的创建窗口函数InitInstance(),在CreateWindow(...)这句里面有 WS_OVERLAPPEDWINDOW这样一个参数,此参数就是用来说明创建出来窗口的风格,只要把窗口改为WS_POPUP,那么就可以让我们的游戏程序窗口不会被改动,不要问我这些参数是什么意思,这些东西在MSDN上面有详细的介绍,虽然是英文的。
 

设置窗口风格

 

 



移动窗口响应处理

  有没有发现我们的游戏程序窗口在被移动的时候会出问题?没关系,只要我们在窗口程序的消息响应函数里加入一点处理就可以轻松解决,我们先来看看图:

 

消息响应处理

 

 

如图所示,我们在WndProc()中加入一个WM_MOVE的消息处理(关于消息可以查阅MSDN),此消息是通知你应用程序窗口被移动过,我们只要相应的做出一些处理,就能解决上面的问题;看看我们加入了什么:

    if( GetGraphics() != NULL)
        GetGraphics()->UpdateBounds();

其中UpdateBounds()函数是HoHo图形部分的更新位置函数,你不需要知道它如何工作,只要知道它能做到就行了。:)



检测窗口是否被激活

  有时候我们的游戏窗口被玩家最小化,如果这时候我们不停的绘制图像,那会消耗很多的无用资源,同时也给用户带来了不便,我们完全可以让我们的游戏在被最小化的时候安静下来,减少对CPU的占用率。好,让我们来看看如何实现。和上面移动窗口的处理一样,加入对窗口激活的消息响应,不过在加消息之前,我们需要为程序加一个全局标记变量,如下:

    bool g_bActive = true;
 

添加全局变量

 

 


  这里我们使用g_bActive来作为标记,如果这个变量值是真,那么当前窗口处于激活状态,否则就是没有激活,消息代码片断如下:

    case WM_ACTIVATE: // 窗口的活動狀態
    {
        switch((LOWORD(wParam)))
        {
            case WA_ACTIVE:
            case WA_CLICKACTIVE:
                g_bActive = true;
                break;
            case WA_INACTIVE:
                g_bActive = false;
                break;
            default:
                break;
        }

        if( GetGraphics() != NULL )
            GetGraphics()->Restore();
    }
    break;
 

窗口激活消息

 

 

这部分处理只是通过消息响应来为g_bActive进行状态的变化,同时会帮你进行DDraw设备的重建,当然,这部分HoHo已经为你做好了,你可以不用考虑这些。现在让我们回头来看看我们的游戏循环,我们需要做一些处理,让我们的程序在最小化(非激活状态)的时候节省点CPU资源,如图:
 

游戏循环

 

 

好了,经过这样的处理,已经可以达到我们的要求,可能有些朋友要问,为什么要加一个Sleep(1)的操作?这里是利用Sleep(1)来将应用程序的进程系统资源占用率返回给系统,你只要打开Windows自带的任务管理器就可以看出两者的差别。



让游戏程序进入全屏方式

  说了半天都是围绕着游戏程序窗口模式的操作,现在我们来考虑一下如何让我们的游戏程序进入全屏状态,真正的游戏状态。使用HoHo要进入全屏模式是相当容易的,还记得Lesson1里面的初始化部分吗?

    g_pDisplay = CreatePlane2D( hWnd, 800, 600, true );

  改为:

    g_pDisplay = CreatePlane2D( hWnd, 800, 600, false );

是很容易吧!我想应该不需要图例了。 :-)



善尾工作,释放数据

  让机器工作了那么久,应该让它休息一下了,我们程序的退出一定要记得把我们用到的东西还给系统,虽然现在的操作系统会帮你收回,但是保持一个良好的习惯还是非常重要的,现在看看如何把HoHo释放掉。
  找到_tWinMain()函数,或者说是主函数吧,只要在函数的结尾部分加入:

    SAFE_DELETE( g_pDisplay );

这样就行了,是不是很简单?执行了这部操作,HoHo会帮助你将所使用的DirectX设备,包括图像的数据资源都会自动释放。


  今天就写到这里,一个初具形态的游戏窗口已经基本上完成了,下一回我们要去了解如何载入并且绘制图像,让我们来美化游戏的面容。

游戏程式设计指南(HoHo篇)Lesson 3 — 图形加载篇  



  通过Lesson1和Lesson2的介绍说明,我们的游戏程序框架基本上已经具备了初步形态,同时也完成图形部分的初始化工作,接下来我们来了解一下利用HoHo引擎,游戏是如何将图像文件的数据装载到内存中;HoHo支持多种标准的图形格式文件,其中有:BMP、TGA、JPG,这三种格式概括了图形常用的三种类型,其中BMP格式是最为普通的类型,它不具备压缩能力,我们可以这样考虑,BMP就是一块平整的图形存储空间,图形数据被一莫一样的保存着;TGA文件与BMP类似,它同样不具备压缩能力,但它特殊的地方是具备图形的通道数据保存,通道数据可以制作出很多图形特效;JPG文件跟以上两种有比较大的区别,它的最大特点是支持压缩,而且压缩效率非常之高,缺点是它的图像压缩是有损失精度的,不过对于游戏中一些登入界面以及一些不需要很标准细微的图像还是有很广泛的应用范围。

注:现在新的BMP结构中也开始对32bit(带Alpha通道)的支持,HoHo引擎不对此类图形格式的支持。

HoHo所支持的图形格式:
  256色(8 Bit)的BMP格式图像。
  真彩色(24 Bit)的BMP格式图像。
  真彩色(24 Bit)的TGA格式图像,此格式的TGA不带Alpha通道数据。
  真彩色(32 Bit)的TGA格式图像,此格式的TGA自带Alpha通道数据。
  真彩色(24 Bit)的JPG格式图像。
以上图形格式均可以通过PhotoShop等一些标准作图软件制作。


目录:
   准备工作
   载入图像
    载入BMP
    载入TGA
    载入JPG
   绘制图像
   图像释放



准备工作

  在介绍如何载入图像资源之前,我们先来看看一个新手经常遇到的问题,那就是调试环境下程序的执行路径问题,在VC.Net的IDE编辑环境中直接用 F5来执行调试程序,这时候VC.Net并不知道你真正需要的路径在哪里,换句话说,就是可能会产生你的程序和你程序需要载入的数据路径不符合,这样就会导致你程序无法打开你所需要的文件,这时候,你就需要对工程的执行路径进行设置,具体如下:

   

打开工程属性页

 

 

然后在工作路径中填入所指定的路径:

修改工作路径

 

 

好了,这样就可以把工作路径设置好,接下来我们就看看如何通过HoHo来载入图形数据。



载入图像

  终于到了实质的部分了,前面一大部分都只是在介绍游戏程序的初始化还有一些所需要注意的细节,在这节中让我们来真正的从图形文件中载入图像数据,呵呵,实际上这部分是相当简单了,我们来看看载入图形数据的步骤:

  首先,我们需要声明图形指针句柄,不要问我为什么需要这个东西,多看看C++的书籍你就能够明白,如果你实在不明白,那你就跟着做就行,将来会明白的(但愿如此!)。我们看看下面代码段:

    LP_BITMAPX g_pBitmapBMP = NULL;
    LP_BITMAPX g_pBitmapTGA = NULL;
    LP_BITMAPX g_pBitmapJPG = NULL;

声明指针

 

 



这里我们定义了3个指针,LP_BITMAPX是HoHo内部定义的一个指针结构,这个东西包含了HoHo所需要的图形资源的数据;这3个指针是我们接下来要载入的三个图像的操作句柄;

  接下来我们来看看载入图形文件数据的代码片段:

    g_pBitmapJPG = GetGraphics()->CreateBitmapFromJPG( "background.jpg" );
    g_pBitmapTGA = GetGraphics()->CreateBitmapFromTGA( "tree.tga" );
    g_pBitmapBMP = GetGraphics()->CreateBitmapFromBMP( "character.bmp" );

载入图形数据

 

 


这里分别用了三支不同的函数来进行载入数据,分别是:

  用来载入JPG图形各式的  CreateBitmapFromJPG()  注1
  用来载入TGA图形各式的  CreateBitmapFromTGA() 
  用来载入BMP图形各式的  CreateBitmapFromBMP()

这三支函数对应了3种不同格式的图形文件进行了支持,其中TGA格式会自动识别图像本身是否带Alpha通道数据,如果有,在LP_BITMAPX结构中会保存Alpha通道数据,以供将来使用,如果没有,则保存为普通的图形数据方式;另外,BMP格式会自动识别256色图形的数据,并且自动将其转换为 16Bit的内部管理色彩数据。

  怎么样?很容易吧,具体如何实现图形数据载入的问题就留给HoHo来帮你解决。 :)



绘制图像

  数据载入完成了,让我们来把它们Show一下,看看是否达到我们的要求。

  我们在以前已经建立好了游戏的循环体,我们现在只要把我们的显示图像的代码放入循环中,游戏程序就会为你不停的刷新游戏窗口,当然,它的刷新内容就是你所指定的图像了。让我们来看看代码片段:

    GetGraphics()->DrawBitmapMMX( 0, 0, g_pBitmapJPG, SCREENBUFFER );
    GetGraphics()->DrawBitmapMMX( 100, 100, g_pBitmapBMP, SCREENBUFFER );
    GetGraphics()->DrawBitmapAlphaChannelMMX( 300, 300, g_pBitmapTGA, SCREENBUFFER );

显示图像

 

 

这里我们使用了三句代码来进行图像绘制,前两句是使用普通的绘制方法来进行图像绘制,最后一句是让HoHo根据图像的Alpha通道数据来绘制那个图像,这里我们不介绍绘制函数的具体操作,我们会在Lesson4进行全面的了解,这里只是为了展示你所载入的图形文件。

  代码加入后,让我们来编译运行一下游戏程序,怎么样?是否如你所愿?下图是附带的例子工程运行截图。


(图像资源来源于  金点时空   的《圣剑英雄传II》)

有没有看到我们的树闪闪发光?嘿嘿!这个就是Alpha通道数据给我们带来的图像效果,是不是像一些游戏中经常可以看到的光影效果。具体如何实现这些,我们下回再讲!



图像释放

  图形文件载入完了,也显示出来了,有一点需要我们紧记,创建了数据用完之后,把数据空间还给操作系统,养成良好的习惯是非常有用的,这里我们来看看HoHo如何释放数据:

  ……

怎么?没有代码了?呵呵,放心,还记得前面有讲过HoHo的释放,实际上HoHo在图形设备被Delete的时候,会自动将自己所用过的图像数据释放,这点HoHo已经帮你完成了,不过可能有些用户会说,我不想等HoHo的图形设备被释放后才释放图像数据,我想我游戏一边运行一边释放不需要的数据,那好,我们来看看下面的例子代码:

    GetGraphics()->RemoveBitmap( g_pBitmapJPG );

只要通过这句,就能简单的将g_pBitmapJPG这个图像数据给释放。


  好了,又到了结束时间,可能有些朋友会留下一个疑问,为什么总是要使用" GetGraphics()-> "?我可以告诉你,这个函数可以获得HoHo的图像指针句柄,当然,前提是你已经初始化完成了,这个函数是全局的,有了这支函数,不管你游戏如何构架,只要呼叫这支函数,就能立即获得图像的操作权,这样可以给我们的游戏开发带来便利。:)

游戏程式设计指南(HoHo篇)Lesson 4 — 图形绘制篇  



  这节讲述的是HoHo的2D模块最重要的功能,不用我多说,这就是HoHo的图像绘制部分,相信没人会否认图像绘制对于游戏的重要性,基本上游戏给玩家的表述多是用图像来说明,HoHo提供了多种多样的图像绘制方式,同时在性能方面也有相当的表现。

  一般在游戏中常用的绘图方式有4种:普通绘制、颜色键(ColorKey)绘制、Alpha混合绘制、色彩饱和(Additive)绘制,其中普通绘制和颜色键(ColorKey)绘制在DirectDraw中就有支持,Alpha和Additive则需要我们自己进行运算处理(这里Alpha混合绘制和色彩饱和(Additive)绘制简称为Alpha和Additive),不过没关系,这些运算以及处理工作HoHo已经为你完成,你需要知道的就只是如何去使用。


目录:
   普通绘制
   颜色键(ColorKey)绘制
   Alpha混合绘制
   色彩饱和(Additive)绘制
   图像RECT裁减绘制



普通绘制

   普通绘图非常简单,只要是HoHo载入的图像数据都可以用来直接普通绘制,普通绘制就是将图像原貌反映在屏幕上,只用通过以下简单的一句代码就可以完成,代码片段:

    GetGraphics()->DrawBitmapMMX( 100, 100, g_pBitmapBMP, SCREENBUFFER );
   

普通绘制

 

 

这样就行了,是不是很简单?这里还需要说明一下SCREENBUFFER的功能目的,SCREENBUFFER实际上也就是一个LP_BITMAPX数据,只不过它比较特殊,它被HoHo默认创建,并且作为与DirectDraw接口进行图像数据更新的一个通讯图像数据,我们只需要知道把图像绘制到它上面就OK了。

  可能有人会问,我们这里的绘制是从g_pBitmapBMP到SCREENBUFFER,我们能否倒置?答案是肯定的,如果你把他们的位置倒换,那么就变成SCREENBUFFER的数据被绘制到g_pBitmapBMP中,除了SCREENBUFFER外,只要是常规的LP_BITMAPX数据结构都可以进行此项操作,有些特殊的LP_BITMAPX结构是无法互通数据,这里我们留着后面再来介绍,将图像绘制出来是此节的主要讨论内容。



颜色键(ColorKey)绘制

  游戏中不可能所有的图像都是整块并且标准的四边形图像,比如游戏中的人物(精灵),它们在图形文件中所存储的数据如下:

人物(精灵)原图

 

 

如果我们按照普通绘制的方法,那么非人物(精灵)的图像数据部分也会被绘制到屏幕上,令人厌恶的紫色色块也会进入我们的游戏视野,我们来看看如何将这些紫色部分去掉,不要让它来影响我们游戏的视觉效果。(通常我们不需要的颜色称之为颜色键(ColorKey))

  HoHo中可以直接进行ColorKey的过滤处理,不过在HoHo对图像绘制进行ColorKey过滤的时候,我们必须事先通知HoHo,什么颜色是ColorKey,看看如下代码片段:

    g_pBitmapBMP->SetColorKey( RGB2Hi(255,0,255) );

设置ColorKey

 

 

这里我们用到了两支函数,其中SetColorKey()就不用多说了,它就是用来设置LP_BITMAPX的ColorKey,它需要的是一个 PIXEL结构的数值,PIXEL是一个16Bit的数值,不要问我为什么是16Bit,我只能回答你,因为我们的游戏是在16Bit模式下运行的;另外,让我们看看RGB2Hi(),这是一支HoHo提供的全局函数,功能是将RGB颜色值转换为上面我们所说的16Bit的PIXEL数据,这里我们用 RGB=255,0,255(紫色)来作为ColorKey的设置参数。

  再我们进行图像绘制之前,我需要说明一下,HoHo内部默认的ColorKey是RGB=0,0,0,可能有人会反对这样的做法,毕竟RGB= 0,0,0就是黑色,黑色在游戏图像中出现的几率还是相当频繁,用黑色岂不是很不方便,用RGB=255,0,255来作为默认ColorKey不更好?我只能说请相信我,我这样做肯定有其好处,虽然这个好处未必明显;在SetColorKey()函数执行后,原来LP_BITMAPX的图像数据中的黑色 (RGB=0,0,0)部分均会被假黑色代替(RGB=0,0,1),所以上面我们设置紫色为ColorKey,HoHo会将原图像中的紫色部分改变为黑色,而原来的黑色部分会被修正为假黑色。(如果你不明白这段文字所说的问题,请掠过此段继续看后面)

  说了那么久,在我们设置好ColorKey之后,我们可以同样通过DrawBitmapMMX()函数来进行ColorKey处理的图像绘制,代码示例如下:

    GetGraphics()->DrawBitmapMMX( 250, 100, g_pBitmapBMP, SCREENBUFFER, true );

ColorKey图像绘制

 

 

在这里我们只是简单的在函数后面加了一个true标记,此标记告诉HoHo,此图像要进行ColorKey处理。



Alpha混合绘制

  前面两种绘制方式是游戏中最基本的应用,现在我们来看看Alpha混合如何处理,Alpha混合处理可以给游戏带来非常多的特效以及更好的视觉效果,在 HoHo中,Alpha混合的算法以及优化等工作都已经帮你完成,你所需要的就是简单的调用函数就可以轻松实现Alpha的混合处理,我们来看看一下的代码片段:

    GetGraphics()->DrawBitmapAlphaMMX( 400, 100, g_pBitmapBMP, SCREENBUFFER, 16 );

Alpha混合绘制

 

 

我们看看它最后的一个参数,16这个数值是通知HoHo进行16阶Alpha混合,这个参数的取值范围为0~32,16相当于是50%的混合;为什么取值范围那么小?为什么不是0~255?这是因为我们所用的图形模式是16Bit色彩,它所变换出来的色彩表现能力实际上最后只能得到0~32级的变化。

注意:Alpha混合操作的函数会自动进行ColorKey的过滤处理。


  说到Alpha混合绘制,这里还需要介绍一下Alpha通道混合处理,HoHo支持的TGA图形Alpha通道数据,并且可以根据通道数据来进行处理,可能有些朋友对Alpha通道图不是很了解,这里我们简单的说说Alpha通道的作用。

  上面说的DrawBitmapAlphaMMX()可以对图像进行Alpha混合处理,但是有些时候我们需要的是图像的局部Alpha混合,或者是一张图片中不同的区域有不同的混合方法,如果这样的话,上面这支函数就无法达到,这时候就需要借助Alpha通道数据来协助图像的绘制。

  在Lesson3中,我们载入了一张TGA带通道的图像数据,这里我们可以通过以下方法来进行绘制,代码片段如下:

    GetGraphics()->DrawBitmapAlphaChannelMMX( 300, 300, g_pBitmapTGA, SCREENBUFFER );

Alpha通道混合绘制

 

 

这样我们就可以把图像数据中的通道数据应用起来。

  还有一种情况,我们需要对带有Alpha通道的图像在加入Alpha值的处理,这时候只要在最末尾处加入一个Alpha混合值就行,就如同DrawBitmapAlphaMMX()的使用。




色彩饱和(Additive)绘制

  现在的游戏里面到处都是光影特效,比如武士飞舞大刀所带的刀光、法师施展的绚丽魔法等,这些都可以通过色彩饱和运算来实现,我们必须先来了解一下色彩饱和的处理方式,色彩饱和是将两张图像的数据融合起来,如果图像是黑色,则两张图像融合后还是原来的图像,当然,这样说可能不是很明了,可以看看本章节最后的附图,不过在看附图之前,我们来看看代码的实现:

    GetGraphics()->DrawBitmapAdditiveMMX( 550, 100, g_pBitmapBMP, SCREENBUFFER );

色彩饱和(Additive)混合

 

 

由于色彩饱和混合的特殊性,它不需要进行ColorKey处理,也不需要Alpha值的参数,就如普通绘图一样。



图像RECT裁减绘制

  有时候我们载入了一张很大的图像,但我们在绘制过程中,我们只需要绘制其中的某个小区域,如果我们整张图进行绘制,那么将是极大的浪费资源,HoHo 已经为你准备了这方面的处理;用过DirectDraw表面绘图的朋友肯定知道DDraw在绘图的时候需要一个RECT参数来进行绘制区域的确定操作,同样,你也可以传入一个RECT结构参数来确定你所需要的绘制区域,看看一下代码片段:

    RECT rect = { 0, 0, 32, 48 };

    GetGraphics()->DrawBitmapMMX( 700, 100, g_pBitmapBMP, SCREENBUFFER, &rect );
    GetGraphics()->DrawBitmapMMX( 750, 100, g_pBitmapBMP, SCREENBUFFER, &rect, true );
    GetGraphics()->DrawBitmapAlphaMMX( 700, 160, g_pBitmapBMP, SCREENBUFFER, &rect, 16 );
    GetGraphics()->DrawBitmapAdditiveMMX( 750, 160, g_pBitmapBMP, SCREENBUFFER, &rect );

RECT裁减绘制

 

 

这里我们制定绘制g_pBitmapBMP图像中的起点(0,0)至终点(32,48)位置的图像,仔细看,这些绘制函数不就是我们上面所介绍的函数,没错,在HoHo中有这些函数的重载操作,只要是第五个参数传入了RECT结构数据,那么HoHo就会根据RECT所制定的位置来进行绘制,当然,具体要进行如何的绘制方法就如同原函数的效果。



最后,我们看看今天的游戏程序运行结果:


(图像资源来源于  金点时空   的《圣剑英雄传II》)

游戏程式设计指南(HoHo篇)Lesson 5 — 字体绘制篇  



图像作为游戏的主要输出途径,其中不可或缺的就是文字,不管是作为游戏中使用,或者作为我们程式的调试手段,文字的输出表示是相当重要的,本节就是要给大家介绍如何在HoHo游戏程序中绘制文字;HoHo为大家提供了两种绘制方式,一种是通过Windows的GDI来进行文字绘制,另外一种则是通过 HoHo自己的处理方式来进行文字绘制,当然,HoHo自处理的方式在性能方面比GDI的处理方式高出许多,同时,HoHo也提供了一个字体生成器,可以很方面的制作我们有戏当中所需要的字体格式。

注:HoHo的自处理字体目前只支持等宽高的字体。


目录:
使用GDI绘制文字
使用HoHo自处理文字
HoHo字体生成器使用



使用GDI绘制文字

首先,我们来看看如何使用Windows的GDI来进行文字绘制,大家都知道,Windows为我们提供了强大的文字绘制功能,很幸运的是, DirectDraw继承了这些,在DirectDraw的表面(Surfce)可以看作一个可供系统GDI绘制的缓存,当然,这里我们不会深入说明如何处理,HoHo已经把这些东西封装好了,好了,让我们来看看如何使用。

第一步初始化,不用多说,声明操作句柄,代码片断如下:

HFONT g_hFont = NULL;

声明GDI字体句柄

 

声明完之后,我们必须对它进行初始化操作,我们通过调用系统API函数来进行Windows字体句柄创建,代码片断如下:

g_hFont = CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "宋体");

初始化GDI字体

 

我们可以看到,这里我们创建了一个12点阵的字体大小,当然,这些复杂的参数在MSDN可以查询到,这部分数据Windows的操作部分,我们不对此进行深入说明,有兴趣的朋友请参看MSDN。

创建好GDI字体后,我们可以通过调用HoHo的图形函数DrawText()来进行字体绘制,代码示例如下:

GetGraphics()->DrawText( SCREENBUFFER, 30, 30, g_hFont, "GDI字体 Test 测试", RGB2Hi(255,255,255) );

绘制GDI字体

 

这样就能完成GDI字体的绘制工作,很easy吧!:)

补充说一下,由于GDI字体绘制的机制与HoHo有所差别,故此函数在实际应用中操作比较消耗速度性能。



使用HoHo自处理文字

接下来让我们看看HoHo自处理字体的使用,为什么要使用HoHo的自处理字体?因为它能够给你带来绘制效率,同时可以给你带来字体的附加效果,如:字体的边缘Alpha混合等。

HoHo字体的初始化和GDI字体一样,我们首先声明操作句柄,代码片段如下:

LP_FONT g_pHoHoFont = NULL;

HoHo字体声明

 

声明完后,我们一样进行字体设备的创建,不过不同于GDI的是,HoHo字体是从自己的字体库文件中提取出来,而并非来源于Windows系统,这样就能有效的避免不同Windows导致的字体错乱情况,这个情况在繁体版本和简体版本的Windows中尤为明显。让我们看看创建HoHo字体的代码片段:

g_pHoHoFont = msCreateFont( "Font12.dat" );

HoHo字体的创建

 

就这么简单的一句就能将字体从字库文件中创建出来,接下来我们看看如何绘制,代码片段如下:

GetGraphics()->DrawFont( SCREENBUFFER, 30, 60, g_pHoHoFont, RGB2Hi(255,255,255), "HOHO字体 Test 测试" );

HoHo字体绘制

 

看看,是不是和GDI的字体绘制方式类似,问题就那么简单。

我们看看我们程序的执行结果:



看到HoHo字体还带着轮廓线了吗?这个就是HoHo自处理字体的功能,只要字库保存了轮廓线数据,我们的字体就能进行轮廓线绘制,当然还能进行轮廓Alpha处理,这里我简要的说明下一一些关于HoHo自处理字体的参数,看看字体的结构:

struct HOHO_API tagFont
{
    int nStyle;                    // 字体风格
    int nWidth, nHeight;           // 字体宽高
    int nASCIIWidth;               // ASCII宽
    int nASCIISize;                // ASCII码的Size
    int nGBSize;                   // GB码的Size
    BYTE* pFontData;               // 汉字起始地址
    BYTE* pASCIIData;              // ASCII起始地址
    char strFontName[32];          // 字体文件名
    long lType;                    // 字体类型
    int nLength;                   // 字体文件长度
    int nSpace;                    //  字间距
    int nAlpha;                    //  是否使用Alpha混合
    int nAlphaLevel;               //  混合程度
    int nAlphaEdge;                //  是否使用Alpha边缘混合
    int nAlphaEdgeLevel;           //  边缘混合程度
    unsigned short pixelEdgeColor; //  边缘线色彩
};

typedef tagFont* LP_FONT;

这个就是HoHo的字体数据结构,其中红色注释部分为用户可修改部分,只要进行相应的修改,则HoHo会根据修改的内容进行绘制,同时,也可以通过其他的数据来了解当前字体的宽高等信息。

对了,游戏程序结束前记得对HoHo自处理字体进行释放,代码片断如下:

msReleaseFont( g_pHoHoFont );



HoHo字体生成器使用

上面介绍了HoHo字体的使用,那么我们如何创建我们所需要的字体呢?很简单,HoHo已经为你准备好了字体制作工具,只要轻轻的点击几下鼠标就能搞定,看看字体转换工具的界面:



只要选择好所需要的字体,然后选择字体大小,最后点一下保存即可,如果把“轮廓线”的复选框选上,则会在创建的自体上添加轮廓线。

此工具附带源码,可以在HoHo的包中Tools文件夹里找到,有兴趣的朋友可以研究一下。

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值