Jewel-mmo開発日記

RubyでMMORPGを作る過程を記録する日記。 Yokohama.rb 発起人。
2008-03-31

Rubyist Magazine 0023 号

http://jp.rubyist.net/magazine/?0023

でてますよ!

2008-03-30

大河ドラマの篤姫

もともと篤姫役の宮崎あおいが好きで見たいたんだけど、 途中から宮崎あおい演じる篤姫が良くなった。

ここ数話は高橋英樹、松坂慶子とのからみが中心だった。 ベテラン俳優に触発され何かが変わったのかそうでないのかわからないけど、面白くなった。

2008-03-30

[プラポケ]第一回イベント終了のお知らせ

http://dgames.jp/pockets/

プラポケのステージ11のポイントの集計が終わりました。

入賞者は次の通りです。

  1. jowcol(土) …… Amazonギフト券5000円プレゼント
  2. testman(風) …… Amazonギフト券2000円プレゼント
  3. moriq(土) …… Amazonギフト券500円プレゼント

おめでとうございます。 参加してくださった皆様どうもありがとうございました。

次回のイベント開催を予定しています。次回はステージ14がイベントステージになる予定です。

  • ステージ12 …… 20日間
  • ステージ13 …… 20日間
  • ステージ14 …… 20日間

上記スケジュールは暫定なので変更される予定があります。

2008-03-27

[Bilbo]ぼちぼちやりたいと思っていること

  • tDiaryからコメントデータをインポート
  • コメントスパムのフィルタリング機構を作る
  • コメント用RSSはなぜ更新してないやつまでLDRに上がってくるんだろう
  • CodeReposにBilboをリリース
2008-03-22

明日はこれに参加させてもらう予定です

http://www5.atwiki.jp/yaruhara/

13時はちょっときついので遅れて参加する予定です。 よろしくお願いします。

2008-03-22

[Bilbo]BilboのMVC

http://mt.endeworks.jp/d-6/2008/03/db-1.html

BilboはDBを使わないけどMVCで実装している。

良い機会なのでBilboの超シンプルなMVCの実装を紹介。 このMVCを実現してるコア(bilbo.rb)は81行。

モデル

日記の記事はモデルとして管理される。具体的にはEntryクラスが記事を扱うモデルである。

entries = Entry.find('200803', :limit => 5)

こんな風にすると2008年3月の記事オブジェクトを5個取り出すことができる。

このEntryクラスの実装は30行。 この30行には、記事をHTMLに変換するコンパイラの登録と変換処理も含まれている。 このEntryクラスはBilboにとって最大の機構。30行なんて長すぎるのでコードは省略。

記事オブジェクトは次のようにしてHTML化できる。

entries.first.to_html

原稿のコンパイラは設定ファイル(bilborc)で指定する。 次のコードはHikiDocを登録する例。

require 'misc/hikidoc.rb'
Entry.add_compiler('.txt') {|entry|
  HikiDoc.to_html(entry.body, :level => 2)
}

拡張子「.txt」の原稿をHikiDocでHTML化する。

ビュー

ビューはいたってシンプル。4行で実装されている。

def render_view(name, b = binding)
  erb = Plugin.views[name] || (chdir(:views) { File.read("#{name}.html.erb") })
  ERB.new(erb).result(b) rescue "<h3>ViewError in #{h name}</h3>#{h $!}<pre>#{$@.join("\n")}</pre>"
end

HTMLテンプレートをERBにてレンダリング。

コントローラ

これも短いので、コードを全行貼ってしまったほうが話が早い。

class Controller
  def list
    @entries = Entry.find(params[:date] || '20',
                          :limit => (params[:limit] || config[:limit] || 5).to_i,
                          :page => (params[:page] || 0).to_i)
    render(:list)
  end

  def render(action)
    render_view(:layout) { render_view(action) }
  end
end

デフォルトのアクションとしてlistを定義してあって、あと基本描画にレイアウトファイル(layout.html.erb)にアクション用のテンプレートを埋め込む。

そしてこのコントローラを呼び出すのが以下の部分。 CGIから渡されたactionパラメータをもとにControllerクラスに定義されているメソッドを呼び出す。

def default_action
  :list
end

def action_name # support: ruby 1.8 and 1.9
  action = (params[:action] || params.index(nil) || 'list').to_sym
  Controller.instance_methods(false).map(&:to_sym).include?(action) ? action : default_action
end

def bilbo_context
  Plugin.load
  Controller.new.__send__(action_name)
end

プラグインの中でControllerクラスのインスタンスメソッドを定義してやれば、 それがアクションとしてすぐに呼び出せてしまう。 よってプラグインによる機能追加かがとっても容易。

2008-03-21

Star Rubyを使ってみる

http://www.starruby.info

フォントとテクスチャーを表示してみる。APIがいい感じだ。 Rubyを知っている人間にとってはMyGameより使いやすい。

Colorの生成は、Color[255, 255, 255]と書けないのかな。

require "starruby"
include StarRuby

font = Font.new("fonts/ORANGEKI", 12)
white = Color.new(255, 255, 255)
texture = Texture.load("images/star")

Game.title = "Hello, World!"

angle = 0
Game.run(320, 240) do
  Game.terminate if Input.keys(:keyboard).include?(:escape)
  Game.screen.clear
  Game.screen.render_text("Hello, World!", 8, 8, font, white)
  Game.screen.render_texture(texture, 100, 100, :alpha => 200,
                                                :angle => (angle += 4) / 180.0 * Math::PI,
                                                :center_x => 8,
                                                :center_y => 8,
                                                :scale_x => 8.0,
                                                :scale_y => 8.0)
end
2008-03-21

starruby-0.1.16-win32.zipのインストーラでこける

http://code.google.com/p/starruby/downloads/list

...\starruby-0.1.16-win32>ruby install.rb
install.rb:14: syntax error, unexpected kDO, expecting $end
Dir["dll/*.dll"] do |path|
                   ^
>ruby -v
ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32]
2008-03-19

[Bilbo]コメントオン

Bilboでテスト運用中の本ブログにコメントプラグインを投入。 まだ実験段階なので、不都合があると消すことがあるかも。 スパムに対しても何の対策もしてないので、スパムが大量に来た場合も一括削除しちゃうかも。

スパム対策はスパムが来てから考える。

あと、RSSでコメントを配信するようにしてる。本文とまぜちゃうとスパムが来たときに問題がありそうなので、コメント用に専用のRSSを用意してみた。

http://dgames.jp/dan/?rss_comments

必要な機能をさくっとプラグインで簡単に追加できるというのが夢だったのだけど、いまのところうまくいっている。 今回コメントのRSS配信用に追加したコードは以下。

class Controller
  def rss_comments
    generate_rss(Comment.find('20*'), :title => "Comments - #{config[:title]}")
  end
end

class Comment
  def rss_description(n = 128)
    body[0, n]
  end

  def rss_tile
    name
  end

  def date
    Date.parse(@filename.to_s[/\A\d{8}/])
  end
end

Plugin.add_hook(:header) {
  %Q!<link rel="alternate" type="application/rss+xml" title="RSS" href="?rss_comments">!
}
2008-03-17

[Bilbo]記事タイトルをページタイトルに付加する

permalinkアクションで記事タイトルをグローバル変数に保存し、フック処理から呼び出す。

$permalink_title = nil
class Controller
  def permalink
    @entry = Entry.find(params[:date], :limit => 1, :complete_label => true).first
    $permalink_title = @entry.title
    render(:entry)
  end
end

Plugin.add_hook(:before_header) {
  if $permalink_title
    "<head><title>#{$permalink_title} - #{config[:title]}</title></head>"
  end
}

うーん、グローバル変数を使わずに、アクションメソッド内の変数をフック処理に渡せないものか……。

あ、これでいいのか。

class Controller
  def permalink
    @entry = Entry.find(params[:date], :limit => 1, :complete_label => true).first
    Plugin.add_hook(:before_header) {
      "<head><title>#{@entry.title} - #{config[:title]}</title></head>"
    }
    render(:entry)
  end
end
2008-03-15

[Bilbo]後方互換と前方互換

BilboはtDiaryスタイルのURLに対する後方互換性をサポートする。

2008年1月23日の1つ目のエントリのURLは上のようになる。 BilboはtDiaryスタイルのURLも受け付けるけど、正式なパーマリンクはtDiaryとは異なる。 Bilboは同日に複数のエントリが合った場合、それぞれのエントリを個別に管理する。 だからコメントも日付単位じゃなくて個別のエントリに対して付けることができる。

で、当然なんだけどtDiaryはBilboに対する前方互換性がない。 本サイトでBilboのテストをしているわだが、すでにBilboスタイルのパーマリンクに対して外のサイトがリンクしていて、 tDiaryに戻すと問題が発生することに気がついた。 まあたぶん戻さずに済みそうだけど。

2008-03-14

[プラポケ]サーバー障害のお知らせ

本日19時〜22時くらいまでの間、雷雨のため回線を落としていたため、サーバーに接続できない状態になっていました。

2008-03-14

言うまでもありませんが

最適化なんてのはもってのほかです。

いいんですよRubyで。遅くて困ったらそのときCで書き換えればいいんです。Ruby+C最強。

2008-03-14

Pencil Bullet

ohaiさんがシューティングゲームを公開。Dかあ。

オレはいまアクションゲームを作ろうとアイデア練ってます。Star Rubyでいきます。

2008-03-14

仕事は1日3時間

http://q.hatena.ne.jp/1203667934

自分の場合、自分が1日に働ける時間が3時間しかないことに気づいたのが大きかったかな。 90分を2本。これが限界。これよりあとは仕事をしてる気分になるだけで仕事はあまり進まない。 集中力よりも単に時間をかけることが重要なときもあるので、これはあくまで個人作業を理想状態でできるときの話しだけど。

自分にとってのポイントは2つあって、ひとつは集中できる状態でしかコードを書かないようにすること。 集中力の切れた状態でコードを書くとバグがバグを呼ぶようなひどい状態になる。 半日悩んだ問題が、翌日冷静に考えてみれば、根本的に不要な作業だったりとか。 これは勝手にいらん仕事作って勝手にはまってる状態。 最高の集中状態でしかコードを書かないこと。 質の低いコードをプロジェクトに混入させないことで、生産性が高くなる。

もうひとつは、なんというか、遅延実装。必要になるギリギリまでコードを書かない。 仕様は常に変わるので、今必要と思われる機能が本当に必要かどうかは怪しい。 だから実装は限界ギリギリまで先延ばしする。 ただし、現在の仕様を実装するのにどれだけの時間が必要かを正確に見積もっておくことが必要。 技術的に問題になりそうな部分は、あらかじめすべて解決しておかなければならない。 検証はしっかりやるけど最後まで実装はしない。 暇だからって「こんなのあったら便利そうだから作っとくか〜」みないな事は絶対にやらない。 コードが増えるとメンテナンスのコストが増える。 あと問題の解決に常に最善の策を追求すべきで、暇に任せて必要かどうかわからないコードをコミットしちゃいけない。 一度書いたコードとかツールは、なんとなく使いたくなって、プロジェクトが余計な実装に引きづられる。 最善の解決方法を追求する妨げになりえる。 でもこっちは仕事のタイプによりけりかも。

仕事をしている気分になること(あと他人から仕事をしているように見えること)と実際の仕事を混同しちゃいけない。 というのが今現在の自分の考え。

2008-03-13

[Bilbo]Bilbo試験中

試験的に本日記をBilboで運用してます。

コメント機能はアツイので切ってあります。少ししたら実験的にコメント機能を有効にします。

tDiaryの記事を全部インポートしたときの動作速度が心配だった(最適化はやってない)のだけど、特に問題なさそうだなあ。

2008-03-09

[Bilbo]だいぶ形になってきた

http://dgames.jp/bilbo/

これまでずっと日記をブラウザから書いてたんだけど(このエントリもブラウザから書いている)、日記の記事をテキストファイルにしてSubversionで管理したいというのがことの始まりだったかな。

一年くらい前に軽く実装して、それきり拡張することなく職場での個人的なログ管理にだけ使っていた。ここ数日いろいろ手直しして、だいぶ形になってきた。ここ数日でかなり改造したつもりだったけど、コアのbilbo.rbはほとんど書き換えずにすんだから、なかなか良い実装なのかもしれない。

とりあえずサービスだけ公開して、少し様子を見てからCodeReposに突っ込む予定。本当ももっと早く形にしたかったのだけど、ごく最近まで余裕がなかった。

2008-03-07

[プラポケ]本戦明日から

明日から本戦が始まります。

  • 1位……Amazonギフト券5000円をプレゼント
  • 2位……Amazonギフト券2000円をプレゼント
  • 3位……Amazonギフト券500円をプレゼント

昨日アクセスしているユーザーは26名です。

2008-03-06

[ruby][Debian]Rubyのアップデート

wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p114.tar.bz2
tar -xvjpf ruby-1.8.6-p114.tar.bz2

RubyGemsを入れてから、

gem install rails
gem install sqlite3-ruby

これでプラポケは動く。

2008-03-05

[開発ログ][todo]todo

  • ヘッダーとフッターのテンプレート機構
2008-03-05

[開発ログ]プラグインのフック

複雑なので修正。

before

  @@hook_plugins = Hash[ *%w(
    before_content after_content before_entry after_entry before_entries after_entries
  ).inject([]) {|t, e| t << e.to_sym; t << []; t } ]
  def self.add_hook(key, priority = 128, &block)
    @@hook_plugins[key] << block
  end

  def self.render_hook(key, *args)
    %Q!<div class="#{key}">#{ @@hook_plugins[key.to_sym].map {|e| e.call(*args) }.join("\n") }</div>!
  end

after

  @@hook_procs = {}
  def self.add_hook(key, priority = 128, &block)
    @@hook_procs[key] ||= []
    @@hook_procs[key] << block
  end

  def self.render_hook(key, *args)
    @@hook_procs[key] or return ''
    @@hook_procs[key].map {|e| e.call(*args) }.join("\n")
  end

存在しないエントリーポイントに対して、render_hookしたときにエラーにしたかったんだけど、その機能はカット。

divタグで囲むのをやめた。 divタグなしのフックエントリを挿入できなくて悩んでたけど、 その辺はビューで解決すべきと判断した。

priorityは未実装。 プラグインの実行順序は、ファイル名で操作できるからいらない気もする。

after2

@@hook_procs[key] or return ''
@@hook_procs[key].map {|e| e.call(*args) }.join("\n")

上の部分はもうちょっとなんとかならないか。

@@hook_procs[key] ? @@hook_procs[key].map {|e| e.call(*args) }.join("\n") : ''

1行になった。

(a = @@hook_procs[key]) ? a.map {|e| e.call(*args) }.join("\n") : ''

ちょっと短くなった。

(@@hook_procs[key] or []).map {|e| e.call(*args) }.join("\n")

さらに短くできた!

(@@hook_procs[key] or []).map(&:call, *args).join("\n")

こうは書けないんだよなあ。 Symbol#to_procに引数を渡すのできないよね?