现在的位置: 首页 > 综合 > 正文

《Windows游戏编程》读书笔记

2013年07月09日 ⁄ 综合 ⁄ 共 9632字 ⁄ 字号 评论关闭

  • 窗口的定义,注册,创建,显示流程。事件处理器,即WinProcLRESULT CALLBACK WindowProc(窗口句柄,消息标识,左参数,右参数)。WM_PAINT:对于DirectX可以30-60帧/秒重画窗口,但对于Windows程序就切力了。

基本windows应用程序框架

主事件循环:

while(GetMessage(&msg, NULL, 0, 0))  { 
  TranslateMessage(&msg);  //虚拟加速键翻译器,输入工具
  DispatchMessage(&msg); //调用WinProc()
}

截屏(2011-08-28 10_03_21).jpg

 主程序入口:定义窗口类→注册窗口→创建窗口→主事件循环;且每个Windows程序都有独立的事件句柄WinProc

 

一个实时事件循环:加入测试消息队列机制,PeekMessage(),使用PM_REMOVE

 

对应同一个窗口类的多个窗口的消息

截屏(2011-08-28 10_22_11).jpg

截屏(2011-08-28 10_45_54).jpg

     动态加载菜单资源。在加载资源时,需要注意字符串形式还是符号常量MAKEINTRESOURCE()
      传入的消息,wparam从技术安全考虑取低位LODWORD(wparam)
 
      在屏幕上渲染是编写一个视频游戏最重要的部分。一般Windows程序用GDI,GDI+,而DirectX则是更专业的DirectDraw,Direct3D
截屏(2011-08-29 10_20_36).jpg 
使用GetDc()函数总可以获得一个窗口的图像描述表hdc
GetDC()-ReleaseDc()→BeginPaint()-EndPaint()  vs ValidateRect()
区别Windows Coords和Client Coords
手动使一个窗口无效:InvalidateRect()
图形&色彩术语
      像素Pixel
      分辨率Resolution
      色深Color depth
      隔行扫描/逐行扫描Interlaced/noninterlaced
      刷新速率Refresh rate (用Hz或fps表示)
      2D/3D加速 2D/3D acceleration
颜色查找表的工作原理
窗口事件
       输出文本:TextOut(Coords); DrawText(Area)
       不透明和透明(SetBkMode)的打印模式
        WM_PAINT,改变窗口大小,移动等情况下产生
键盘事件 →DirectInput
       Win32库,GetAsynKeyState()跟踪状态表中该键的最后已知状态(好处:可跟事件循环无关)
鼠标事件
自我传递消息
       PostMessage() 传递消息序列,异步
       SendMessage() 直接传消息,同步

      

第四章_WindowsGDI,控件和突发奇想     
     >图形设备描述表
             当访问一个图形设备描述表或句柄时,实际上就表示安装在计算机系统上的视频卡具体描述及其分辨率和色彩容量
     >色彩、画笔和画刷
             GDI一般一次只使用一个画笔和一个画刷
     >使用画笔
             创建CreatePen(), 获取默认GetStockObject()
             将任何GDI对象选择到图形设备描述表SelectObject(), 用完DeleteObject()
     >使用画刷
             GDI画刷为2类:纯色的和阴影的←MS愚蠢的规定(?)
             创建纯色填充画刷CreateSoildBrush()
             ....带阴影线的.........CreateHatchBrush()
     >直接绘点 SetPixel()
     >绘制线条 MoveToEx(), LineTo()
   >绘制矩形 Rectangle()
             填充矩形 FillRect()
             右边界的中空矩形FrameRect()
       **对于任何一个实例,必须都要一个窗口hWnd,HDC
      >绘制椭圆 Ellipse()
      >绘制多边形 Polygon()
      >字体 CreateFont()
      >WM_TIMER
            设置定时器 SetTimer,GetTickCount() 一般30fps
      >碰撞逻辑
     > 使用控件
      > 获取消息   GetSystemInfo()  SYSTEM_INFO结构指针
                          GetSystemMetrics()  通用的检索Windows和Desktop所有信息
                          GetTextMetrics()  检索文本规格函数
      > 一个字符的构成  《VC++技术内幕》p75
      > T3D游戏控制程序

 

第五章_ DirectX基础和COM 

> COM  所有的DirectX组件都是由COM构成的
     > HEL(硬件模拟层) 硬件不支持时用软件算法模拟出硬件功能,效率降低,但至少能实现
         HAL(硬件抽象层) 硬件支持需要的性能
     >DirectX基础类v6.0
        DirectDraw:控制视频显示的基本着色和2D图形引擎
        DirectSound:声音组件
        DirectSound3D:3D声音组件
        DirectMusic
        DirectInput:所有输入设备
        DirectPlay:网络方面内容
        Direct3DRM:Direct3D保留模式(用途:编写预排程序,模拟显示,速度极慢的演示)
Direct3DIM:Direct3D即时模式
   DirectSetup/AutoPlay:准DirectX组件
> COM升级的便利性
          COM对象:实际上就是实现大量界面的一个C++类或一套C++类
          COM对象的分布或包含,如何实现即插即用特性
      > GUID(全局单值标识符),或称IID(界面标识符) ← 可以利用微软的GUIDGEN.EXE生成
      > 创建COM
                 1,定义界面: struct  IGraphics : IUnknown {  }
                 2,创建界面容器类(核心) class COM_OBJECT : public  IGraphics, ISound, IInput {  }
      > DLL才是COM对象
      > COM和函数指针
           原型:int (*SetPixel) (int x, int y, int color);
                     int SetPixel_ATI (int x, int y, int color);
                     int SetPixel_VOODOO (int x, int y, int color);
                     int SetPixel_SIII (int x, int y, int color);
                     SetPixel = SetPixel_ATI ; // assigning a function pointer
           C++和虚函数都是建立在函数指针的基础上的,虚函数只是被很好地内置到了编程语言中,加强了功能,实际上就是这么一回事
     > 创建和使用DirectX接口 
        理解COM对象其实就是接口集,该接口集也就是函数指针(VTABLE)
          用DirectX COM对象来工作,只要创建COM对象,获得一个接口指针,然后正确调用该接口即可。
                1,安装SDK时,安装程序会自动对DLL进行装载并注册
                2,Win32 App中必须包含DDRAW.LIB
                3,#include “DDRAW.H”
        本质上讲,任何DirectX的调用都采用的方式: interface_pointer -> method_name (parameter list);
    > 接口查询
               所有的DirectX各个版本里的号码都是不同步的! (命名混乱
               确保使用最新版本的接口:1使用底层COM函数; 2使用QueryInterface()函数
                      LPDIRECTDRAW lpdd;   // version1.0
                      LPDIRECTDRAW lpdd7;  //version7.0
                      DircectDrawCreate(NULL, &lpdd, NULL);  // create version 1.0 DirectDraw object interface
                      lpdd->QueryInterface(IID_IDirectDraw7, &lpdd7); //find IDIRECTDRAW7 interface ID and use it to query for the interface
                      lpdd->Release();  
                      lpdd = NULL;
               
                      DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL);
    > COM / COM++ / DCOM

 

第六章_初次邂逅DirectDraw

>DirectDraw接口
             IUnknown 基本接口
             IDirectDraw 必须创建的主接口对象,支持MMS
             IDirectDrawSurface 用DirectDraw创建,控制和显示的实际显示表面
             IDirectDrawPalette 
             IDirectDrawClipper 帮助剪切DirectDraw光栅和位图操作到一些可见显示表面的子集

     > 组合使用接口

             1,创建主DirectDraw对象,并使用QueryInterface()来得到一个IDirectDraw7接口,或直接DirectDrawCreateEx()创建
             2,IDirectDrawSurface7接口至少创建一个主显示表面用以绘图
             3,IDirectDrawPalette接口创建一个调色板,用RGB三元组初始化并配置到相关显示表面中
             4,至少需要创建一个剪裁器并将尺寸设置为可见窗口的范围
             5,主显示表面上绘图
     > 创建DirectDraw对象 (昨天的内容)
     > DirectDraw的错误处理
              2个宏:FAILED() SUCCEEDED() 一般使用前者
   > DirectDrawCreateEx(NULL,(void**)&lpdd,IDD_IDirectDraw7,NULL);
      > 视频显示设备:
                 全屏模式(容易),直接写到视频设备里。没有其他应用程序能接触到该设备
                 窗口模式(更难掌握),其他应用程序的介入
      >设置DirectDraw的协作级别,IDirectDraw7::SetCooperativeLevel()
> 创建一个显示画面
                  屏幕上所显示的图像只不过是内存的某种形式,调色板或RGB彩色像素矩阵
                  1,写一个DDSURFACEDESC2数据结构
                  2,调用CreateSurface()
      > 选用调色板 SetPalette()
      > 绘图像素
                 所有DirectDraw视频模式和画面都是线性的,内存从上到下,从左到右线性增加
      > 锁定
                或解锁显存,顺序很重要 ::Lock()
      > 屏幕上绘制随机像素的全部过程
                1,// first create base IDirectDraw 7.0 interface
                     DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL);
                2, lpdd->SetCooperativeLevel // set the cooperative level for full-screen mode
                3,  lpdd->SetDisplayMode  // set the display mode   
                4,memset(&ddsd,0,sizeof(ddsd));
                     ddsd.dwSize = sizeof(ddsd); // clear ddsd and set size
                     ddsd.dwFlags = DDSD_CAPS; 
                     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
                5,lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL);// create the primary surface
                6,// build up the palette data array,fill in entry 0 and 255 with black and white
                7,lpdd->CreatePalette// create the palette object
                8,lpddsprimary->SetPalette// finally attach the palette to the primary surface
                9,lpddsprimary->Lock
                10,//TODO
                11,lpddsprimary->Unlock(NULL);// now unlock the primary surface
 

第七章_高级DirectDraw和位图图形

    IDIRECTDRAWSURFACE7::Blt()

    IDIRECTDRAWSURFACE7::BltFast()  需要剪裁时用前者,不需要时用后者

    基础裁剪知识(像素裁剪、位图裁剪),3D裁剪将会十分复杂

        像素按视口裁剪

        位图裁剪技巧

    使用IDirectDrawClipper进行DirectDraw裁剪

        步骤1,创建DirectDraw裁剪器对象,CreateClipper()

            2, 创建Clipper序列 //最麻烦,需要填写RGNDATA结构

            3,用IDIRECTDRAWCLIPPER::SetClipList

            4,用IDIRECTDRAWSURFACE7::SetClipper

    使用位图

        载入.bmp文件 (位图头文件,位图信息段(有调色板的话),位图数据段)

        载入8bit位图 SetEntries

        载入16bit位图 (24bit转16bit)

        载入24bit位图

    离屏表面

        创建的表面跟主表面是兼容的,具有一致的色深


    在离屏表面上进行blitting

      装载位图,创建表面,使用blitting

    色彩键

      源色彩键 DDCOLORKEY Object优先于background

      目标色彩键,方法跟源色彩键相同SetColorKey,需要改变2个标志位

      源叠加色彩键

      目标叠加色彩键


    如何更新DirectDraw调色板项

    256色模式下的色彩旋转(Color Roation)

       模拟水或液体的流动效果

    使用RGB模式的技巧

       1,利用手动色彩变换或查询表

       2,采用新的DirectX彩色和Gamma补偿,实时地在主表面上执行色彩操作


    手动色彩变换及查询表

       透明·alpha混合·光照·暗化处理

    DirectX新的色彩和Gamma控制接口

       IDirectDrawColorControl可以控制高度,对比度,色调,饱和度,锐度和Gamma值

       各种效果:如水下感觉,屏幕闪烁,灯光,黑暗

    将GDI和DirectX联用

       只需在DirectDraw中找到一个兼容DC

       在独占模式下,Windows不能够用GDI在任何DirectDraw表面绘制

    主DirectDraw对象

       GetCaps获得HEL,HAL,用于获取任意表面能力

       GetPixelFormat或GetSurfaceDesc结构DDSURFACEDESC2::ddpfPixelFormat

    在窗口模式下使用DirectDraw

       必须考虑使用者可能在任意分辨率和任意色彩深度模式下启动游戏

    在窗口中绘制像素

       1,主表面是整个屏幕,GetWindowRect()实际上获得的是整个窗口

       2,不知道色深,GetPixelFormat()以决定色彩的深度

    查找实际客户区

       AdjustWindowRectEx 计算不同样式的窗口尺寸

    剪裁DirectX窗口

       裁剪只对blitter起作用

       CreateClipper()

       SetHWnd() 将裁剪器同窗口相关联

       SetCClipper() 裁剪器同想要裁剪的表面相连

    本章总结:

              高彩模式,blitter,裁剪,彩色键,采样理论,窗口方式的DirectDraw



第八章_矢量光栅化及2D变换

   绘制线条

     问题1,计算机屏幕是一个由整数坐标表示的2D网格,如何显示浮点型坐标

     Bresenham算法

     解决实际问题:把像素以最接近实际直线的位置从点p1到点p2进行填充的这个过程成为光栅化。

               1,计算斜率K

               2,画点(x0,y0)

               3, 在x方向上每前进1.0个单位,在y方向上就前进K个单位,把这两个值加到(x0,y0)上

   基础2D图形裁剪知识

     图像空间级(像素级)裁剪,对象空间级裁剪

     两直线之交点

       利用矩阵式求逆阵

     裁剪直线

     Cohen-Sntherland算法

       判断线段跟矩形(剪裁区域)的情况

   线框多边形

     在游戏中,集中注意一件事,那就是速度!

     为了画多边形,所要做的就是对顶点循环,并连接点与点


   2D平面里的变换

     平移

     旋转(计算机中sin、cos采用弧度而不是角度)

     坐标变换很像极坐标向笛卡尔坐标的转变

     旋转时,逆时针θ为正,顺时针θ为负。在显示屏上,y轴是相反方向,正负也相反

     实时程序中使用三角函数很糟糕,需要建立一个查询表,将算好的0-360度的sin、cos值保存在查询表内

     关于精度,选择int还是float还是double

     缩放,每个坐标乘以缩放因子

     矩阵引论

       基础的矩阵知识已经在《3D数学基础》内补完,这里学起来就异常轻松了。

       使用矩阵进行各种变换(平移,缩放,旋转)

    

   填充实心多边形

     第一个约束条件,多边形必须为凸多边形

     第二个约束条件,确定所要画的多边形到底有多复杂


            

   绘制三角形和四边形

     每个端点变成整数之前加0.5

   四边形光栅化的一般情况

   多边形的三角化

     递归分割思想

     通用凸N边形渲染算法


   多边形碰撞检测

     边界球/圆

       对象具有一个平均半径,然后检测半径是否重叠(会有漏判)

       开方函数sqrt会消耗大量CPU周期,想办法优化

         1,只计算一次float差

         2,泰勒级数展开

     边界盒、边界箱

       Find_Bounding_Box_Poly2D

     点包含

       测试一个点是否被包含在一个矩形内部

       ↓如何判断一个点是否被包含在任意凸多边形之内

       半空间检测(Halfspace Test)需要运用到向量点积

   

   深入定时和同步

     基于Win32函数GetTickCount()

   卷轴和摇镜头

     页面卷轴Page Scrolling

     均匀平铺显示引擎

       采用基于tile的数据结构表示场景卷动

     稀疏位图平铺显示引擎(适合太空射击游戏)

     伪3D等轴测引擎

       等轴测Isometric,即采用一定倾斜视角的游戏

       方法一,基于单元,全2D

       方法二,基于全屏,具有一些2D或3D的碰撞网络

       方法三,采用全3D数学运算,使用一个固定的视角

         采用工具画碰撞对象非常消耗时间,且对画面的任何变动都意味着返工


   T3DLIB1函数库

     2D引擎架构,可以先全屏再调整窗口大小到窗口程序

     基本定义

     可用宏

     数据类型和结构

       BOB(Billter Object Engine)

     全局定义

     DirectDraw接口

       DDraw_Init

       DDraw_Shutdown

       DDraw_Attach_Clipper

       DDraw_Create_Surface

       DDraw_Flip

       DDraw_Wait_For_Vsync

       DDraw_Fill_Surface

       DDraw_Lock_Surface

       DDraw_UnLock_Surface

     2D多边形函数

       Draw_Triangle_2D

       Draw_TriangleFP_2D

       Draw_QuadFP_2D

       Draw_Filled_Polygon2D

       Translate_Polygon2D

       Rotate_Polygon2D

       Draw_Line

       Draw_Pixel

       Draw_Rectangle

       Draw_HLine

       Draw_VLine

       Screen_Transitions

       Draw_Text_GDI

     数学和误差函数

       Fast_Distance_2D //3.5% error

       Fast_Distance_3D //11% error

       Find_Bounding_Box_Poly2D

       Open_Error_File

       Close_Error_File

       Write_Error

     位图函数

       Load_Bitmap_File

       UnLoad_Bitmap_File

       Create_Bitmap_File

       Destroy_Bitmap

       Load_Image_Bitmap

       Flip_Bitmap

       Scroll_Bitmap

       Copy_Bitmap

     调色板函数

       Set_Palette_Entry

       Get_Palette_Entry

       Save_Palette_To_File

       Load_Palette_From_File

       Rotate_Colors

      *Blink_Colors

     实用工具函数

       Get_Clock

       Start_Clock

       Wait_Clock

       Collision_Test

       Color_Scan //另一种碰撞检测法

     BOB引擎

       BOB基本上是由一个或多个DirectDraw表面(最大到64个)

抱歉!评论已关闭.