ゲームにhttpdを組み込む話

そのうち書こうと思いつつずっと後回しになってた話。6日にあったSDL offで発表した内容のまとめも兼ねて。


2009/01/11の日記でも少し触れていますが、exception conflictのサーバーモードはhttpサーバーも兼ね、ブラウザでアクセスすると難度などを設定するフォームが開いて、動的にパラメータを変更するインターフェースになっています。
また、常設サーバーを設置して頂いている まじ☆エビ さんの要望により、ゲームの参加人数&生存者数、経過時間、平均フレームレート、現在のオブジェクト数などのゲーム中のパラメータも表示するようになりました。
これにより、外部スクリプトでゲーム内の情報を読み取り、それに応じて動的にパラメータを変更させることが可能になっています。


現在常設サーバーでは まじ☆エビ さんのperlスクリプトにより、参加人数が増えると敵が固くなる、生存者が減ったり平均フレームレートが下がったりすると破片の量が減る、などの動的難度調整が自動的に行われています。
思いつきでくっつけてみた「外部から動的にゲームを制御する機構」が、こういうゲーム内のスクリプト制御とはまた違った面白い変化をもたらす可能性があるということが分かったので、これを開発に生かしたり、既存のゲームにこういう機構を組み込むことで化ける余地もあるかもしれません。


…というような話を、exception conflictの紹介を交えつつSDL offで発表しました。
独自プロトコルとかでも良くてhttpである必要はないんだけど、ブラウザで見れるのはやはり大きいので。ブラウザからゲーム内スクリプトを投げてその場で敵のパラメータを調整するとか、レベルエディタをflashで作って動的に読み込ませるなどの芸当も可能なハズ。


(httpサーバを書く、と言うと難しく聞こえるかもしれないけど、基本は下記の短いコードで、後は全部これの応用です。たぶん。)

#define _WIN32_WINNT 0x0500
#include <boost/asio.hpp>
using boost::asio::ip::tcp;

// コンパイルして実行して http://localhost/ にアクセスすると"ok"と書かれたページを表示する。 
// また、コンソールにブラウザから送られてきたリクエストを垂れ流す。 
int main(int argc, char *argv[])
{
  boost::asio::io_service service;
  tcp::acceptor acceptor(service, tcp::endpoint(tcp::v4(), 80));
  for(;;) {
    tcp::iostream s;
    acceptor.accept(*s.rdbuf());

    // リクエスト読み出し 
    std::string l;
    for(;;) {
      std::getline(s, l);
      puts(l.c_str());
      if(l.empty() || l[0]=='\r') {
        fflush(stdout);
        break;
      }
    }

    // 応答 
    s <<
"HTTP/1.1 200 OK\r\n"
"Content-Length: 2\r\n"
"Connection: close\r\n"
"Content-Type: text/plain; charset=Shift_JIS\r\n"
"\r\n"
"ok";
  }

  return 0;
}