Jewel-mmo開発日記

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

[開発ログ] ASR でプリミティブの描画テスト

2D プリミティブ(文字、画像、長方形)は表示出来た。 現状で Tk よりよいと思う点は

  • 画像の拡大縮小表示ができる
  • アニメーションに GIF アニメが使える
  • HTML なので馴染みやすい
  • IE の安定感
  • HTML なのでフラッシュムービーとか音も簡単に組み込めそう
  • 最終的に JavaScript に移植すれば非常に多くの環境で動く

あたりだろうか。デメリットとしては Tk は多角形(ポリゴン)が表示できたが HTML ではできなそう。

上記 2 つが嬉しくて、これができるとドラクエ 7 のような 3D っぽいキャラクタ表示が可能。

この手の実験的なコードを日記に張っておくと後にたいへん役立つので実験用スクリプトを張っておく。 Prim のインターフェースはまだまだいい加減。

test.hta

<html>
<head>
  <HTA:APPLICATION ID="ERProt"
    ApplicationName="ERProtOnASR"
  />
<script language="RubyScript">
$KCODE = "SJIS"
require 'main.rb'
</script>
</head>
<body onload="init" language="RubyScript">
<div id="top_div"></div>
</body>
</html>

main.rb

require 'er.rb'

def main_loop
	@counter += 1
	@font.elm.style.top = @counter * 4 % 480
end

def init
	@screen = init_window(640, 480, '#ccccff')
	@counter = 0

	@cwin = @screen.create_prim Box, :box01, 0,@screen.h-100,0, @screen.w-16, 100-16, '#ffcccc'
	@cwin.margin = "8 8"
	@cwin.padding = "8 8"
	@cwin.onmouseover = "__self__.test00"
	@cwin.create_prim Font, :id00, 0,0,0, 16, 'ABC'*20

	@font = Font.new :id01, 100,120,0, 16, 'ABC'
	@screen.add_prim @font
	@font.create_prim Font, :id02, 100,140,0, 16, 'ABC'
	@screen.create_prim Image, :image00, 140,100,0, 'i_31.gif'

	start_window(50, :main_loop)if @window
end

if $0 == __FILE__
	init
	puts @screen.html
end

er.rb

class Prim
	attr_accessor :id, :str, :src
	attr_accessor :margin, :padding, :bgcolor
	attr_accessor :position_type, :x, :y, :z, :w, :h, :size
	attr_accessor :onmouseover
	@@prims = {}
	@@window = nil
	def self.find(id)
		@@prims[id]
	end

	def self.window=(win)
		@@window = win
	end

	def initialize *arg
		@prims = []
		@html_tag = 'div'
		@position_type = 'absolute'
		([:id] + initialize_params).each do |meth|
			break unless v = arg.shift
			__send__ "#{meth}=", v
		end

		raise unless id.is_a? Symbol
		raise id.inspect if @@prims[id]
		@@prims[id] = self
	end

	def initialize_params
		[:x, :y, :z, :size, :str]
	end

	def create_prim klass, *arg
		@prims <<	klass.new(*arg)
		@prims.last
	end

	def add_prim prim
		@prims << prim
	end

	def inside_of_html
		str
	end

	def style_params
		params = []
		{
			:margin => 'margin',
			:padding => 'padding',
			:position_type => 'position',
			:y => 'top',
			:x => 'left',
			:w => 'width',
			:h => 'height',
			:bgcolor => 'background-color',
		}.each do |k, v|
			if __send__ k
				params << "#{v}:#{__send__ k}; "
			end
		end
		params
	end

	def events
		params = []
		{
			:onmouseover => 'onmouseover',
			#:setInterval => 'setInterval',
		}.each do |k, v|
			value = __send__ k
			if value
				params << %Q|#{v}="#{value.gsub('__self__', "Prim.find(:#{id})")}" |
			end
		end
		params
	end

	def html
		%Q|<#{@html_tag} id="#{id}" language="RubyScript" #{events.join}style="#{style_params.join}">\n#{inside_of_html}#{children_html}</#{@html_tag}>|
	end

	def children_html
		@prims.map{|prim| prim.html}.join("\n")
	end

	def elm
		@elm ||= @@window.__send__ id
	end

	def test00
		elm.style.width = "200"
		elm.style.backgroundColor = "#FF0000"
	end
end

class Font < Prim
end

class Box < Prim
	def initialize_params
		[:x, :y, :z, :w, :h, :bgcolor]
	end
end

class Image < Prim
	def initialize_params
		[:x, :y, :z, :src]
	end

	def inside_of_html
		%Q|<img src="#{src}">|
	end
end

def init_window(w, h, bgcolor)
	if @window
		Prim.window = @window
		@top_div = @window.top_div
		@window.resizeTo w+40, h+40
	end
	Box.new :__screen__, 0,0,0, w,h, bgcolor
end

def start_window(interval, func)
	@top_div.innerHTML = @screen.html
	@timer = @window.setInterval func.to_s, interval, "RubyScript"
end