2010-07-25
Flash用のなにか
最近、Flashの勉強をしている。
と言ってもActionScriptは全然で、Flashのswfファイル解析、swf内のABC(ActiondcriptByteCode)解析みたいなこと。
FlexだってActionScriptをコンパイルしてswfを吐き出しているわけだから、これらの構造さえ理解できて出力することができれば、ActionScript以外の言語をコンパイルして動かすことができるのではないか。
例えばFlash用SchemeコンパイラHappyABCのような。
んでも、俺が考えることと言えば今も昔も一貫して「Rubyでゲームプログラミング」なわけだ。
つまりswfを吐き出すRubyコンパイラを作ってみたい。
もしRubyでゲームを作って、それがswfファイルになって、ブラウザで遊べるのならば、ゲームの配布とかの問題も無くなる。
実際にできるのかどうか、実行速度はどの程度なのか、というのはよくわからないが、とりあえずやってみないことには話にならない。
いまのところ、AVM2の仕様書を見ながらファイルの内容の解析はある程度できた。
仕様書の記述があいまいだから、FlexSDKを突っ込んでActionScriptをコンパイルしてどういうコードが出るのかを調べているところ。
ActionScriptも触ったことないし、Flashの予備知識も無しで、言語処理系なんか作ったこと無いっつー状態からのスタートで、果たして動くものができるのか、と思わないでもない。
きちんとした完成度の高いものができるとはちょっと思えないが、まあ、何か動けばいいだろう。そんな程度で。
ちなみにFlashPlayerで動作するswfを出力するRubyコンパイラは、Flash7時代のでよければ既にある。
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ぽく書き直すもよし、自分流に作り直すもよし。なによりもまず、動くモノがそこにある、というところからスタートする必要がある。
ケチを付けて修正する前に、まずはそのまま動かして、理解するところから始める。
なんだかんだ言ってゲーム作ることに関しては素人だから、自分の勉強としてやってるだけだ。
ついでに人の役に立てばいいなあ、みたいな。