游戏编程文章搜集资料.docx

上传人:b****7 文档编号:23655957 上传时间:2023-05-19 格式:DOCX 页数:65 大小:289.03KB
下载 相关 举报
游戏编程文章搜集资料.docx_第1页
第1页 / 共65页
游戏编程文章搜集资料.docx_第2页
第2页 / 共65页
游戏编程文章搜集资料.docx_第3页
第3页 / 共65页
游戏编程文章搜集资料.docx_第4页
第4页 / 共65页
游戏编程文章搜集资料.docx_第5页
第5页 / 共65页
点击查看更多>>
下载资源
资源描述

游戏编程文章搜集资料.docx

《游戏编程文章搜集资料.docx》由会员分享,可在线阅读,更多相关《游戏编程文章搜集资料.docx(65页珍藏版)》请在冰豆网上搜索。

游戏编程文章搜集资料.docx

游戏编程文章搜集资料

游戏编程文章搜集资料

游戏开发—图形图像篇

游戏开发--开篇

  记得我第一次玩的PCgame是KKND(绝地风暴),当时的游戏平台是DOS,我只是觉得很好玩,经常和几个小学同学一起厮杀到12点。

可是现在回忆起来,KKND无论是从智能设计还是在游戏画面与操作上都是非常出色的。

他的音效同样是很棒的,而且全中文配音让当时很多不懂英语的玩家找到了许多的亲切感。

这真是一款很棒的游戏。

Itisgreat!

  我想,这样的感觉是许多游戏开发者或者梦想成为游戏开发者的人们所共同经历的感受。

一款好游戏会带给人们很多东西,会带给社会很多东西。

在人的层面上,无论是"大富翁"让我们娱乐,还是"文明"让我们感受科技发展带来的成果与思考,在我们玩一个游戏的时候,我们读到的故事,经历的坎坷,解决的问题,无时无刻不在让我们感受着游戏之外的很多东西。

在社会的层面上,游戏产业就本身而言,市场不断扩大,需求不断增多;更重要的是,他带动了出版、通信等相关产业的迅猛增长。

游戏与相关产业增长的比值有时甚至是1:

100。

现在看看韩国政府对于游戏产业的支持,就有"醉翁之意不在酒"的感觉了。

  中国的游戏产业将在2005年左右达到10美元的市场,我们国人绝不应放弃这个发展的大好机会。

其实,我们可以看到现在有很多的游戏公司,看起来像是一片欣欣向荣、蓬勃发展的场面,但是这里面又有多少是搞游戏开发的呢?

是少之又少。

很多公司都是代理国外的游戏,这样一来,国外很多的游戏开发厂商获得了大量的利润,而我们在为小蛋糕争得你死我活时,别人已经各自享用着自己的大餐了。

资金不足无疑是各个公司搞游戏代理的最主要理由。

但是我们可以看到,像CS这样成功的GarageGame,我们为什么做不出来?

答案很多,问题很多,我们要做的事情很多。

于是,本着从我做起的原则,还是应该不断以提高自身的能力为主。

毕竟我们和外国走的路不同,我们要找到适合自己的发展道路,走出一条具有中国特色的产业发展路线。

当然,在路上我们还要不断的学习。

  所以,在我学习游戏开发的过程中,看到了我们中国学生的很多文章,有很多都是很有水平的。

于是自己也提起笔来,把自己学习的经验和心得写下来,和大家一起讨论和提高。

这一系列的文章主要是面向想学习游戏开发的朋友,文章是从实际开发源代码的角度去介绍游戏开发的各个方面(文章中的示例代码用C++编写),但是瓦文章并不是完全地教学,更像是一个游戏开发的学习索引。

它告诉初学者,做什么游戏需要什么技术,指引他们去学习某项技术,从而真正回归到自己学习的乐趣中来,为最终游戏的设计和实现奠定基础。

游戏开发--图形图像篇

(一)

一个游戏的好坏谁说了算?

  玩家。

  玩家如何看一个游戏?

  用眼睛。

  那么这款游戏怎么样?

  "画面真棒!

"

  ……

  你的游戏做得再好,如果没有一个很好的图形效果,那展现在玩家眼前的东西将大打折扣。

而且,你的游戏也不会得到很好的支持。

为什么呢?

因为你的游戏无需使用很好的显示设备和图形加速设备,硬件厂商不会理睬你的游戏。

这也就和开篇所说的"游戏促进相关产业的发展"的职责相悖了。

所以,在写一个游戏之前,想一想开发这个游戏需要什么技能,"磨刀不误砍柴工"。

让我们开始吧,先学一学游戏的图形开发。

一.Windows绘图接口

1.GDI/GDI+

在开始前先让我们看一个具体的例子。

 

这个小程序的图形显示部分就是用GDI编写的。

  我们在编写Windows应用程序的时候,经常会用到GDI/GDI+(GraghicDeiceInterface,图形设备接口)。

GDI是Windows早期版本中包括的图形设备接口,而GDI+是GDI的改进版本,对GDI的现存性能进行了优化,而且增加了很多新性能。

GDI/GDI+的结构如下图:

GDI+的C++接口中包括大约40个类、50个枚举和6个结构。

听起来虽然不多,但是这也足够胜任大多数应用了。

  GDI编写程序的优点是他基本上兼容所有的显示设备,但是这是以损失效率为代价的。

通常,编写应用程序时,大多数桌面应用程序用到的只是相对稳定的图形图像显示,所以在这种情况下,使用GDI是很实用的。

可是,在开发对图形图像显示速度要求非常高的游戏程序时,GDI就显得不够强劲了。

所以,我们把开发游戏的图形图像显示部分的重担交给了下面就要介绍的DirectX。

GDI学习参考:

《WindowsProgramWithMFC》中的GDI部分。

2.DirectX

  谈到DirectX或许你不会陌生,因为像很多大名鼎鼎的FPS游戏都是用它来开发的。

这其中有Valve小组的HalfLife及其衍生作品--CS。

所以,DirectX已经成为了游戏开发所不可或缺的重要组成部分。

还是先让我们看一个小程序。

[programMovePicturev0.3]

DirectDraw与DirectInput的游戏编程体验

我想关于这个主题的文章,不算少,但也不算太多。

但大多是分别介绍DirectDraw与DirectInput,而并没有将其结合起来,也许你会问:

“分开与合并起来并没有本质区别啊!

”。

其实的确没有本质区别,但那样使那些最初对游戏编程报有极大热情的爱好者感到非常失望,因为这其中的一个并不能完全满足他们的要求,并且使其感到巨大的阻力,从而失去信心。

所以本文将DirectDraw与DirectInput结合起来去讲一个主题就是“游戏编程”,请注意是“游戏编程”,当然这只是一个简单的桌面游戏,但这已经与先前有很大的不同了,这已不是简单的DirectDraw或DirectInput编程。

我想你现在应该能够体会出其中的区别了。

  声明:

在这之前需要你具有一定的WIN32API函数的知识,并且可以熟练使用。

和DirectDraw的知识,关于DirectDraw可以参见中的<<动画程序编写——DirectDraw之旅>>1-3),或其它文章。

最后是c++语言,当然也要包括面向对象的那部分。

在VisualC++.NET编译环境下进行开发的。

  首先,我们还是先简要复习一下DirectDraw的概念吧!

DirectDraw本质上是显存管理程序。

它最重要的性能是允许程序员直接在显存里存储和操纵位图。

它使你能够利用视频硬件bliter(位块传输器)在显存内部进行位图的blit(位块传输)。

用视频硬件的blitter从显存向显存进行blit比从内存向显存更快。

这在64位显卡向显存提供64位数据路径的今天显得尤其重要,硬件独立于促CPU进行位块传输操作,使得CPU得以继续工作。

另外DirectDraw支持显卡的其他硬件加速特性,例如对精灵和z-buffering的硬件支持。

DirectDraw的工作原理

我们这里还是用图表方式展现给大家吧!

  细心的朋友可以很明显地注意到图示中的右上角的图解中说明,表面对象有两个宽度,一个是WIDTH,一个是PITCH。

WIDTH就是创建表面时所给出的那个宽度,而PITCH是表面的实际宽度,是按字节算的。

在许多显卡上,PITCH和WIDTH是相等的,比如在640x480的高彩模式下,PITCH为1280。

而在某些显卡上,PITCH比WIDTH要大。

比如在640x480的256色模式下,当WIDTH是640时,PITCH为1024而不是640,这些显卡这样做是为了更好地进行数据对齐来提高性能或达到其它目的。

所以,我们在实际编程时,为了保证程序的兼容性,必须按PITCH处理。

但这些硬件的底层问题,我们不用太关心,只要稍有了解就可以了。

下面我们再简要叙述一下,如何使用DirectX9.0中提供的DirectDraw类库来创建对象并使用操作对象。

宏定义在先,定义删除指针和释放对象的宏

#defineSAFE_DELETE(p){if(p){delete(p);(p)=NULL;}}

#defineSAFE_RELEASE(p){if(p){(p)->Release();(p)=NULL;}}

先创建一个CDisplay的全局对象

CDisplay就是ddutil.h中定义的类,用于处理表面之间的拷贝翻页等操作的类,再次定义一个全局变量,用于以后对指向的表面之间进行操作

CDisplay*g_pDisplay=NULL;

然后创建表面,当然可以创建很多的表面,这些表面都是离屏表面,在更新画面时,都可以用CDisplay类的对象中的方法,将其拷贝到后备缓冲区表面上。

只要创建离屏表面,就要用到CSurface类。

CSurface也是ddutil.h头文件中定义的类,用于对表面本身进行操作,如设置色彩键码,在此定义的图画指针。

 

CSurface*g_pBackSurface=NULL;

DirectX中就一共用这两个类封装了DirectDraw对象的大部分操作,如果你觉得这还不能满足要求,那么你也可以在程序中用DirectDrawAPI函数编写程序,不过在本文中不再介绍。

这之后,我们会用到InitDirectDraw函数。

这个函数是我们自己创建的。

在此函数中作所有的DirectDraw的对象初始化工作。

HRESULTInitDirectDraw(HWNDhWnd)

{

     HRESULThr;//接受返回值,其实是long型变量

     LPDIRECTDRAWPALETTEpDDPal=NULL;//定义程序中的调色板

     intiSprite;//定义与sprite个数有关的计数器

     g_pDisplay=newCDisplay();//动态开辟一个CDisplay类

     if(FAILED(hr=g_pDisplay->CreateFullScreenDisplay(hWnd,SCREEN_WIDTH,

           SCREEN_HEIGHT,SCREEN_BPP)))/*设置程序为全屏,并且g_pDisplay就是动态开辟一个CDisplay类的指针,而在这个类的域中,有一个DirectDraw主表面指针,和一个后备缓冲区表面的指针。

在从我建议你可以先去阅读一下ddutil.h和ddutil.cpp文件。

*/

     {

           MessageBox(hWnd,TEXT("Thisdisplaycarddoesnotsupport1024x768x8."),

                 TEXT("DirectDrawSample"),MB_ICONERROR|MB_OK);

           returnhr;

     }

     if(FAILED(hr=g_pDisplay->CreatePaletteFromBitmap(&pDDPal,MAKEINTRESOURCE(IDB_DIRECTX))))//顾名思义,就是从bmp图片中获得调色板值,并赋值在pDDPal结构指针所指向的结构体中。

           returnhr;

     if(FAILED(hr=g_pDisplay->SetPalette(pDDPal)))//用刚才从IDB_DIRECTX中获得的调色板制来设置程序调色板

           returnhr;

     SAFE_RELEASE(pDDPal);//释放指针,在用过后,一定要释放,这是良好的编程习惯

      //用IDB_WINXP图片创建一个表面,并用g_pBackSurface指向这个表面

     if(FAILED(hr=g_pDisplay->CreateSurfaceFromBitmap(      &g_pBackSurface,MAKEINTRESOURCE(IDB_WINXP),

      SCREEN_WIDTH,SCREEN_HEIGHT)))

           returnhr;//设置色彩键码为黑色,0代表黑色,这样在表面的拷贝过程中黑色像素的点将不会被拷贝,这样可以产生镂空效果。

当然你可以任意设置关键颜色,而颜色的表示法可以用RGB宏定义。

例如红色:

RGB(255,0,0),黑色RGB(255,255,255)

      if(FAILED(hr=g_pBackSurface->SetColorKey(RGB(255,255,255))))

           returnhr;

     returnS_OK;

}

下面的函数是用于更新画面的。

 

HRESULTDisplayFrame()

{

     HRESULThr;

     g_pDisplay->Clear(0);//清空后备缓冲区表面

     //将g_pBackSurface所指向的图片拷贝到后备缓冲区表面

      g_pDisplay->Blt(0,0,g_pBackSurface,NULL);//最关键的地方在这里,请看下面的语句,只要我们一执行翻页操作,就可以将改动了的图像了显示在屏幕上了

     if(FAILED(hr=g_pDisplay->Present()/*翻页操作*/))

           returnhr;

     returnS_OK;

}

下面的函数是用于在程序失去焦点时调用的。

HRESULTRestoreSurfaces()

{

     HRESULThr;

     LPDIRECTDRAWPALETTEpDDPal=NULL;/*当程序失去焦点,要保存当前的画面,请注意这里,g_pDisplay->GetDirectDraw()函数返回的才是真正的DirectDraw对象*/

     if(FAILED(hr=g_pDisplay->GetDirectDraw()->RestoreAllSurfaces()))

           returnhr;//在此我们还要重新创建调色板

     if(FAILED(hr=g_pDisplay->CreatePaletteFromBitmap(&pDDPal,MAKEINTRESOURCE(IDB_DIRECTX))))

           returnhr;//重新设置调色板

     if(FAILED(hr=g_pDisplay->SetPalette(pDDPal)))

           returnhr;

     SAFE_RELEASE(pDDPal);//重新画出图画

     if(FAILED(hr=g_pLogoSurface->DrawBitmap(MAKEINTRESOURCE(IDB_WINXP),

SPRITE_DIAMETER,SPRITE_DIAMETER)))

           returnhr;

     returnS_OK;

}

下面这个函数是释放表面指针所用的。

VOIDFreeDirectDraw()

{

      SAFE_DELETE(g_pBackSurface);

      SAFE_DELETE(g_pDisplay);

}

我们的回顾到此结束,下面我们开始本文要介绍的一个关键技术,DirectInput的使用。

游戏编程可不仅仅是图形程序的开发工作,实际上包含了许多方面,本文所要讲述的就是关于如何使用DirectInput来对键盘编程的问题。

而我们为什么要选择用DirectInput来处理游戏中的输入问题呢?

其实用Win32API函数也完全可以处理这些工作,例如其中,有一个

GetAsyncKeyState()的函数可以返回一个指定键的当前状态是按下还是松开。

这个函数还能返回该指定键在上次调用GetAsyncKeyState()函数以后,是否被按下过。

虽然这个函数听上去很不错,但需要我们自己轮换查询每个键盘的状态。

而在DirectInput中我们已经可以脱离这些烦琐的工作,只因它的功能更强大。

由于本文重点在二者的结合,故在此只介绍DirectInput中比较简单的,而且最容易上手的立即模式的工作方式。

而这里我们要用到DirectInput的API函数。

有人会问,为什么在DirectDraw中用DirectX提供的类库编程,而对于DirectInput却直接使用要用其API函数呢,是因为没有提供DirectInput的类库吗?

不是!

而是因为使用类库并不很方便而且不灵活。

OK,让我们开始我们游戏编程的第二部——DirectInput编程。

前面讲DirectDraw时,并没有提到,微软是按COM来设计DirectX的,所以就有了一个DIRECTINPUT对象来表示输入设备,而某个具体的设备由DIRECTINPUTDEVICE对象来表示。

也许会感到很无奈,怎么游戏编程需要这么多的知识啊,其实您也无需烦恼,只要知道一下就可以了,其实这并不;影响您的设计,而且就算您不知道,也同样可以驾驭DIRECTINPUT。

实际的建立过程是先创建一个DIRECTINPUT对象,然后在通过此对象的CreateDevice方法来创建DIRECTINPUTDEVICE对象。

#include

#defineDINPUT_BUFFERSIZE16

LPDIRECTINPUTlpDirectInput;//DirectInput对象实际上是一个com对象

LPDIRECTINPUTDEVICElpKeyboard;//DirectInput设备

BOOLInitDInput(HWNDhWnd)

{

      HRESULThr;//创建一个DIRECTINPUT对象

     if(FAILED(hr=DirectInputCreate(hInstanceCopy,DIRECTINPUT_VERSION,&lpDirectInput,NULL)))

     {//失败提示或处理

       returnhr;

      }//创建一个DIRECTINPUTDEVICE界面

//参数GUID_SysKeyboard指明了建立的是键盘对象

      if(FAILED(hr=lpDirectInput->CreateDevice(GUID_SysKeyboard,&lpKeyboard,NULL)))

      {

            //失败提示或处理

            returnhr;

       }//设定为通过一个256字节的数组返回查询状态值

      if(FAILED(hr=lpKeyboard->SetDataFormat(&c_dfDIKeyboard)))

      {

      //失败提示或处理

            returnhr;

      }//设定协作模式为独占模式和前台模式,独占模式表面本程序在运行中占有所有键盘资源,而前台模式指出当程序具有焦点时才可以占有键盘资源

      if(FAILED(hr=lpKeyboard->SetCooperativeLevel(hWnd,DISCL_EXCLUSIVE|DISCL_FOREGROUND)))

      {

      //失败提示或处理

            returnhr;

      }

      //设定缓冲区大小

      //如果不设定,缓冲区大小默认值为0,程序就只能按立即模式工作

      //如果要用缓冲模式工作,必须使缓冲区大小超过0

      //在此,我们没有必要设定,因为我们就用立即模式工作(还有一种缓冲模式),所有我们将其注调了

      /*DIPROPDWORDproperty;

      property.diph.dwSize=sizeof(DIPROPDWORD);

      property.diph.dwHeaderSize=sizeof(DIPROPHEADER);

      property.diph.dwObj=0;

      property.diph.dwHow=DIPH_DEVICE;

      property.dwData=DINPUT_BUFFERSIZE;

      if(FAILED(hr=lpKeyboard->SetProperty(DIPROP_BUFFERSIZE,&property.diph)))

      {

      //失败

            returnFALSE;

      }

      */

      //此处是关键,我们要通过这个函数来锁定键盘,记住,所有的DirectInput资源在使用前都要锁定,在此即获得键盘资源,在知识我们刚才设定的键盘模式才能起作用

      hr=lpKeyboard->Acquire();

      ifFAILED(hr)

      {

            //失败

            returnFALSE;

      }

      returnTRUE;

      }

在这段代码中,我们首先定义了lpDirectInput和lpKeyboard两个指针,前者指向DIRECTINPUT对象,后者指向一个

DIRECTINPUTDEVICE界面。

其顺序就是这样的。

这和其它COM对象的使用方法都一样,即先创建COM对象,然后创建界面,然后再获得

硬件资源,然后使用资源,然后释放。

通过DirectInputCreate(),我们为lpDirectInput创建了一个DIRECTINPUT对象。

然后我们调用CreateDevice来建立一个DIRECTINPUTDEVICE界面。

  

完成这些工作以后,我们便调用DIRECTINPUTDEVICE对象的Acquire方法来激活对设备的访问权限。

在此要特别说明一点,任何一个

DIRECTINPUT设备,如果未经Acquire,是无法进行访问的。

还有,当系统切换到别的进程时,必须用Unacquire方法来释放访问权限,在系统切换回本进程时再调用Acquire来重新获得访问权限。

立即模式的数据查询

HRESULTReadImmediateData(HWNDhWnd)

{

      HRESULThr;

      BYTEdiks[256];//创建键盘状态数据缓冲区存取键盘信息

      inti;//计数器

      if(NULL==g_pKeybo

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1