Jewel-mmo開発日記

RubyでMMORPGを作る過程を記録する日記。 Yokohama.rb 発起人。
2006-10-30

配列とeach

配列の要素に先頭から順にアクセスするにはどうしたらいいか。

int a[] = {0, 10, 20, 30};
int i;
for(i = 0;i < 4;i++) {
  int e = a[i]; // 配列の要素にアクセス
}

Ruby にも for 文はある。

a = [0, 10, 20, 30]
for i in [0, 1, 2, 3]
  e = a[i]
end

for の後ろの変数 i には in の後ろで与えられた配列の要素が順番に入ってくる。 が、それならわざわざこんな書き方をしなくても次のように書けばいい。

a = [0, 10, 20, 30]
for e in a
  # e には配列 a の要素が先頭から順に入ってくる
end

変数 i が消えてシンプルになった。変数 i がなくていいならそれに越したことはない。

しかし、実は Ruby では for はあまり使われない( Rails では積極に使われている模様だが)。上のようなコードは each を使って次のように表現することが多い。

a = [0, 10, 20, 30]
a.each do |e|
  # e には配列 a の要素が先頭から順に入ってくる
end

配列の要素すべてを先頭から順に puts メソッドで表示するなら次のように書けばいい。

a = [0, 10, 20, 30]
a.each do |e|
  puts e
end

each do 〜 end の部分には C 言語にはないややこしい話(かつとても興味深い話)があるのだけど、ややこしいので説明は後ほど。 |e| の | がなんなのかとか気になるかも知れないが、do 〜 end の中で使う値を受け取るのにこういう書き方をするという以外に深い意味はないので、もうこの形をまる覚えしてしまうのがいいだろう。

C 言語ユーザーから見れば for の方が自然か。しかし each の書き方は each に限らず他にもいろんなケースで使える形なのだ。

2006-10-30

配列

Ruby では配列をシンプルに表現することができる。

a = [0, 10, 20, 30]

文字列を扱う場合も同じ。

a = ['a', 'b', 'cde']

さらに配列の要素を特定の型で統一する必要がないので、数値や文字列を混在させることもできる。

a = [0, 'abc', 2]

配列はすべて配列型(Array型)であり要素の型はなんだっていい。

要素にアクセスする方法は C によく似ている。

a = [0, 'abc', 2]
p a[0]    #=> 0
p a[1]    #=> "abc"
p a[2]    #=> 2
2006-10-28

オブジェクトのコピー

b = a と書いて変数に変数を代入してもオブジェクトの複製が作られるわけではない。 b = a というのは a が示すオブジェクトに b という別名をつけているに過ぎない。

a = 'abc'
b = a
a.upcase!
p a       #=> "ABC"
p b       #=> "ABC"

a と b は同じオブジェクトにつけられた名前だ。まったく同じものを指している。a の実体は b の実体なので a が指し示すオブジェクトを破壊的に書き換えれば当然 b の内容も書き換わったことになる。

dup メソッドでオブジェクトのコピーを作り出すことができる。

a = 'abc'
b = a.dup
a.upcase!
p a       #=> "ABC"
p b       #=> "abc"

※ dup に似たメソッドに clone があるがその違いはリファレンスを参照されたい。

この場合 dup を使わなくても次のように書けば同じような結果が得られる。

a = 'abc'
b = a
a = a.upcase        #=> updase の戻り値に新たに a という名前をつける
p a       #=> "ABC"
p b       #=> "abc"

経験上 dup が必要になるケースは少ない。

2006-10-28

変数は箱じゃない

次の Ruby コードは C によく似ている。

a = 1
a += 2

しかし 1 行目の a が指し示すオブジェクトと 2 行目の a が指し示すオブジェクトは別物になる。

a = 1
p a.object_id  #=> 3
a += 2
p a.object_id  #=> 7

a というのはただの名前であって決して値の入れ物ではない。

a += 2

というのは

a = a + 2

であり、 a + 2 の結果として返るオブジェクトに a という名前をつけているわけだ。

int a;
a = 1;
a += 2;

それに対して C 言語 だと a に入っている値そのものに 2 を加算して a に入っている値をそのまま上書きする。 C に慣れすぎていたせいですべてが参照という世界はなかなか理解できないかった。

けどこんなことは知らなくても普通に C の感覚で Ruby のコードは書けてしまう。参照を知らずにコードを書いていたころも罠にはまったことはほとんどなかった。

2006-10-28

オブジェクトと変数

Ruby の変数は C の変数と違って箱ではない。オブジェクトを参照するための'何か'だ。その'何か'がなくなるとオブジェクトは自動的にメモリから消える。

a = 'abc'
a = 0     # 上で生成した文字列オブジェクトが消える

「オブジェクトを変数に代入する」ということは「オブジェクトに名前をつける」ということである、といってしまってもいいだろうか。

a = 'abc' # 文字列オブジェクトに a という名前をつける
b = a     # a が指している文字列オブジェクトに b という名前もつける
a = 0     # 0 に a という名前をつける
          # 'abc' には b という名前が残っているのでオブジェクトは消えない
b = 0     # 'abc' には名前がなくなってしまったので 'abc' が消滅!

ひとつのオブジェクトにはいくつでも名前をつけることが出来る。オブジェクトにつけた名前がひとつでも残っていれば、その名前でオブジェクトにアクセスできるしオブジェクトが消滅することはない。

def foo
  a = 'abc'
  return a
end

b = foo

C 言語だと関数の中の変数の内容はそのスコープ外では扱えないわけだが、Rubyの場合そんな不自由はない。Cの変数がメモリに割り当てられた絶対的なメモリスペース(値を保持するメモリそのもの)であるのに対して、Ruby の変数はオブジェクトにつけた名前に過ぎない。名前があればオブジェクトは生き残ることが出来る。メソッドの中で生成したオブジェクトもそのオブジェクトを指し示す名前が存在する限り生き続ける(名前が残っているということはそのオブジェクトにアクセスする手段を残しているということである)。

オブジェクトの名前がなくなってしまうともう2度とアクセスできない……かと思いきや変数名という名前がなくてもオブジェクトは生きていられる。

a = []     # 空の配列をつくり a という名前をつける
a << 'abc' # 配列に文字列オブジェクトを追加
a << 'xyz' 

a は配列オブジェクトの名前であって文字列オブジェクトの名前ではない。 文字列 'abc' は配列 a が所持しているのでアクセスすることが出来るし消えない。ただし配列 a が消えてしまうと文字列 'abc' も消えてしまう。

変数名がなくてもオブジェクトは生き残れる。オブジェクトが生き残れる条件とはなんなのだろう。噂のGCというやつと密接に関係していそうだ。

2006-10-28

Ruby の基本的なところ

ふだんなんとなく使っていた部分について少し深く考えてみる。

2006-10-24

[Ruby] Symbol#to_proc を使ってみる

cars.each {|car| car.draw }

が次のように書ける。

cars.each &:draw

暗号っぽいけどどうかな。上記のようなケースで配列の全要素に対して任意のメソッドを適用する方法は前からほしかった。

今後はこの方法で書くと思う。今までなかったから違和感があるだけかも。最初は {|e| e... } だって記号に見えてなかなか理解できなかったわけだし。

今はこう唱えてるけど、将来は標準になる模様。

class Symbol
  def to_proc
    Proc.new { |obj, *args| obj.send(self, *args) }
  end
end
2006-10-23

のだめ

面白い!

風のハルカといいマイボスといい今年はドラマの当たり年だ。 もしくはドラマはほとんど見てなかったから、面白いのがあることを知らなかっただけかも。

2006-10-19

バカが征く on Rails 復旧しました

春に旧サーバーPCが故障して以来停止していたのだが直した(現実逃避)。ついでに手直ししたらソースがどんどん短くなって 50 行に。ひな形のコードに手を入れているのは entry_controller.rb と 2 つのモデルだから書いたのは 42 行以下か(テンプレートは別)。 Rails すげー。

今回の修正で、本家サイトからテキストを落としてきてデータベースに突っ込むスクリプトは Rails から切り離した。このスクリプトは cron で呼ぶようにしてたので自動更新されるようになった。

ソース: http://dgames.jp/archive/bakagaikuonrails/

2006-10-18

[MyGame]キャラクタークラスの2Dアニメーション指定方法案

アニメーションパタンを横に並べた画像データをアニメーション毎に用意しておく。

man_stand.bmp
man_attack.bmp
man_run_left.bmp
man_run_right.bmp

次のようにしてファイルを指定。

class Man < MyGame::Character
  image_file_prefix 'images/man_'    # デフォルトは images/クラス名_
  image_width_height 48, 64          # デフォルトは (image_height, image_height)
  animation_shift :attack, :stand
  animation_wait :attack, 8, 8, 4, 8
end

規約を設けてしまうという考え方。

以下課題

  • アニメーションの表示フレーム時間をどう指定するか
    • → animation_wait
  • ループ指定をどうするか
    • → デフォルトがループ
  • アニメーションの遷移をどう表現するか
    • → animation_shift
2006-10-15

ホワイトボードに書いた台車が動きだす

http://rucila.s43.xrea.com/memo/?date=20061012#p01 経由。

http://www.youtube.com/watch?v=NZNTgglPbUA&eurl=

うおすげ。ネットワークゲームを作ったら次は物理シミュレーションのゲームを作ろうと思ってるんだけど(たぶん5年後くらいにスタート)、これはすごくイメージに近い。

2006-10-15

[プラポケ]この時間にアクティブな人の半数くらいの人がログイン済み

というのがすごい(午前9時)。上位25人中の約半数が既に今日の結果を確認しているようだ。

現在の登録数90。100まであとちょっと。

--

ゲームとしては最低限の形でまわっているけど、もっと機能追加していきたいなあ。暇になったらまたどかっとやりたい。

今のカード価格は人数が増えるとどんどん高騰するはず。参加人数が少ないことを想定したバランスなのでそろそろ調整を入れたほうがいいかも。とはいっても大きな害があるわけでなく、相対的にゲームの賞金とアイテム価格が安くなるということだから上位グレードと下位グレードの優位差が少なくなっているということかな。

2006-10-15

るりまオフライン検討会

に参加してきた。それなりに大きなプロジェクトっぽく今後どうなっていくのか興味深い。

2006-10-11

アサマシのチャンス

PFU Happy Hacking Keyboard Lite2 英語配列/白/PS2 PD-KB200W/P PFU Happy Hacking Keyboard Lite2 英語配列/白/USB PD-KB200W/U

Happy Hacking Keyboard Lite2 。

2006-10-08

[プラポケ]一部のカード画像が消えた

サーバーのディレクトリがいっぱいで整理してたら消しちゃった。 というかバージョン管理下に入ってなかった><

どっかにあったかな……。

2006-10-08

Visual C++ 2005 Express Edition

インストールしようとしたら XP の SP2 が必須と言われたので断念。 手元のノート PC は SP2 を入れるとなぜか重くなるので入れていない。休み明けに再挑戦しよう。

2006-10-07

Ruby/SDL 環境のセットアップメモ(2)

すごいことを思いついたんですよ。

先日はこんなことを書いたわけですが……。

デスクトップにある「ruby console」ショートカットを 解凍したディレク
トリ(install_rubysdl.rbがあるディ レクトリ)にコピーして、実行。起
動したDOS窓に以下のコマンドを打ち込む。

ruby install_rubysdl.rb

ActiveScriptRuby との組み合わせに限れば、こんなことをするまでもなく、

エクスプローラーで解凍したフォルダを開いて install_rubysdl.rb をダブ
ルクリック。

でいいじゃん。

2006-10-07

[Ruby]Windowsプログラミング

をほとんどやったことがないもので dll とかその互換性とかぜんぜん知らない。

勉強のために Ruby/SDL が動く環境を自分でソースからコンパイルしてみるといいのではないだろうか。まずはコンパイラを入手しないとなあ。さてどうしよう。

2006-10-03

Ruby勉強会@関西-12

面白そう……。行きたいけどさすがに関西じゃおいそれとは行けない><

2006-10-03

nadoka 0.7.0 リリース

いつも svn から最新版をとってきて使ってるから個人的にはとくにどうということはないのだけど、おめでとうございます。

2006-10-03

Ruby/SDL + Exerb に再挑戦

やっと成功した(わかってしまえば何も難しいことはない><)のでメモ。使用したのは以下の Ruby と Ruby/SDL 。 exerb は ActiveScriptRuby に同梱されているものをそのまま使用。

  • ActiveScriptRuby 1.8.4.5
  • Ruby/SDL Win32's binary(ver 1.2.0) for Ruby 1.8

1.8.4 と 1.8.5 で拡張ライブラリの互換性があるのかどうかわからなかったので ASR もいちおう 1.8.4 にした。

Ruby/SDLはMyGameでラップ。 次のような Ruby スクリプトとレシピファイル(erb)を用意する。

test.rb

require 'mygame/boot'

test.rexy

general:
  startup: test.rb
  core: gui
  kcode: none

file:
  test.rb:
  mygame.rb:
  mygame/boot.rb:
  sdl.rb:
    file: C:/ruby-1.8/lib/ruby/site_ruby/1.8/sdl.rb
  sdl.so:
    file: C:/ruby-1.8/lib/ruby/site_ruby/1.8/i386-msvcrt/sdl.so
    type: extension-library
  forwardable.rb:
    file: C:/ruby-1.8/lib/ruby/1.8/forwardable.rb
  rubysdl_aliases.rb:
    file: C:/ruby-1.8/lib/ruby/site_ruby/1.8/rubysdl_aliases.rb
  kconv.rb:
    file: C:/ruby-1.8/lib/ruby/1.8/kconv.rb
  nkf.so:
    file: C:/ruby-1.8/lib/ruby/1.8/i386-mswin32/nkf.so
    type: extension-library
  <% %w(SDL_ttf    iconv       sdlskk    zlib1
        SDL_image  SGE         jpeg      smpeg
        SDL_mixer  freetype-6  libpng13  zlib).each do |name|
  %>
  <%= name %>.dll:
    file: C:/ruby-1.8/bin/<%= name %>.dll
    type: extension-library
  <% end %>

以下を実行。

erb test.rexy > test.exy
exerb test.exy

test.exe が作成される。実行環境には test.exe ファイルとともに以下の dll も置く。

SDL.dll
MSVCP71.DLL
msvcr71.dll

SDL.dll はレシピに追加せず、それ以外の SDL 関係の dll は全部 exe 化した。

2006-10-03

Ruby/SDL 環境のセットアップメモ

ゲームプログラミングをやってみたいけどプログラムをまったく知らないという人に Ruby/SDL がいいよって言いたいときの話、インストール編。

ActiveScriptRubyをインストール

http://arton.hp.infoseek.co.jp/indexj.html から。 インストールは簡単。

参考↓

http://www.atdot.net/~ko1/diary/200608.html#d8

Ruby/SDLのダウンロードとインストール

http://www.kmc.gr.jp/~ohai/rubysdl_download.html からダウンロードできる。

ActiveScriptRubyのバージョンとRuby/SDLバイナリのバージョンに注意。現時点だとActiveScriptRubyは最新が1.8.5でRuby/SDLバイナリは最新が1.8.4という罠(なのかな……?)。

Ruby/SDLの「Win32's binary(ver 1.2.0) for Ruby 1.8」をダウンロードして解凍。デスクトップにある「ruby console」ショートカットを解凍したディレクトリ(install_rubysdl.rbがあるディレクトリ)にコピーして、実行。起動したDOS窓に以下のコマンドを打ち込む。

ruby install_rubysdl.rb

これで先ほどインストールしたActiveScriptRubyに必要なファイルがコピーされるはず。

dll が見つからない問題

ruby -r sdl -e ""

実行してみると環境によってはエラーが発生。

  • MSVCR71.dll が見つからなかったため、(ry
  • msvcp71.dll が見つからなかったため、(ry

うーん。 http://yy10.kakiko.com/test/read.cgi/ff11/1143561685/187n-198n

このdllはRuby/SDLのバイナリに同梱してもらうのがいいのかな。 このエラーいつも出るのだけど、みんなのPCには入っているのか……。Windowsの開発環境持ってないからなあ><

2006-10-02

[プラポケ]カード入手画面を微調整

そうそう、昨日少し手を入れた。新規カード入手画面でもソートが出来てしまったり、ポケットへの入れ方がわからないという意見に対応。

バグ報告が出ていないようなので無事に動いているのかな。