読者です 読者をやめる 読者になる 読者になる

いつクリはてブロ

いつになったらクリエイティブするの?

DXRuby製のゲームに通信機能を組み込む

技術 Ruby DXRuby

この記事はDXRuby Advent Calendar 2013の22日目です。

前回はしろかのさんのDXRubyからのHLSL使用方法でした。
普段ゲームを作るときはグラフィック……??みたいな姿勢なので、これを機に多少はその辺のコードも書けるようにしないとなと改めて思いました(小学生並の感想)
Shader使えたら画面をもっとキレイにかっこ良くできるんだろうけど、道のりは遠そうです……。

つまり、今回もグラフィカルな要素とは無縁の記事です。ご了承ください。

DXRuby製のゲームに通信機能を組み込む

今回もまたDXRubyをどう使うか、という話になります。
本当はもっと盛り沢山の内容になるはずでしたが、サンプルを作るのに割と手間取ってしまったため、いろいろ残念なことになっています。

さて、ゲームに通信機能を組み込むと一言で言っても、いろんなパターンがあり得ます。
また、用途に合わせて通信の方式も変わってきます。
今回はDXRubyで作ったゲームを同期通信させ、MMOっぽい挙動をする何かを作ってみました。
vivit-jc/socket_mmo · GitHub
ソースコード置き場
今回は後述する事情によりソースコードのみとさせていただきます。
実行のための環境は各自ご用意ください。

このツールを実現するために、サーバー(server.rb)とクライアント(main.rb)の二つのソフトウェアを書く必要があります。
サーバー側のコードを適切な場所に置き起動させてから、クライアントソフトで接続します。
この接続にはソケット通信というものを使っています。詳しくはググってください。
ソケット通信 - Google 検索
ソケット通信をRubyで行うためにはライブラリを読み込む必要があります。Rubyに標準で付属しているはずなのでコードの頭に以下を書き足すだけでOKです。

require 'socket' 

サンプルをローカルで動かす

アドレス指定の関係上*1、そのままでは動かないので、一部を書き換える必要があります。
ローカルで実験する場合、model.rbの以下の部分を書き換えてください。

#@s = TCPSocket.open("intotheprow.rackbox.net", 40004) #これを
@s = TCPSocket.open("localhost", 3002) #こう書き換える

まずserver.rbをコマンドプロンプトなどから実行します。
そしてさらに複数のコマンドプロンプトを起動して、main.rbを実行します。
複数のクライアントからログインしたとき、ちゃんとその数だけキャラクターが表示されているでしょうか?
f:id:vivit_jc:20131223033235p:plain

サーバー側ソフトウェアの解説

サーバー側はプレイヤーとの接続が確立されるたびにスレッドを作成し、そのプレイヤーの情報(名前、X,Y座標)を保存します。
また、何か情報を受け取ったら、その情報を更新し、参加しているユーザー全体の情報をまとめてクライアントに渡しています。
ここはサーバーに処理させる部分なのでDXRubyは全く関係ありません。すみません……。

クライアント側ソフトウェアの解説

クライアント側では、文字入力や矢印キーの入力を受け付け、それをサーバー側に送ります。
また、サーバーから自分を含む全てのプレイヤーの情報が送られてくるので、それに合わせて画面表示を行います。
ファイル構成はMVCっぽくなってますが今回はとにかく時間が無く、非常に雑な仕上がりになっています。
しかし、雑でもそれなりに素早く書けてしまうのがRuby+DXRubyの強力なところでもあります。
プロトタイプはこんな感じで適当で良いのです!(開き直り)

他の通信手段

他の通信手段としてはHTTPによる通信が考えられます。
これもソケット通信と同様、ライブラリを足して実現します。
gemを使うともっと便利にwebとの通信を行うことができます。
私はよくmechanizeを使います。
mechanize-2.7.0 Documentation
これによって、例えばネットを通じたオンラインスコアランキングなども手軽に作ることができます。

また、クライアントソフトが独自に通信をしなくても事が足りる場合があります。
例えば、Win32APIを用いることで、標準ブラウザで指定のURLを開くという方法が利用できます。
Twitterにスコアを投稿させるなどの簡単な挙動の場合は、自力で実装するよりもこちらの方がラクで、ユーザーフレンドリーになるでしょう。

実現には課題が多い><

しかしDXRuby製のゲームに通信機能を組み込むのは一筋縄ではいきません。

ライブラリの問題

先に挙げたように、通信機能の多くはライブラリから提供されています。
DXRubyスターターキットに付属しているgame.exeはその辺のライブラリを積んでいないので、それらライブラリをパッケージングした独自のexeファイルを作成する必要があります。
これには様々な方法と選択肢があるのですが、本記事の取り扱う範囲を超えるので省略します。

クライアントの書き換えの問題

Rubyは処理系がインタプリタなので、コンパイルして難読化するということが比較的しにくいです。
小手先のテクニックで難読化、暗号化することはできるにはできますが、根本的にはソースコードが読めてしまいます。*2
ソースコードが読めるということは、リバースエンジニアリングにより不正なクライアントを作成したり、ゲームに不正にアクセスして悪影響を与えることが可能であるということを意味しています。

ひとりよりふたり

いろいろと問題はありますが、プロトタイプを作って適当に遊ぶ分には無視できますし、工夫を凝らせばかなりの割合で問題を解決できます。
DXRubyを使えば、一人用だけでなく、複数人用のゲームも、ちゃんと作れるのです。

皆様も是非、複数人用のゲームを空想して眠れない夜をお過ごしくださいませ。


明日は土屋つかささんの「短編小説:叔父さんと私と『DXRuby』(あるいは、なぜラノベ作家は過去MSXという8bitパソコンを愛し、現在DXRubyでゲームを作るのか)」です。
しょ、小説!?
何でもアリな感じがたまりませんね、非常に楽しみです!



参考にさせていただいた記事

[Ruby] ソケット通信 | unlinked log

*1:おそらく常設してません。どうしてもサンプルのアドレスで試したい場合は、私までお問い合わせください

*2:コンパイルしてバイナリを作る言語も読もうと思ったら読めなくもないですが、その度合いがインタプリタとは全然違ってきます