Hatena::ブログ(Diary)

mirichiの日記 このページをアンテナに追加 RSSフィード

2010-07-25

Flash用のなにか

最近、Flashの勉強をしている。

と言ってもActionScriptは全然で、Flashのswfファイル解析、swf内のABC(ActiondcriptByteCode)解析みたいなこと。

FlexだってActionScriptをコンパイルしてswfを吐き出しているわけだから、これらの構造さえ理解できて出力することができれば、ActionScript以外の言語をコンパイルして動かすことができるのではないか。

例えばFlash用SchemeコンパイラHappyABCのような。

http://happyabc.org/


んでも、俺が考えることと言えば今も昔も一貫して「Rubyでゲームプログラミング」なわけだ。

つまりswfを吐き出すRubyコンパイラを作ってみたい。

もしRubyでゲームを作って、それがswfファイルになって、ブラウザで遊べるのならば、ゲームの配布とかの問題も無くなる。

実際にできるのかどうか、実行速度はどの程度なのか、というのはよくわからないが、とりあえずやってみないことには話にならない。


いまのところ、AVM2の仕様書を見ながらファイルの内容の解析はある程度できた。

仕様書の記述があいまいだから、FlexSDKを突っ込んでActionScriptをコンパイルしてどういうコードが出るのかを調べているところ。

ActionScriptも触ったことないし、Flashの予備知識も無しで、言語処理系なんか作ったこと無いっつー状態からのスタートで、果たして動くものができるのか、と思わないでもない。

きちんとした完成度の高いものができるとはちょっと思えないが、まあ、何か動けばいいだろう。そんな程度で。


ちなみにFlashPlayerで動作するswfを出力するRubyコンパイラは、Flash7時代のでよければ既にある。

http://sourceforge.net/projects/rubyonflash/

2010-07-20

SWFファイルのヘッダ

とーとつにFlashに興味が沸いたので手始めにヘッダを解析してみた。

問題なのは興味の対象がFlashであってASではないところだ。

require 'zlib'

class SWF
  attr_reader :version, :length, :x_min, :x_max, :y_min, :y_max, :frame_rate, :frame_count

  def initialize(filename)
    # swfファイルの読み込み
    open(filename, 'rb') do |fh|
      @bin = fh.read
    end

    # シグネチャ判定
    case @bin[0, 3]
      when 'CWS' # CWS(圧縮形式)であれば展開してFWSに変換する
        @bin = 'F' + @bin[1, 7] + Zlib::Inflate.inflate(@bin[8..-1])
      when 'FWS' # FWS(通常形式)であればそのままにする
        # 処理なし
      else
        raise "swf形式のファイルではありません"
    end

    # バージョン情報
    @version = @bin[3, 1]

    # ファイルの長さ
    @length = @bin[4, 4].unpack('V')[0]

    # ヘッダのRECT型
    nbits = @bin[8, 1].unpack('B*')[0].to_s[0, 5].to_i(2)
    rect_size = (nbits * 4 + 5 + 7) / 8
    rect = @bin[8, rect_size].unpack('B*')[0].to_s[5..-1]
    @x_min = rect[0, nbits].to_i(2)
    @x_max = rect[nbits, nbits].to_i(2)
    @y_min = rect[nbits * 2, nbits].to_i(2)
    @y_max = rect[nbits * 3, nbits].to_i(2)

    # フレームレート
    @frame_rate = @bin[8 + rect_size, 2].unpack('v')[0] / 256.0

    # フレーム数
    @frame_count = @bin[8 + rect_size + 2, 2].unpack('v')[0]
  end
end

swf = SWF.new('Hello.swf')

puts "version     : #{swf.version.unpack('C')[0]}"
puts "length      : #{swf.length}"
puts "x_min       : #{swf.x_min}"
puts "x_max       : #{swf.x_max}"
puts "y_min       : #{swf.y_min}"
puts "y_max       : #{swf.y_max}"
puts "frame_rate  : #{swf.frame_rate}"
puts "frame_count : #{swf.frame_count}"

#=

2010-07-17

少しできた。

先日のサンプルの続きを作っていた。

とりあえず本家サンプルのStage1〜7プラスExtraという構成のうち、Stage1だけできた。

http://dxruby.sourceforge.jp/files/AAM_DXRuby_Sample.zip

ただ、絵については本家のものを使うから、本に付属しているCDからTextureディレクトリをコピーしなければならない。(ダウンロードできるようにはなってない)


同梱してあるのはRuby1.9.1とDXRuby1.2(trunk)を含んだDXRubyスターターキット。

本家の動作をできる限りそのまま再現しようとしたらWindow.draw_morphを使う必要があって、こうするしかなかった。

そのかわり、本家の仕組みはできる限りそのまま再現した。少なくともStage1.hのコードはほぼそのままのアルゴリズム・クラス構成になっている。文字描画とかそのへんは手を抜いてるし、色も反転してるけど、それは今後どうにかしようと思う。


「Stage1.hのコードはほぼそのままのアルゴリズム・クラス構成である」

アクションゲームアルゴリズムマニアックスのサンプルをRubyで書く、という試みだからそうした。

決して、このサンプルが書き直しの必要が無いほど素晴らしいデキである、と言っているわけではない。

またRubyで書くという面でも、このコードはRubyらしくないし(だって元はC++だし)、DXRubyの機能を使えばもっとスマートに書けるところもある。

それらを踏まえて、あえて、そのままにした。コメントはサンプルコードのファイルのほうには全く入っていなかったから、本を参考に追加しておいた。


Rubyぽく書き直すもよし、自分流に作り直すもよし。なによりもまず、動くモノがそこにある、というところからスタートする必要がある。

ケチを付けて修正する前に、まずはそのまま動かして、理解するところから始める。

なんだかんだ言ってゲーム作ることに関しては素人だから、自分の勉強としてやってるだけだ。

ついでに人の役に立てばいいなあ、みたいな。