DTLの自作レンダラの実験
いいスクリーンショットがなかなか撮れない。のでgif動画にしてみた。
土屋つかささんのdxruby_text_layerを使って、独自レンダラを書いて、この間のmieki256さんのSTGサンプルのステージクリアの文字みたいな動きを(アルゴリズムパクって)作ってみた。それ以外のコードはDTLサンプルからパクった。パクりまくりである。
ざっくり作っただけだからもうちょい効果的な感じに調整する必要はあるのだろうけど、とりあえず動いたかなーという感じ。
現状では文字レンダラ側から描画先のサイズが取得できないところが地味に問題だけど、それはまあ、別に汎用的である必要も無いんじゃないかと思うので使う人がいたら自分で調整してください。
画面から出たときに描画する必要は無いだろうから、@stateが:endになったら描画しないようにするとちょっと無駄が無くなるかもしれない。@non_active_textから消し去りたい気もするが。
あとたぶん、元のアルゴリズムは画面の中央あたりに描画するためのモノで、画面の任意の位置に描画する場合はちょっと考え直す必要があるのだと思う。
require 'dxruby' require './dxruby_text_layer' class HogeCharRenderer < Char_renderer_base def initialize( x, y, char, font, font_config, is_skip, mode, options = {}) @width, @height, offset_x, offset_y = normalize_image(char, font, font_config) @ex = x - offset_x + @width / 2 @ey = y - offset_y + @height / 2 rad = Math.atan2(240 - @ey, 320 - @ex) @x = @ex + Math.cos(rad) * 800 @y = @ey + Math.sin(rad) * 800 @dx = -Math.cos(rad) * 4 @dy = -Math.sin(rad) * 4 @scale = 8.0 @image = Image.new(@width, @height) @image.draw_font_ex(offset_x, offset_y, char, font, font_config) @state = :start end def update case @state when :start d = 0.2 @x += (@ex - @x) * d @y += (@ey - @y) * d @scale += (1.0 - @scale) * 0.2 if (@ex - @x).abs < 1.0 and (@ey - @y).abs < 1.0 @x = @ex @y = @ey @scale = 1 @state = :active end when :active when :non_active @x += @dx @y += @dy @dx *= 1.15 @dy *= 1.15 @scale *= 0.98 if @x < -100 or @x > 740 or @y < -200 or @y > 580 @state = :end end when :end end end def draw(rt) rt.draw_scale(@x - @width / 2, @y - @height / 2, @image, @scale, @scale) end def start_non_active @state = :non_active end end #テキストレイヤ生成 layer = Dxruby_text_layer.new(640, 480, :char_renderer=>HogeCharRenderer) commands = [ [:line_feed, nil], [:line_feed, nil], [:text, :text =>"自作文字レンダラテスト"], [:line_feed, nil], [:text, :text =>"こんな感じに動く■"], [:stop, nil], [:clear_active_text, nil], [:line_feed, nil], [:text, :text =>"ちょっと思ってたのと違うけど"], [:line_feed, nil], [:text, :text =>"まあいいか■"], [:stop, nil], [:clear_active_text, nil], [:line_feed, nil], [:text, :text =>"かなり無理矢理感があるぞ"], [:line_feed, nil], [:text, :text =>"でも動いたからOKOK"], [:stop, nil], [:clear_active_text, nil], ] #ゲームループ Window.loop do #テキストレイヤが処理を停止していて、かつスペースキーが入力された場合。 if layer.stop? and Input.key_push?(K_SPACE) #コマンドの処理 loop do #コマンド配列が空ならループを抜ける break if commands.empty? #コマンドを取り出す command = commands.shift case command[0] when :stop #シナリオの読み取りを一時停止し、描画終了まで待機状態に入る。 break when :text #文字列を分解してcharコマンドに変換する command[1][:text].each_char do |ch| #コマンドをスタックする layer.stack_command(:char, {:char => ch}) end else #他のコマンドはテキストレイヤが処理するとしてコマンドをスタックする layer.stack_command(command[0],command[1]) end end end #テキストレイヤ処理 layer.update #テキストレイヤ描画 Window.draw(0, 0, layer.image) end