⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter9.txt

📁 系统全面的介绍WINDOWS中游戏的编程
💻 TXT
📖 第 1 页 / 共 2 页
字号:
                {
                    if (ModeList[i].bpp == (int)GameBPP &&
                        ModeList[i].w   == GameSize.cx &&
                        ModeList[i].h   == GameSize.cy)
                    {
                        break;
                    }
                }
            }else
            {
                for (i=0; i<NumModes; i++)
                {
                    if (ModeList[i].w   == GameSize.cx &&
                        ModeList[i].h   == GameSize.cy)
                    {
                        break;
                    }
                }
            }
            if (++i >= NumModes)
            {
                i = 0;
            }
            Msg("ModeList %d %d",i,NumModes);
            GameMode.cx = ModeList[i].w;
            GameMode.cy = ModeList[i].h;
            GameBPP     = ModeList[i].bpp;
            bStretch    = FALSE;
            InitGame();
            }
            break;
在收到VK_F6的消息后,程序设立一个初值为0的变量,并以该变量为存放显示模式列表的数组的下标,然后令其自加直至找到一个与当前模式相同的。然后令其自加1,取以该值为下标的元素为显示模式,最后重新初始化游戏。
5.F7的作用是改变颜色数。
       case VK_F7:
            GameBPP = GameBPP == 8 ? 16 : 8;
            InitGame();
            break;
6.F8的作用是决定是否使用拉伸算法。
        case VK_F8:
            if (bFullscreen)
            {
                bStretch = !bStretch;
                InitGame();
            }
          else
          {
              RECT rc;

            GetClientRect(hWnd, &rc);

            bStretch = (rc.right  != GameSize.cx) ||
                           (rc.bottom != GameSize.cy);

           if (bStretch = !bStretch)
                SetRect(&rc, 0, 0, GameMode.cx*2, GameMode.cy*2);        
           else
                SetRect(&rc, 0, 0, GameMode.cx, GameMode.cy);

          AdjustWindowRectEx(&rc,
                GetWindowStyle(hWnd),
                GetMenu(hWnd) != NULL,
                GetWindowExStyle(hWnd));

          SetWindowPos(hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
                    SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
            }
            break;


这部分的运行过程为:若为全屏模式则对 bStretch取非,然后初始化游戏。若为窗口模式,则取得当时窗口的特征,以确定bStretch的值,然后从新显示窗口。

7.F9的作用是取消使用软件模拟并逐个使用已有的驱动程序
   case VK_F9:
            DevIndex ++;
            bUseEmulation = FALSE;
            if (DevIndex >= MaxDevIndex)
                DevIndex = 0;

            ExitGame();
            DDDisable(TRUE);        // destroy DirectDraw object
            InitGame();
            break;

第七节 其他消息
    case WM_DISPLAYCHANGE:
        break;

    case WM_CREATE:
        break;
 这两个消息收到后,将不做任何反应。

    case WM_SETCURSOR:
        if (bFullscreen && bIsActive)
        {
            SetCursor(NULL);
            return TRUE;
        }
        break;
该信息在光标随鼠标的移动而输入未被捕获时发出。
由于本游戏不需鼠标,故在随后的检测是否是全屏模式或是被激活的语句,获得肯定的答案后,将光标从屏幕上删除。   
case WM_PAINT:
        hdc = BeginPaint( hWnd, &ps );
        if (bPaused)
        {
            char *sz = "Game is paused, this is not a bug.";
            TextOut(ps.hdc, 0, 0, sz, lstrlen(sz));
        }
        EndPaint( hWnd, &ps );
        return 1;
该消息在请求重新绘制应用程序窗口是发出 。
程序在接收到这个消息后就调用BeginPaint()为hWnd所指的窗口作好绘画准备。然后判断游戏是否暂停,若是则向屏幕输出Game is paused, this is not a bug.最后调用EndPaint()
    case WM_DESTROY:
        hWndMain = NULL;
        lastInput=0;
        DestroyGame();          // end of game
        DDDisable(TRUE);        // destroy DirectDraw object
        PostQuitMessage( 0 );
        break;
该消息在要撤消某窗口时向该窗口发送。
在收到这个消息后程序令指向窗口的句柄为NULL,对游戏的刷新单元的下一次输入设为0,然后清除游戏及游戏工所占的内存。

第八节 刷新游戏单元
在讨论完窗口过程后,我们应开始介绍这个游戏的消息循环部分了。在这个游戏的消息循环部分中大部分在第二章 windows编程基础中已经谈到过了,所以在这里我们将只介绍刷新游戏单元和重画游戏单元部分。在消息循环中程序是调用函数ProcessFox(SHORT sInput)来进行这两部分的工作的。在ProcessFox(SHORT sInput)函数中,先对游戏是否正在运行或恢复游戏运行是否成功作了一个检测,然后就先调用ProcessInput(sInput)函数进行刷新游戏单元部分,再调用NewGameFrame()进行重画游戏单元的工作。下面就让我们先看看刷新游戏单元部分吧。
这一部分的运行过程为:

1.狐狸的行为刷新
首先取得当前狐狸的的速度、行为和方向。然后检测是否获得狐狸的位置或输入是否是4209,若检测的表达式为TURE则输入为0,即没有输入,若为FLASE则开始对各种输入进行响应。在响应的过程中程序先对狐狸的当前状态进行判断,然后根据狐狸的当前状态决定下一帧狐狸的基本状态。比如“↓”键或小键盘的“2”被按下时的响应过程为
    case KEY_DOWN:
        if( foxAction == STOP )
        {
            break;
        }
        else if( foxAction == STILL )
        {
            SetSpriteAction( hFox, CROUCH, SAME );
        }
        else if( foxAction == WALK )
        {
            SetSpriteAction( hFox, CROUCHWALK, SAME );
        }
        break;
在“↓”键被按下时,如果狐狸的动作是在急停的,则跳出;如果狐狸是静止的,则狐狸蹲下不动;若狐狸是在移动,则狐狸的行动改为爬行。
在对输入的初步处理后,程序便结合狐狸行为的其他属性,确定下一帧狐狸的状态。在这里同样是用switch——case语句和大量的if——else语句完成的。

2.熊和苹果的行为刷新
这两部分的运行过程实际上是一致的,都是首先进行碰撞检测,然后再根据检测结果决定角色新的行为属性。

第九节 重画游戏单元 
这部分的工作是由NewGameFrame()完成的。这个函数首先调用SetSpriteX() 、SetSpriteY()两函数设定角色的新位置,再调用SetPlaneVelX()和SetPlaneX()函数设定三层背景的移动速度和下一帧的位置。然后通过检测bTransDest的值决定是先将角色的位图粘贴到Backbuffer还是先将背景的位图粘贴到BackiBuffer,
最后调用函数gfxSwapBuffers()进行页面翻转将后备缓冲区中的图显示到屏幕上。该函数是这样实现的:
BOOL gfxSwapBuffers( void )
{
    if( bFullscreen )
    {
        if( bStretch )
	{
            gfxStretchBackbuffer();
	}

        if (nBufferCount > 1)
            return gfxFlip();
        else
            return TRUE;
    }
    else
    {
        return gfxUpdateWindow();
    }
它的运行过程是这样的:在全屏模式下且使用拉伸算法时用gfxStretchBackbuffer()对后备缓冲区和拉伸缓冲区之间进行blt操作,然后在有一个以上(不含一)的后备缓冲区时用gfxFlip()调用IDirectDrawSurface_Flip( lpFrontBuffer, NULL, DDFLIP_WAIT )进行一次页面翻转操作将后备缓冲区中的图显示到屏幕上。如果是窗口模式下,则通过gfxUpdateWindow()调用IDirectDrawSurface_Blt( lpFrontBuffer,&rcWindow,lpBackBuffer,NULL,DDBLT_WAIT,NULL)直接将后备缓冲区中的内容blt到主缓冲区中。这样就完成了重画游戏单元的任务了。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -