博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

游戏中多线程的使用

Posted on 2011-05-09 17:40  +石头+  阅读(3138)  评论(0)    收藏  举报

多线程是提高程序效率的有效手段,在游戏中也十分的常用。

1.在游戏开始时加载资源时,多线程是非常常用的。主界面显示等待的画面,多线程中这时进行资源的加载(地图资源, 地图上的对象资源。。)

2.在正常的渲染逻辑中,如果把游戏的更新在多线程中运行,游戏的效率将有很大幅度的提升。

我们将多线程封装成一个类,方面使用。

class CXMultThread

{

public:

    CXMultThread(void){mHandle = NULL , mThreadID = 0;};

    ~CXMultThread(void){if(mHandle)CloseHandle(mHandle);};

public:

    HANDLE mHandle;

    DWORD mThreadID;

    bool Create(LPTHREAD_START_ROUTINE MainFunc, LPVOID lpParam, bool RunWhenCreate);    //第二个参数为,多线程函数的参数,第三个参数为创建后是否执行,true为执行,false为挂起

    void Suspend();

    void Resume();

    void Terminate();

};

XMultThread.cpp:

bool CXMultThread::Create( LPTHREAD_START_ROUTINE MainFunc, LPVOID lpParam, bool RunWhenCreate )

{

    if(RunWhenCreate)

    {

        mHandle = CreateThread(NULL, NULL, MainFunc, NULL, 0, &mThreadID);

    }else

    {

        mHandle = CreateThread(NULL, NULL, MainFunc, NULL, CREATE_SUSPENDED, &mThreadID);

    }

    

    if(mHandle)

    {

        return true;

    }else

    {

        return false;

    }

}

 

void CXMultThread::Suspend()

{

    if(mHandle)

    {

        SuspendThread(mHandle);

    }

}

 

void CXMultThread::Resume()

{

    if(mHandle)

    {

        ResumeThread(mHandle);

    }

}

 

void CXMultThread::Terminate()

{

    if(mHandle)

    {

        TerminateThread(mHandle ,1);

    }

    if(mHandle)

    {

        ExitThread(0);        //退出当前线程,在哪个线程中执行的,哪个就是当前线程

    }

}

在主函数中调用

CXMultThread MT_Load;

MT_Load.Create(&Load, NULL, true);

Load函数为加载资源的回调函数

DWORD WINAPI Load(LPVOID pParam)

{

    CoInitialize(NULL);

    

    D3DXCreateSprite(gDX->GetDVC(),&gSprite);

    D3DXCreateFont(gDX->GetDVC(),32,0,0,0,0,GB2312_CHARSET,0,0,0,"宋体",&gFont);

    D3DXCreateFont(gDX->GetDVC(),24,0,0,0,0,GB2312_CHARSET,0,0,0,"宋体",&gFont24);

    D3DXCreateFont(gDX->GetDVC(),18,0,0,0,0,GB2312_CHARSET,0,0,0,"宋体",&gFont18);

    //Sleep(3000);

 

    gEye.Create(NULL,gDX);

    gEye.mXPos.mPos=Vector(0,100,0);

 

    gSea.Create(NULL,gDX);

    gSea.AddQuakePoint(2000,2000,5,3.5);

    gSea.AddQuakePoint(-670,-200,4,2.5);

    gSea.AddQuakePoint(2000,0,8,4);

    gSea.AddQuakePoint(0,0,2,0.5);

 

    gMapCell.Create(NULL,gDX);

    gMapCell.mXPos.mPos = Vector(100, 0 ,-100);

 

    gSky.Create(NULL,gDX,".\\RES\\Sky\\Sky1.x");

    gSky.mXPos.mZoom=Vector(0.3,0.3,0.3);

    gSky.mXPos.mPos=Vector(0,-300,0);

 

    gBox.Create(NULL, gDX, "RES\\BOX\\box.x","001.jpg,002.jpg,003.jpg,004.jpg,005.jpg,006.jpg");

    gBox.mXPos.mPos=Vector(100,30,100);

    gBox.mXPos.mZoom = Vector(10, 10, 10);

    gBox.mXPos.mBodyPass = Vector(0, 0.5, 0);

    gBox.ForceOnMap(&gMapCell, 0, uwmMap);

    gCoord.Create(&gBox,gDX,201,10);

    gCoord.mXPos.mPos=Vector(0,0,0);

 

    

 

    gGS.ChangeScense(gsGame);

    CoUninitialize();

    return 1;

}

首先进入Loading界面,随后在多线程中加载资源。

在渲染的更新函数中:

MT_Update.Create(&UpdateMT, NULL, false);

DWORD WINAPI UpdateMT(LPVOID lpParam)

{

    while(1)

    {

        gDX->UpdateLight(gCurrentPass);

        gSea.Update(gCurrentPass);

        gBox.Update(gCurrentPass);

        gMapCell.Update(gCurrentPass);

        MT_Update.Suspend();        //为了保证不是一直在更新,我们每次更新后将线程挂起,在每次渲染前Resume线程.

    }

    return 1;

}