Topic : A DirectPlay Tutorial
Author : Sobeit Void
Page : << Previous 5  
Go to page :


            lpvMsgBuffer = GlobalAllocPtr(GHND, dwMsgBufferSize);

            } // end if (hr ==DPERR_BUFFERTOOSMALL)
        } while(hr == DPERR_BUFFERTOOSMALL);

        // message is received in buffer
        if (SUCCEEDED(hr) && (dwMsgBufferSize >= sizeof(DPMSG_GENERIC)
        {
            if (idFrom == DPID_SYSMSG)    // if system mesg
                Handle_System_Message((LPDPMSG_GENERIC)lpvMsgBuffer,
                        dwMsgBuffersize, idFrom, idTo);
            else  // else must be application message
                Handle_Appl_Message((LPDPMSG_GENERIC)lpvMsgBuffer,
                        dwMsgBufferSize,idFrom,idTo);
        }
    } while (SUCCEEDED(hr));

    if (lpvMsgBuffer)  // free mem
        GlobalFreePtr(lpvMsgBuffer);

}  // end void Receive_Mesg()



First we check if there are any messages in the loop. If not, we break out of this function. We then keep trying to receive the message in the buffer by allocating the new buffer. When the return value is not DPERR_BUFFERTOOSMALL, it means either we have received the message or another serious error has occurred. So we check if the hresult is successful before determining whether it is a system or application message, by which we call the appropriate functions. System messages come from DPID_SYSMSG, which is a reserved value in DirectPlay.

The 2 functions should be implemented as follows:


int Handle_System_Message(LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize,
                          DPID idFrom, DPID idTo)
{
    switch(lpMsg->dwType)
    {
    case DPSYS_SESSIONLOST:
        {
            // inform user
            // PostQuitMessage(0)

        } break;
    case DPSYS_HOST:
        {
            // inform user

        } break;
    case DPSYS_CREATEPLAYERORGROUP:  // a new player
        {
            // cast to get message
            LPDPMSG_CREATEPLAYERORGROUP lp = (LPDPMSG_CREATEPLAYERORGROUP)lpMsg;

            // inform user a new player has arrived
            // name of this new player is lp->dpnName.lpszShortNameA

        } break;
    case DPSYS_DESTROYPLAYERORGROUP:  // a lost player
        {
            // cast to get message
            LPDPMSG_DESTROYPLAYERORGROUP lp = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;

            // inform user a player has left
            // name of this new player is lp->dpnName.lpszShortNameA

        } break;
    default:
        // an uncaptured message. Error here
    }  // end switch

return(1);  // success
}  // end int Handle_System_Message(..)

int Handle_Appl_Message(LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize,
                        DPID idFrom, DPID idTo)
{
    switch(lpMsg->dwType)
    {
    case DP_MSG_CHATSTRING:
        {
            // cast to get the message we defined
            DP_STRING_MSG_PTR lp = (DP_STRING_MGS_PTR)lpMsg;

            if (gameServer)   // if server, relay the message to all players
  {
                lpdp->Send(local_player_id,DPID_ALLPLAYERS,
                    DPSEND_GUARANTEED, lp, dwMsgSize);
            }

            // update your chat window

        } break;
    default:
        // unknown application message, bad

    }  // end switch

    return(1);  // success
}  // end int Handle_Appl_Message(..)



The two functions are very similar. To get the actual message, we need to cast the message to the appropriate type before extracting the individual components. Even if the application message comes through, we need to cast it get the data within. The dwType parameter we defined in the chat string struct above enables us to differentiate the different messages the application defines. Although the chat requires only one message, which is the chat message, there is definitely a need for more messages types the application should handle. Every new message type you define should include a dwType parameter so the application can differentiate the messages.

Putting it Together
Now you know how it should be implemented, I will piece the various parts together (in WinMain)


// Get information from local player

// Connection creation
if (gameServer)
    Create_TCP_Connection("");
else
    Create_TCP_Connection(tcp_address);

// Session part
if (gameServer)  // if host
    // open connection
else  // if client
{
    // EnumSessions
    // Open connection
}

// Player creation
if (gameServer)  // set flags to create serverplayer
    // set flags to DPID_SERVERPLAYER
// create local player

while(1)
{
    if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)
    {
        if (msg.message == WM_QUIT)
            break;

        // translate and dispatch message
  
    }  // end if PeekMessage(..)
    else
    {
        // Your game loop

        Receive_Mesg();
    }  // end else

}  // end of while(1)

// close session

DirectPlay_Shutdown();



The reason I do not have a sample application to show is because the interface code would be as long as all this code and it would require another tutorial as long as this to explain how to do interface. However if you really do not know how to do a chat interface, I recommend looking at the control EDIT in the MSDN. For simplicity, the chat window can be implemented as a multi-line edit. Anyway I hope this makes DirectPlay clearer and the documentation makes more sense.

Page : << Previous 5