HSP-TECH 第10弾

Network Game クライアントプログラム(エントリ処理)

2001.4.24 Written & Programed by Smith


 前回は、サーバプログラムがゲームのセッションを立ち上げ、クライアントからのエントリ要求に応答するというのを解説しました。今回は、クライアントプログラム側がサーバプログラムにゲームセッション参加のエントリ要求を行うプロセスを解説します。前回のサーバプログラムが理解できていればさほどむつかしくはありませんが、クライアントがサーバへのエントリ処理において考慮しなければならないポイントがあります。

 詳細に入る前にそれでは、ゲームセッションへのエントリ処理についてサーバ側とクライアント側での動作をまとめてみます。


     ■サーバ側
       1)ゲームセッションを起動
       2)エントリ要求待ち
       3)エントリ要求が着たらプレイヤーNo.を採番し参加要求元へ返す

     ■クライアント側
       1)ゲームセッションを検索(セッション数やセッション名を取得)
       2)自分のDirectPlayID(DPID)とゲームサーバのDirectPlayIDを取得
       3)ゲームサーバへ自分のDirectPlayIDを通知(これをもってゲームへのエントリ要求とする)
       4)プレイヤーNo.が発行されるまで待機する、発行されたらめでたくエントリ完了

 サーバ側よりも若干面倒な感じがしますね。なかでもポイントは、1)と4)になります。それではこれらを具体的にサンプルScriptを例にとり解説していきます。それでは早速ゲームセッションの検索からです。


	;/////	セッションの検索処理を開始	/////
SESSION_NAME="ARPG":Dest_ADDR="192.168.0.2":Port=""
AMdplaySelectSpecifiedConnection Dest_ADDR,Port,AMDPLAY_CONNECT_TCPIP
  ;///// セッションの列挙
           dim session,1:session = 0
           repeat
           wait Ivent_Time
           stick ky:if ky==128 : goto *owari ; [ESC]中断チェック
           if session == 0 : AMdplayEnumSessionCount session, GameName
           if session > 0 : break
           loop

 コネクション選択のAMdplaySelectSpecifiedConnectionですが、これは当然ゲームサーバのIPアドレスをセットします。私の環境では、家庭内LANの192.168.0.2というアドレスを振ったPC上でサーバプログラムを起動させそれに対してクライアントがエントリするように設定してみました。次にセッションの列挙ですが、これにはAMdplayEnumSessionCount命令を使い稼動しているセッション数を数えます。この命令のp2には、通信したい相手の識別名を指定しなければなりません。これは、サーバ上でいくつの通信用プログラムが稼動しているかわからないのでその特定に使われます。つまり、通信相手を特定するには、IPアドレス(またはドメインネーム)→通信アプリケーション名(識別名)→セッション名という感じで特定されていくのです。

 次にセッションの検索です。取得したセッション数をもとに、該当するセッション名を探します。


	;/////	セッションの検索ルーチン
dim flg,1:flg = $ff
repeat session
wait Ivent_Time
s = "" : AMdplayEnumSessionName s, "", cnt
if s == SESSION_NAME : AMdplayJoinSession cnt : flg=cnt : break
loop
if flg&&$ff{
mes "セッションが見つけられませんでした/session = "+session
wait Ivent_Stop:goto *owari
}
mes "セッションを見つけました/session = "+session
wait Ivent_Stop

取得したセッション数分の繰り返し処理の中で、wait命令を十分に取りながらAMdplayEnumSessionName命令でセッション名を取得していきます。そして、ログインしたいセッション名が見つかったらAMdplayJoinSession命令でそのセッションへの参加を通知します。また、ここでは例外処理としてセッションを見つけられなかった場合のことも考慮して適切な処理を入れてください。ポイントとなるwaitの時間ですが、Internetを想定した場合よほどよい環境でも50msくらいはかかると見たほうが良いでしょう。場合によっては、100ms〜200msどころか1000msくらいからることも十分にあり得ます。ですが、通信に1000msもかかるような環境の場合、もはや例外処理に回すほうが適切なのかもしれません。このあたりは実際にInternet上で何度もテストを重ねてknow-howとしていくしか無いかもしれません。

 次は、自分(クライアント)のDirectPlayID取得とサーバのDirectPlayID取得を解説します。


  AMdplayGetMyID MyID
  AMdplayGetPlayerID serverID,, DPENUMPLAYERS_SERVERPLAYER
	Set_DataType = Entry_Logon
AMdplaySend MyID, 1, pflg, serverID

自分のDirectPlayID(以下DPID)は、AMdplayGetMyID命令により取得できます。また、サーバ(実際はサーバプレイヤ)のDPIDは、AMdplayGetPlayerID命令で取得することが可能です。これらの処理をしておき、データタイプにEntry_Logon(#defineで定義済み)をセットしてAMdplaySend命令で自分のDPIDをサーバ側へ通知します。そしてこれがゲームセッション参加へのエントリ要求となります。ここで登場したデータタイプとは、アプリケーションで自由に設定できる値ですので、これはすなわち独自プロトコルの範囲と言えると思います。実際、ネットワークゲームを組むには主要な部分がほとんどこのデータタイプによって「何のデータであるのか」を定義付けし、サーバとクライアントの通信を制御していかなければなりません。この概念は非常に重要ですので良く理解しておきましょう。

 最後にエントリ要求後のプレイヤーNo.の通知待ちを解説します。


	repeat 200
wait Ivent_Time
AMdplayReceive tmp
if (tmp == 1) && (info.0 == Logon_Okay ) : break
loop
if (tmp ! 1) || (info.0 ! Logon_Okay) {
mes "ゲームサーバーがBusyです"
wait Ivent_Stop
goto *owari
}
dim MyNo,1:MyNo = bufnum.0
mes "PlayerNo. = "+MyNo
wait Ivent_Stop
mes "エントリ及びログオンに成功しました"

 繰り返し処理の中でwaitを取りながらサーバからの応答を待ちます。受信処理は、AMdplayReceive命令です。そして通知待ち処理条件として、「データを受信した」+「データタイプがエントリOK(Logon_Okay)」になりこれを判断したらbreakで繰り返し処理を抜けてあげます。通知待ちの繰り返し処理は、無限回数ではなく有限回数としこれを超えるようであれば例外処理を実行するようにしておきます。ネットワークを介したやりとりでは、いつ相手がどんな状態になっていたとしても良いように自分側に例外処理を組み込まなければなりません。これは必須ではありませんが、アプリケーションとしての配慮です。

今回は短めですがこれで解説は終わりです。また、今回のScriptは前回のサーバプログラムと一緒にアーカイブしたものをベースで解説してあります。じっくりScriptを眺め、またAMdplayのリファレンスで確認しながら解読してみてください。次回はいよいよマルチプレイヤーキャラクターの処理、サーバプログラムによるモンスターの行動処理、それらの配信処理といったネットワークRPGの主要処理とも言える部分を解説致します。そしてそのプログラムはHSP製のNetworkRPGのベースとして期待できるレベルのはずです、おたのしみに。
 それでは、次回に。

▽前回のスクリプトのセットをDLする(5kb)▽

  HSP-TECH第11弾へ

INDEXへ戻る