Jewel-mmo開発日記

RubyでMMORPGを作る過程を記録する日記。 Yokohama.rb 発起人。
2009-05-20

[Ruby]Rubyのグラフィックライブラリの漠然とした案(2)

いや、今回は特にRubyに限った話じゃないんだけど。

引き続き、render(とかdraw)をいちいち呼ばないというのを考えてみる。

画面に描画するオブジェクトをクラスとして設計して、 オブジェクト自身に移動処理や描画処理(renderメソッド)を持たせてしまう、 というのはPSのゲームを作っていたころたどり着いた形で、 当時(3年前)この方向性の理想系として設計したのがMyGame(Rubyで手軽にゲームを作るためのライブラリ)だ。

ライブラリを実装するとき、 描画処理を描画オブジェクトのrenderメソッドとして シンプルに実装できる場合はいいのだけど、 現実問題そう出来ないこともある。 renderの前後である手続きが必要で、 その手続きが複数の描画物をまたがざる終えないような場合だ。

開発環境によっては、 MyGame型のAPIにうまく収まらない状況を何度か経験していて、 結局状況に応じてアドホックな実装を行う破目に。 具体的にはrenderメソッドの呼び出し前後で思いっきりネイティブなライブラリ関数を呼んだり。 いちいち対応すれば、無理やりオブジェクトの中に処理を隠蔽できそうな気はするが、 面倒なのででそこまではやらない。

結局やりたいことは、キャラクターをコントローラや移動アルゴリズムで操作するようなレイヤーから 次のことを隠蔽したいわけだ。

  • 描画物生成・破棄のメモリ管理
  • 描画物生成・破棄の煩雑な手続き
  • 描画の煩雑な手続き

MyGame型の設計では、表示物ひとつひとつを描画プリミティブとしてオブジェクトとして管理していた。 オブジェクトの中に煩雑な処理を隠蔽していたわけだ。

が、最近の考えているのは、描画処理全般を一枚岩で実装して、 外部にはシンプルはAPI(コマンド)を公開する形。 新しい環境で開発をするときは、結局描画クラスを毎回実装することになるのだから、 それなら一枚岩のほうが、汎用的なAPIが楽に実装できるんじゃないかと。

……と思ったけど、改めて考えるとやっぱり描画プリミティブをオブジェクトにするメリットはでかいんだよなあ。 何もかもをオブジェクトにしようと意識しすぎていただけかもしれない。 要はバランスの問題か。

2009-05-14

[Ruby]Rubyのグラフィックライブラリの漠然とした案

こんなのどうだろう。

コンセプトは描画オブジェクトのインスタンスをクライアントで保持し続けないことと、あとループ処理を作らずにクロージャー。

WorldServer.start で世界を作る。 あとは描画物を create するとそこに自動的に描画される。 render メソッドとかいらない。

WorldServer.start

Image.create('sample.bmp', :x => 100, :y => 100)

loop {}

画像を移動させる。

WorldServer.start

img = Image.create('sample.bmp', :x => 100, :y => 100)

loop {
  img.x += 1
  vsync
}

クライアントでインスタンスを保持していなくても、 id があれば描画要素にアクセスできる。 ついでに vsync_callback 。

WorldServer.start

id = Image.create('sample.bmp', :x => 100, :y => 100).id
vsync_callback {
  Image.find(id).x += 1
}

loop {}

id を記録したらインスタンス保持するのと同じか。じゃあ名前でアクセスとか。

WorldServer.start

Image.create('sample.bmp', :name => :sample)
vsync_callback {
  Image.find_by_name(:sample).x += 1
}

loop {}

上のコードは下のようにも書ける。

WorldServer.start

Image.create('sample.bmp').vsync_callback {|e|
  e.x += 1
}

loop {}

下のように書いてもいい。

WorldServer.start

Image.create 'sample.bmp', :vsync_callback => lambda {|e| e.x += 1 }

loop {}

x キーで画像をひとつ追加。 z キーで描画要素をすべて削除。

WorldServer.start

x = 0
Input.x {
  Image.create('sample.bmp', :x => x)
  x += 10
}

Input.z {
  WorldServer.clear
}

loop {}
2009-05-10

横浜へなちょこプログラミング勉強会行ってきた

よこへな行ってきた。

あとで書く。

2009-05-08

Sinatraをさくらインターネットで動かしたときのメモ

さくらインターネットにてSinatraをCGIで動かすときのメモ。

自前でインストールしたrubyとgem環境にsinatraをインストール。

 gem install sinatra

準備完了。

start.cgi

#!/home/ユーザー名/local/ruby/bin/ruby
require 'rubygems'
require 'sinatra'

get '/hi' do
  'hi!'
end

get '' do
  'Hello Sinatra!'
end

set :run => false, :environment => :production
Rack::Handler::CGI.run Sinatra::Application

.htaccess

start.cgi を置くディレクトリに .htaccess を作成する。

DirectoryIndex start.cgi

RewriteEngine On
RewriteBase /sinatra
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) start.cg/$1 [L]

mod_rewriteの設定はよく理解していないが、とりあえずこれで動いた。 RewriteBaseは start.cgi を http://dgames.jp/sinatra/ で動かすなら、「/sinatra」と書けばいいみたい。

「Errno::ESPIPE - Illegal seek」対策

※使用しているバージョンは sinatra (0.9.1.1), rack (0.9.1)

CGIをそのまま動かすと「Errno::ESPIPE - Illegal seek」というエラーが発生したので、 ここを参考に 「~/local/ruby/lib/ruby/gems/1.8/gems/rack-0.9.1/lib/rack/request.rb」を書き換える。

以下はオリジナルのスクリプト(編集前のrequest.rbをrequest.rb.origという名前でコピーしたもの)と書き換えたスクリプトのdiff。

$ cd ~/local/ruby/lib/ruby/gems/1.8/gems/rack-0.9.1/lib/rack/
$ diff request.rb.orig request.rb
116c116,119
<           @env["rack.input"].rewind if @env["rack.input"].respond_to?(:rewind)
---
>           begin
>             @env["rack.input"].rewind if @env["rack.input"].respond_to?(:rewind)
>           rescue Errno::ESPIPE
>           end

上の箇所を編集した後、cgiにアクセスすればエラーはでなくなる。

2009-05-08

さくらインターネットにrubyとgemをインストールしたときのメモ

ここで扱う環境とバージョンは以下。

  • さくらインターネット レンタルサーバーのスタンダードプラン
  • ruby 1.8.7-p160
  • rubygems 1.3.3

サーバーに最初から入っているrubyを使う手もあるようだが、 ここではローカル環境に最新のrubyをインストールし、インストールしたrubyにgemをインストールする。

以下コンソールで作業。

rubyのコンパイルとインストール

任意の作業用ディレクトリに移動して、最新のrubyをダウンロード。

wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p160.tar.gz

解凍。

tar xzvf ruby-1.8.7-p160.tar.gz

コンパイル。(※「ユーザー名」は自分のユーザー名に置き換える)

cd ruby-1.8.7-p160
./configure --prefix=/home/ユーザー名/local/ruby
make

インストール。

make install

インストールが終了したらダウンロードしたソースやコンパイルしたファイルは不要(消して良い)。 コンパイルしたrubyは「/home/ユーザー名/local/ruby」にコピーされている。

「$HOME/local/ruby/bin」にパスを通す。 csh(デフォルトのシェル)を使っているなら、.cshrc の「set path」の先頭に「$HOME/local/ruby/bin」を追加する。

set path = ($HOME/local/ruby/bin /sbin /bin /usr/sbin ..(略)..)

.cshrcを書き換えたあと、シェルにログインし直して、インストールしたrubyが参照されるか確認する。 インストールした先にパスが通っていれば、シェルでのrubyコマンドは新しくインストールしたrubyが優先されるようになる。

ruby -v
#=> ruby 1.8.7 (2009-04-08 patchlevel 160) [i386-freebsd6.1]

または、

which ruby
#=> /home/ユーザー名/local/ruby/bin/ruby

で確認。

CGI等でrubyのパスを指定する場合は、「/home/ユーザー名/local/ruby/bin/ruby」となる。

gemのインストール

任意の作業用ディレクトリに移動して、最新のgemをダウンロード。

wget http://rubyforge.org/frs/download.php/56227/rubygems-1.3.3.tgz

解凍。

tar xzvf rubygems-1.3.3.tgz

インストール。(※上記方法でインストールしたローカルのrubyを呼び出していることに注意)

cd rubygems-1.3.3
ruby setup.rb

下記コマンドでgemのバージョンが表示されればインストール成功。

gem -v
#=> 1.3.3

rakeをインストールする例。

gem install rake
2009-05-04

concrete5をさくらインターネットにインストールしたときのメモ

現状のconcrete5はDBひとつをまるごと使うが、 普通ならそのまま動く模様。

※追記(2009/05/06): バージョン 5.3.1.1 で下記問題は修正されたようです。

だが、

○データベースの名前にハイフン「-」が入っているとインストールができません

公式FAQより

うちは不幸にもこれに該当してしまう。 さくらインターネットの「さくらのレンタルサーバ スタンダード」では、アカウント名がMySQLのDB名になるのだが、うちのアカウント名はハイフン入りなのだ。

FAQには対策方法がなにやら書いてあるが面倒そうであきらめかけたものの、 要はSQL分のDB名指定のところが「`」で囲んでないだけじゃないのか?

事実確認のためブラウザのセットアップ画面からDB名(ハイフン入り)を入力してセットアップ開始すると、 確かに「-」が原因でエラーになる。 ソースを見ると「concrete/libraries/database.php」の次の部分が問題のところらしい。

concrete/libraries/database.php

>--->---$cd = $this->db->GetRow("show create database {$this->db->database}");
>--->---if (!preg_match('/' . DB_CHARSET . '/i', $cd[1])) {
>--->--->---$this->db->Execute("ALTER DATABASE {$this->db->database} character set " . DB_CHARSET);
>--->---}

次のように {$this->db->database} を「`」で囲んでやる。2箇所修正。

>--->---$cd = $this->db->GetRow("show create database `{$this->db->database}`");
>--->---if (!preg_match('/' . DB_CHARSET . '/i', $cd[1])) {
>--->--->---$this->db->Execute("ALTER DATABASE `{$this->db->database}` character set " . DB_CHARSET);
>--->---}

これでOK。 さくらのレンタルサーバーでも無事動かすことができた。

2009-05-03

concrete5をUbuntuにインストールしたときのメモ

PHPをほとんど使ったことがなかったのでちょっと戸惑ったが、 PHPが入っている環境ならファイルを置くだけで動くものらしい。 準備が整っていなくてもセットアップ画面が開き、必要なものがインストールされているかチェックした結果を表示してくれるので大変親切。

準備

sudo apt-get install apache2
sudo apt-get install php5 php5-gd
sudo apt-get install mysql-server mysql-client php5-mysql

手元の環境では上記で必要なパッケージの準備は完了。

一応apache2を再起動しておく。

sudo /etc/init.d/apache2 restart

MySQL

データベースの作成。 ここではmysqlインストール時にrootにパスワードを設定していないので、パスワードなしでアクセス。

mysql -u root

ここでは「concrete5」という名前でデータベースを作成する。名前は任意。

CREATE DATABASE concrete5 CHARACTER SET utf8;

concrete5のセットアップ

下記サイトから「concrete5.3.0 日本語 最新安定板」をダウンロード。

以下Ubuntuのシェルで作業。

unzip concrete5.3.0.ja.zip

上記コマンドでダウンロードしたzipを解凍し、 「/var/www/concrete5」にコピーする。

sudo cp -r concrete5.3.0.ja /var/www/concrete5

configとfilesのパーミッションを変更。

cd /var/www/concrete5
sudo chmod 777 config
sudo chmod 777 files

ブラウザから下記URLにアクセスする。 (別PCのブラウザからアクセスする場合、localhostの部分はUbuntuのホスト名になる。)

セットアップ画面が起動するはず。

サーバーの必須機能が正しく認識されていることを確認し、各種情報を入力する。

  • サイト名 …… 任意
  • メールアドレス …… 任意
  • MySQLデータベース情報 …… localhost
  • MySQLユーザー名 …… root
  • MySQLパスワード …… 任意(ここでは設定していないので空欄のまま)
  • データベース名 …… concrete5

上記を入力したら「concrete5をインストール!>」をクリック。

concrete5の管理画面が開くはず。

http://localhost/concrete5/ にアクセスするとデフォルトで用意されているサイトのトップページを開くことが出来る。