游戏开发论坛

 找回密码
 立即注册
搜索
12
返回列表 发新帖
楼主: 爱冒险

DirectPlay中的图象抖动问题

[复制链接]

10

主题

69

帖子

69

积分

注册会员

Rank: 2

积分
69
发表于 2007-4-29 22:11:00 | 显示全部楼层

Re:DirectPlay中的图象抖动问题

不会不行吧
    把你的代码(关于DPLAY方面的)贴出来,我帮你看看
   

1

主题

12

帖子

12

积分

新手上路

Rank: 1

积分
12
 楼主| 发表于 2007-4-30 00:16:00 | 显示全部楼层

Re:DirectPlay中的图象抖动问题

好的,今天已经很晚了,不折腾了。
明天贴出来,请你指教。
感觉你能搞定这个问题的。

1

主题

12

帖子

12

积分

新手上路

Rank: 1

积分
12
 楼主| 发表于 2007-4-30 00:52:00 | 显示全部楼层

Re: DirectPlay中的图象抖动问题

算了,还是现在就贴出来,反正回去也睡不着!
就辛苦你啦!多谢!!!

//-----------------------------------------------------------------------------
// 初始化DirectXPlay
//-----------------------------------------------------------------------------
HRESULT DPlayNetServiceProvider::InitDirectPlay(void)
{
        ......

    // 创建IDirectPlay8Peer对象
    if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Peer, NULL,
                                       CLSCTX_INPROC_SERVER,
                                       IID_IDirectPlay8Peer,
                                       (LPVOID*) &m_pDP ) ) )
    {
        OutputError( TEXT("Failed Creating the IDirectPlay8Peer Object"), hr );
        return hr;
    }

    // 初始化DirectPlay
    if( FAILED( hr = m_pDP->Initialize(NULL, DirectPlayMessageHandler, 0 ) ) )
    {

        OutputError( TEXT("Failed Initializing DirectPlay"), hr );
        return hr;
    }

        ......
}



//-----------------------------------------------------------------------------
// 回调函数。
//调用DPlayNetServiceProvider::MessageHandler处理DirectXPlay发送给应用程序的各种消息。
//-----------------------------------------------------------------------------
HRESULT WINAPI DirectPlayMessageHandler(PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer)
{
        HRESULT  hr = S_OK;
        switch( dwMessageId )
    {

        //处理接收到的消息
                case DPN_MSGID_RECEIVE:
                        hr = netProvider->ReceiveMessage(pvUserContext,dwMessageId,pMsgBuffer);
                        break;
                       
        ......
    }


        return hr;
}


//-----------------------------------------------------------------------------
//处理接收到的消息。
//-----------------------------------------------------------------------------
HRESULT DPlayNetServiceProvider::ReceiveMessage(PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer)
{
        PDPNMSG_RECEIVE     pMsg=NULL;
        pMsg = (PDPNMSG_RECEIVE) pMsgBuffer;

        //将接收到的BYTE*类型的数据转换为矩阵指针类型
        m_recMatrix = (D3DXMATRIX*)(pMsg->pReceiveData);

        return S_OK;
}


//-----------------------------------------------------------------------------
// 向会话中的所有玩家发送消息
//-----------------------------------------------------------------------------
HRESULT DPlayNetServiceProvider::SendDirectPlayMessage(BYTE* sendData)
{
        ......
    dpnBuffer.pBufferData = sendData;
    dpnBuffer.dwBufferSize = sizeof(D3DXMATRIX);

    if( FAILED( hr = m_pDP->SendTo( DPNID_ALL_PLAYERS_GROUP, // dpnid
                                    &dpnBuffer,              // pBufferDesc
                                    1,                       // cBufferDesc
                                    0,                       // dwTimeOut
                                    NULL,                    // pvAsyncContext
                                    NULL,                    // pvAsyncHandle
                                    DPNSEND_SYNC |
                                    DPNSEND_NOLOOPBACK ) ) ) // dwFlags
    {
       // OutputError( TEXT("Failed Sending Data"), hr );
        //return hr;
    }

    return S_OK;
}


//-----------------------------------------------------------------------------
//获取收到的matrix(表示位置的矩阵)
//-----------------------------------------------------------------------------
D3DXMATRIX* DPlayNetServiceProvider::GetReceivedMatrix()
{
        return m_recMatrix;
}

///////////////////////////////////////////////////////////////////////////////////
//以上为网络通信的相关代码
//以下为在整个程序中与网络相关的部分
///////////////////////////////////////////////////////////////////////////////////

int WINAPI WinMain(HINSTANCE hIns,HINSTANCE hPre,LPSTR lpCmdLine,int nShow)
{
        ........
        CoInitializeEx(NULL,COINIT_MULTITHREADED);
        ........
        netProvider = new DPlayNetServiceProvider;
    // Init the DirectPlay system
    if( FAILED( hr = netProvider->InitDirectPlay() ) )
    {
    }
         ........

                while(msg.message != WM_QUIT) {
                        if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
                                if(msg.message != WM_QUIT) {
                                        TranslateMessage(&msg);
                                        DispatchMessage(&msg);
                                }
                        }
                        else {
                                g_pd3dEnv->Render();
                                Sleep(20);
                        }
        .........
}



void CD3DEnv::Render()
{
        .......
        DrawPlane();//显示自己
        ............
        //render guest plane
        RenderGuestPlane();//显示另外一架
        ...........
}

void CD3DEnv:rawPlane()
{
    //先显示自己,然后把自己的位置发送给远程玩家。
        .............
    //----------------------------------------------------------------
    //发送消息
    BYTE *pByte;
        pByte = (BYTE*)(&mat);
        netProvider->SendDirectPlayMessage(pByte);               
    //------------------------------------------------------------------
}

void CD3DEnv::RenderGuestPlane()
{
        static D3DXMATRIX matPlane;

        D3DXMATRIX matIdentity;
        D3DXMatrixIdentity(&matIdentity);
       

        if((netProvider) && (netProvider->GetReceivedMatrix() != NULL))
        {
        matPlane = *(netProvider->GetReceivedMatrix());
         .............
}

10

主题

69

帖子

69

积分

注册会员

Rank: 2

积分
69
发表于 2007-4-30 11:30:00 | 显示全部楼层

Re:DirectPlay中的图象抖动问题


//对初始化DPLAY部分的修改
......
    //cqr add
    //declare a member IDirectPlay8ThreadPool* m_pThreadPool;
    hr = CoCreateInstance( CLSID_DirectPlay8ThreadPool, NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_IDirectPlay8ThreadPool,
                          (LPVOID*) &m_pThreadPool );
    //end cqr add

    // 创建IDirectPlay8Peer对象
    if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Peer, NULL,
                                       CLSCTX_INPROC_SERVER,
                                       IID_IDirectPlay8Peer,
                                       (LPVOID*) &m_pDP ) ) )
    {
        OutputError( TEXT("Failed Creating the IDirectPlay8Peer Object"), hr );
        return hr;
    }
    //cqr add
    hr = m_pThreadPool->Initialize(NULL, DirectPlayMessageHandler, 0 );
    //end cqr add

    // 初始化DirectPlay
    if( FAILED( hr = m_pDP->Initialize(NULL, DirectPlayMessageHandler, 0 ) ) )
    {

        OutputError( TEXT("Failed Initializing DirectPlay"), hr );
        return hr;
    }


    //cqr add
    if( FAILED( hr = m_pThreadPool->SetThreadCount( (DWORD) -1, 0, 0 ) ) )
    {
        DXTRACE_ERR_MSGBOX( TEXT("Failed calling SetThreadCount"), hr );
    }

    //end cqr add
......

//

10

主题

69

帖子

69

积分

注册会员

Rank: 2

积分
69
发表于 2007-4-30 11:42:00 | 显示全部楼层

Re:DirectPlay中的图象抖动问题

//对WINMAIN的修改
int WINAPI WinMain(HINSTANCE hIns,HINSTANCE hPre,LPSTR lpCmdLine,int nShow)
{
........
CoInitializeEx(NULL,COINIT_MULTITHREADED);
........
netProvider = new DPlayNetServiceProvider;
    // Init the DirectPlay system
    if( FAILED( hr = netProvider->InitDirectPlay() ) )
    {
    }
         ........

while(msg.message != WM_QUIT) {
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
if(msg.message != WM_QUIT) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else {
//cqr add
  if (netProvider->m_pThreadPool!=NULL)
  netProvider->m_pThreadPool->DoWork( 100, 0 );
  //not OO you should modify it in OO
//end cqr add
g_pd3dEnv->Render();
Sleep(20);
}
.........
}
//

1

主题

12

帖子

12

积分

新手上路

Rank: 1

积分
12
 楼主| 发表于 2007-5-2 22:46:00 | 显示全部楼层

Re: DirectPlay中的图象抖动问题

五一快乐,conquerors!

我试过了,看着远程的那架飞机还是在前后抖。除了改动你说的那几处代码,应该不用改动别的地方了吧,比如工程属性等?

如果本地飞机静止不动则远程飞机看起来不抖动。 [em7] [em7] [em7] [em7] [em7]

10

主题

69

帖子

69

积分

注册会员

Rank: 2

积分
69
发表于 2007-5-3 08:44:00 | 显示全部楼层

Re:DirectPlay中的图象抖动问题

修改后的代码,DPLAY是在主线程中处理NETMSG的,也就是说,不存在线程之间的干扰.
这样,飞机还会抖动,说明表示飞机坐标的数据可能问题.

你做一个DEBUG OUT PUT 吧
把你的飞机坐标输出,看看有什么规律
还有,把这个代码Sleep(20)去掉

1

主题

12

帖子

12

积分

新手上路

Rank: 1

积分
12
 楼主| 发表于 2007-5-4 19:59:00 | 显示全部楼层

Re:DirectPlay中的图象抖动问题

经过调试,我发现问题的关键是:收到数据的平均速率基本上是本地处理数据的速率的两倍。也就是说收到的近一半数据,本地程序还来不及处理就被后续收到的数据覆盖了。并且有时候是收一个处理一个,有时候接连有几个数据未被处理就被覆盖,造成显示远程飞机时,其位置跨度太大,从而出现前后抖动的现象。证据是调用receivemessage()的频率几乎是getReceivedMatrix()的两被

10

主题

69

帖子

69

积分

注册会员

Rank: 2

积分
69
发表于 2007-5-5 01:21:00 | 显示全部楼层

Re:DirectPlay中的图象抖动问题

DPLAY应该不会覆盖尚未处理的数据包,而且如果,你已经按照我的提示修改代码为单线程的,receivemessage()和getReceivedMatrix()是顺序执行的,没有异步的问题。

我觉得飞机抖动的问题应该是源自表示飞机坐标的MATRIX。

你可以尝试一下用一组float型变量来保存飞机的坐标xyz,并且将这组坐标发送到远程机器上,远程机器在收到坐标后做相应的world transform,估计就不会出现抖动的问题。

结合你所发现的问题,如果飞机的位置没有变化就不发送相关的NetMsg。
(注意float型的变量有精度问题)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-26 14:25

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表