Platform SDK: DirectX

ステップ 5 : ゲームの開始とメッセージの交換

[C++]

ここでは、Visual Basic でのアプリケーション開発について説明する。C++ については、「DirectPlay C/C++ チュートリアル」を参照すること。

[Visual Basic]

DirectPlay は、最低 1 人のプレーヤーがセッションに参加すると、直ちにメッセージの送信を開始する。プレーヤーがセッションに参加したり、セッションから離れたりするたびに、システム メッセージが送信される。Memory サンプルでは、このメッセージをきっかけとして、frmWaiting 内のプレーヤーのリストが更新される。

ゲーム (またはほかの形式の DirectPlay セッション) をどのように開始するかは、アプリケーション次第である。DirectPlay から見ると、アプリケーションがメッセージを送信してゲームの状態を更新していようがいまいが、セッションはセッションである。

Memory サンプルでは、最低 1 人のプレーヤーが参加したときに、ホストがセッションを開始できる。ホストが [Start] ボタンをクリックしたら、ますセッションへの参加を不可能にし、新しいユーザーがそのセッションを利用できないようにする。

Set SessionData = gObjDPlay.CreateSessionData
Call gObjDPlay.GetSessionDesc(SessionData)
Call SessionData.SetFlags(SessionData.GetFlags + _
        DPSESSION_JOINDISABLED)
Call gObjDPlay.SetSessionDesc(SessionData)

次に、タイプ識別子、プレイする順番に従ったプレーヤー ID のリスト、およびゲーム ボードのタイルの配置を含むメッセージを作成する。このメッセージに応答して、アプリケーションのほかのインスタンスが、プレーヤーの順番とゲーム ボードに関する情報を更新する。このメッセージは、プレーヤーがゲームの状態に関する情報を交換する方法の一例を示している。

まず、DirectPlayMessage のさまざまな書き込みメソッドを使用して、データをメッセージに組み込む。

Dim dpMsg As DirectPlayMessage
 
Set dpMsg = gObjDPlay.CreateMessage
 
' メッセージ タイプを組み込む。
Call dpMsg.WriteLong(MSG_SETUPBOARD)
 
' プレーヤーの数を組み込む。
Call dpMsg.WriteByte(gNumPlayers)
 
' プレーヤー ID を組み込む。
Dim PlayerID As Long
For X = 0 To gNumPlayers - 1
    PlayerID = objDPEnumPlayers.GetDPID(X + 1)
    dpMsg.WriteLong (PlayerID)
    ' プレーヤー ID のローカル コピーを保持する。
    gPlayerIDs(X) = PlayerID
    ' プレイの順番をホストに割り当てる。
    If PlayerID = gMyPlayerID Then gMyTurn = X
Next X
 
' タイルの配置を組み込む。
For X = 0 To NumCells - 1
    dpMsg.WriteByte (gPicArray(X))
Next X

ホストのアプリケーション インスタンスは、ここで自らのゲーム状態を更新する必要がある。アプリケーションのインスタンスは、ホストが送信したメッセージを受信しない。そのため、ホストにとっては、ここがほかのインスタンスがメッセージを受信したときに実行する更新を実行する最後のチャンスである。

次に、DPSEND_GUARANTEED フラグを使用して、このメッセージをほかのすべてのプレーヤーに送信する。このフラグを設定するのは、ほかのすべてのプレーヤーがこの情報を受信する必要があるからである (動きの速いアクション ゲームでわずかな変更を通知する場合は、保証なしのメッセージで十分である)。

Call gObjDPlay.Send(gMyPlayerID, DPID_ALLPLAYERS, _
        DPSEND_GUARANTEED, dpMsg)

受信側では、Sub Main プロシージャでメッセージを検索する。このとき、DoEvents を使用して、問い合わせ中にほかの処理を実行できるようにする。

Do While DoEvents() 
    GetDPMessages
Loop

GetDPMessages プロシージャでは、保留になっているメッセージの数を確認する。

Dim MsgCount As Long
MsgCount = gObjDPlay.GetMessageCount(gMyPlayerID)

次に、各メッセージを取得し、それを DirectPlayMessage オブジェクトの dpMsg に代入する。さらに、メッセージのタイプを取得する。これは、システム メッセージの場合も、Memory で定義されるメッセージの場合も、常に最初の Long 値である。

Dim FromPlayerID As Long
Dim ToPlayerID As Long 
Dim dpMsg As DirectPlayMessage
Dim MsgType As Long 
' 一部の宣言については省略する。GlobalModule.bas を参照すること。
.
.
.  
Do While MsgCount > 0
    Set dpMsg = gObjDPlay.Receive(FromPlayerID, ToPlayerID, _
            DPRECEIVE_ALL)
    MsgType = dpMsg.ReadLong()
 
    MsgCount = MsgCount - 1

システム メッセージの場合、FromPlayerID は DPSYS_MESSAGE である。それ以外は、すべてアプリケーション定義のメッセージである。Memory は、MSG_SETUPBOARD というタイプのアプリケーション定義を見つけると、データを組み込まれている順番で読み取り、いくつかの追加処理を実行してゲーム状態を更新し、プレイを開始できるようにする。

    Select Case MsgType
 
        Case MSG_SETUPBOARD
 
          ' プレーヤーの数。
          gNumPlayers = dpMsg.ReadByte
 
          ' プレイ順のプレーヤー ID。使用されていないプレーヤーの ID は 0。
          For X = 0 To gNumPlayers - 1
              gPlayerIDs(X) = dpMsg.ReadLong
              If gPlayerIDs(X) = gMyPlayerID Then gMyTurn = X
          Next X
 
          ' タイルの配置。
          For X = 0 To NumCells - 1
              gPicArray(X) = dpMsg.ReadByte
          Next X
 
          ' ゲーム ボードを表示する。 
          frmWaiting.Hide
          gGameUnderway = True
          frmGameBoard.Show
.
.
.
    End Select
.
.
.
Loop