#============================================================================== # ■ Textview #------------------------------------------------------------------------------ #  文字表示クラス #============================================================================== class Textview #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_accessor :autdispose #on_changeがfalseなら自動でdisposeするフラグ attr_accessor :autemphasis #文字列が変更したら自動で強調表示するフラグ attr_reader :x #x座標 attr_reader :y #y座標 attr_reader :z #z座標 attr_reader :zoom_x #拡大率x attr_reader :zoom_y #拡大率y attr_reader :color #ブレンド色 attr_reader :opacity #透明度 attr_reader :on_change #↓の何れかがtrueならtrueを返す attr_reader :on_change_place #座標移動中ならtrueを返す attr_reader :on_change_color #色変更中ならtrueを返す attr_reader :on_change_zoom #拡大縮小中ならtrueを返す attr_reader :on_change_opacity #透明度変更中ならtrueを返す attr_reader :on_flash #フラッシュ進行中ならtrueを返す #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(x,y,z, value, pos = 0, size = 22, color = nil) @x = x #x座標 @y = y #y座標 @z = z #z座標 @value = value #文字列 @prevalue = value #文字列の変更を監視するための変数 @pos = pos #原点位置 @size = size #フォントサイズ color = Color.new(0,0,0,0) if color.nil? @color = color #スプライトのブレンド色 @opacity = 255 #透明度 @zoom_x = 1.0 #拡大率x @zoom_y = 1.0 #拡大率y @defcolor = color #デフォルト色 @defzoom_x = 1.0 #デフォルト拡大率x @defzoom_y = 1.0 #デフォルト拡大率y @emphasis_count = 20 #強調表示フレーム数 @emphasis_color = Color.new(255, 0, 0) #強調時の色 @emphasis_zoom = 2 #強調時の拡大率 @strs = Array.new #文字列スプライト make_sprite() #スプライト作成 memory_all() #スプライトの各種状態を記憶 end #-------------------------------------------------------------------------- # ● 更新 #-------------------------------------------------------------------------- def move(value = @prevalue) return true if value.nil? @value = value #文字列が変更されたら if value != @prevalue @prevalue = @value make_sprite() #強調表示 emphasis() if @autemphasis end @on_change = false #移動 change_place() if @on_change_place #色変更 change_color() if @on_change_color #拡大率変更 change_zoom() if @on_change_zoom #透明度変更 change_opacity() if @on_change_opacity #フラッシュ進行 change_flash() if @on_flash #自動消滅 if @autdispose && @on_change == false dispose() return true else return false end end #-------------------------------------------------------------------------- # ● スプライト作成 #-------------------------------------------------------------------------- def make_sprite array = @value.split(//) for i in 0...array.size if @strs[i].nil? @strs[i] = Sprite_textview.new() @strs[i].color = @defcolor @strs[i].mx = @x @strs[i].my = @y @strs[i].mz = @z @strs[i].mzoom_x = @defzoom_x @strs[i].mzoom_y = @defzoom_y @strs[i].mcolor = @defcolor @strs[i].mopacity = @opacity end @strs[i].bitmap = CacheString::string(array[i],@size) end if @strs.size > array.size for i in array.size...@strs.size @strs[i].bitmap = CacheString::string(" ") end end set_pos() refresh() end #-------------------------------------------------------------------------- # ● 初期状態に戻す #-------------------------------------------------------------------------- def refresh @strs.each{|i| i.fx = @x * 1.0 i.fy = @y * 1.0 i.x = @x i.y = @y i.z = @z i.zoom_x = zoom_x i.zoom_y = zoom_y i.color = color i.opacity = opacity } gradation(@gcolor1,@gcolor2) if @g2_flag gradation3(@gcolor1,@gcolor2,@gcolor3) if @g3_flag gradation_o(@gopacity1,@gopacity2) if @g2o_flag gradation3_o(@gopacity1,@gopacity2,@gopacity3) if @g3o_flag end #-------------------------------------------------------------------------- # ● 位置調整 #-------------------------------------------------------------------------- def set_pos dx, dy = 0, 0 #縦書き if @vertical #原点x操作 @strs[0].oy = 0 for i in 1...@strs.size @strs[i].oy = @strs[i-1].oy - @strs[i-1].bitmap.height end case @pos % 3 when 1 dy = (@strs[-1].oy - @strs[0].bitmap.height - @strs[0].oy) / 2 when 2 dy = (@strs[-1].oy - @strs[0].bitmap.height - @strs[0].oy) end @strs.each{|i|i.oy -= dy} #原点y操作 case @pos / 3 when 1 dx = @size / 2 when 2 dx = @size end xline = @strs[0].bitmap.width for i in 0...@strs.size @strs[i].ox = dx - (xline - @strs[i].bitmap.width) / 2 end #横書き else #原点x操作 @strs[0].ox = 0 for i in 1...@strs.size @strs[i].ox = @strs[i-1].ox - @strs[i-1].bitmap.width end case @pos % 3 when 1 dx = (@strs[-1].ox - @strs[0].bitmap.width - @strs[0].ox) / 2 when 2 dx = (@strs[-1].ox - @strs[0].bitmap.width - @strs[0].ox) end @strs.each{|i|i.ox -= dx} #原点y操作 case @pos / 3 when 1 dy = @size / 2 when 2 dy = @size end @strs.each{|i|i.oy = dy} end end #-------------------------------------------------------------------------- # ● 強調表示 #-------------------------------------------------------------------------- def emphasis(zoom = nil,color = nil,count = nil) @emphasis_zoom = zoom unless zoom.nil? @emphasis_color = color.clone unless color.nil? @emphasis_count = count unless count.nil? set_color(@emphasis_color.clone) set_zoom(@emphasis_zoom,@emphasis_zoom) set_color(nil, @emphasis_count) set_zoom(nil,nil, @emphasis_count) end #-------------------------------------------------------------------------- # ● 縦書き設定 #-------------------------------------------------------------------------- def vertical_writing(flag = true) @vertical = flag set_pos() end #-------------------------------------------------------------------------- # ● 2色カラーグラデーション #-------------------------------------------------------------------------- def gradation(c1,c2) @g2_flag = true @g3_flag = false @gcolor1 = c1 @gcolor2 = c2 size = @strs.size - 1 return if size == 0 if size == 1 @strs[0].color = c1 end for i in 0..size red = c1.red * (size - i) / size + c2.red * i / size green = c1.green * (size - i) / size + c2.green * i / size blue = c1.blue * (size - i) / size + c2.blue * i / size alpha = c1.alpha * (size - i) / size + c2.alpha * i / size @strs[i].color = Color.new(red,green,blue,alpha) end end #-------------------------------------------------------------------------- # ● 3色カラーグラデーション #-------------------------------------------------------------------------- def gradation3(c1,c2,c3) @g2_flag = false @g3_flag = true @gcolor1 = c1 @gcolor2 = c2 @gcolor3 = c3 size = @strs.size - 1 return if size == 0 if size == 1 @strs[0].color = c2 elsif size == 2 @strs[0].color = c1 @strs[1].color = c3 end half = size / 2 for i in 0..half red = c1.red * (half - i) / half + c2.red * i / half green = c1.green * (half - i) / half + c2.green * i / half blue = c1.blue * (half - i) / half + c2.blue * i / half alpha = c1.alpha * (half - i) / half + c2.alpha * i / half @strs[i].color = Color.new(red,green,blue,alpha) end ahalf = size - half for i in half..size red = c2.red * (size - i) / ahalf + c3.red * (i - half) / ahalf green = c2.green * (size - i) / ahalf + c3.green * (i - half) / ahalf blue = c2.blue * (size - i) / ahalf + c3.blue * (i - half) / ahalf alpha = c2.alpha * (size - i) / ahalf + c3.alpha * (i - half) / ahalf @strs[i].color = Color.new(red,green,blue,alpha) end end #-------------------------------------------------------------------------- # ● 2点透明度グラデーション #-------------------------------------------------------------------------- def gradation_o(opacity1,opacity2) @g2o_flag = true @g3o_flag = false @gopacity1 = opacity1 @gopacity2 = opacity2 size = @strs.size - 1 return if size == 0 if size == 1 @strs[0].opacity = opacity1 end for i in 0..size @strs[i].opacity = opacity1 * (size - i) / size + opacity2 * i / size end end #-------------------------------------------------------------------------- # ● 3点透明度グラデーション #-------------------------------------------------------------------------- def gradation3_o(opacity1,opacity2,opacity3) @g2o_flag = false @g3o_flag = true @gopacity1 = opacity1 @gopacity2 = opacity2 @gopacity3 = opacity3 size = @strs.size - 1 return if size == 0 if size == 1 @strs[0].opacity = opacity2 elsif size == 2 @strs[0].opacity = opacity1 @strs[1].opacity = opacity3 end half = size / 2 for i in 0..half @strs[i].opacity = opacity1 * (half - i) / half + opacity2 * i / half end ahalf = size - half for i in half..size @strs[i].opacity = opacity2*(size - i)/ahalf + opacity3*(i - half)/ahalf end end #-------------------------------------------------------------------------- # ● グラデーション解除 #-------------------------------------------------------------------------- def cancel_gradation @g2_flag = false @g3_flag = false @g2o_flag = false @g3o_flag = false refresh() end #-------------------------------------------------------------------------- # ● 移動設定 #-------------------------------------------------------------------------- def set_place(x = nil, y = nil, z = nil, count = 0, interval = 0) if count == 0 @strs.each{|i| i.x = x.nil? ? i.mx : x i.y = y.nil? ? i.my : y i.z = z.nil? ? i.mz : z i.fx = i.x i.fy = i.y } @on_change_place = false else @strs.each{|i| i.tx = x.nil? ? i.mx : x i.ty = y.nil? ? i.my : y i.tz = z.nil? ? i.mz : z i.spx = (i.tx - i.x) / (count * 1.0) i.spy = (i.ty - i.y) / (count * 1.0) i.spz = (i.tz - i.z) / (count * 1.0) } @pcount = 0 @pinterval = interval @on_change_place = true end end #-------------------------------------------------------------------------- # ● 相対移動設定 #-------------------------------------------------------------------------- def set_rplace(x, y, z, count = 0, interval = 0) if count == 0 @on_change_place = false return else @strs.each{|i| i.tx = i.x + x * count i.ty = i.y + y * count i.tz = i.z + z * count i.spx = x i.spy = y i.spz = z } @pcount = 0 @pinterval = interval @on_change_place = true end end #-------------------------------------------------------------------------- # ● 拡大率変更設定 #--------------------------------------------------------------------------- def set_zoom(zoom_x = nil, zoom_y = nil, count = 0, interval = 0) if count == 0 @strs.each{|i| i.zoom_x = zoom_x.nil? ? i.mzoom_x : zoom_x i.zoom_y = zoom_y.nil? ? i.mzoom_y : zoom_y } @on_change_zoom = false else @strs.each{|i| i.tzoom_x = zoom_x.nil? ? i.mzoom_x : zoom_x i.tzoom_y = zoom_y.nil? ? i.mzoom_x : zoom_y i.spzoom_x = (i.tzoom_x - i.zoom_x) / (count * 1.0) i.spzoom_y = (i.tzoom_y - i.zoom_y) / (count * 1.0) } @zcount = 0 @zinterval = interval @on_change_zoom = true end end #-------------------------------------------------------------------------- # ● 色変更設定 #-------------------------------------------------------------------------- def set_color(color = nil, count = 0, interval = 0) if count == 0 @strs.each{|i|i.color = color.nil? ? i.mcolor : color} @on_change_color = false else @strs.each{|i| i.tcolor = color.nil? ? i.mcolor : color i.spred = (i.tcolor.red - i.color.red) / (count * 1.0) i.spgreen = (i.tcolor.green - i.color.green) / (count * 1.0) i.spblue = (i.tcolor.blue - i.color.blue) / (count * 1.0) i.spalpha = (i.tcolor.alpha - i.color.alpha) / (count * 1.0) } @ccount = 0 @cinterval = interval @on_change_color = true end end #-------------------------------------------------------------------------- # ● 透明度変更設定 #-------------------------------------------------------------------------- def set_opacity(opacity = nil, count = 0, interval = 0) if count == 0 @strs.each{|i|i.opacity = opacity.nil? ? i.mopacity : opacity} @on_change_opacity = false else @strs.each{|i| i.topacity = opacity.nil? ? i.mopacity : opacity i.spopacity = (i.topacity - i.opacity) / (count * 1.0) } @ocount = 0 @ointerval = interval @on_change_opacity = true end end #-------------------------------------------------------------------------- # ● フラッシュ設定 #-------------------------------------------------------------------------- def set_flash(color, duration, interval = 0) if duration == 0 @strs.each{|i|i.flash(color, duration)} @on_flash = false else @fcolor = color @fcount = 0 @duration = duration @finterval = interval @on_flash = true end end #-------------------------------------------------------------------------- # ● 移動 #-------------------------------------------------------------------------- def change_place @pcount += 1 for i in 0...@strs.size if (@pinterval * i) / @pcount == 0 if @strs[i].tx != @strs[i].x @strs[i].fx += @strs[i].spx @strs[i].x = @strs[i].fx @strs[i].x = @strs[i].tx if (@strs[i].tx - @strs[i].x).abs<@strs[i].spx.abs end if @strs[i].ty != @strs[i].y @strs[i].fy += @strs[i].spy @strs[i].y = @strs[i].fy @strs[i].y = @strs[i].ty if (@strs[i].ty - @strs[i].y).abs<@strs[i].spy.abs end if @strs[i].tz != @strs[i].z @strs[i].z += @strs[i].spz @strs[i].z = @strs[i].tz if (@strs[i].tz - @strs[i].z).abs<@strs[i].spz.abs end end end @x = @strs[0].x @y = @strs[0].y @z = @strs[0].z if @strs[-1].x == @strs[-1].tx && @strs[-1].y == @strs[-1].ty && @strs[-1].z == @strs[-1].tz @pcount = 0 @on_change_place = false else @on_change = true end end #-------------------------------------------------------------------------- # ● 拡大率変更 #-------------------------------------------------------------------------- def change_zoom @zcount += 1 for i in 0...@strs.size if (@zinterval * i) / @zcount == 0 if @strs[i].tzoom_x != @strs[i].zoom_x @strs[i].zoom_x += @strs[i].spzoom_x @strs[i].zoom_x = @strs[i].tzoom_x if (@strs[i].tzoom_x-@strs[i].zoom_x).abs<@strs[i].spzoom_x.abs end if @strs[i].tzoom_y != @strs[i].zoom_y @strs[i].zoom_y += @strs[i].spzoom_y @strs[i].zoom_y = @strs[i].tzoom_y if (@strs[i].tzoom_y-@strs[i].zoom_y).abs<@strs[i].spzoom_y.abs end end end @zoom_x = @strs[0].zoom_x @zoom_y = @strs[0].zoom_y if @strs[-1].zoom_x == @strs[-1].tzoom_x && @strs[-1].zoom_y == @strs[-1].tzoom_y @zcount = 0 @on_change_zoom = false else @on_change = true end end #-------------------------------------------------------------------------- # ● 色変更 #-------------------------------------------------------------------------- def change_color @ccount += 1 for i in 0...@strs.size if (@cinterval * i) / @ccount == 0 if @strs[i].tcolor.red != @strs[i].color.red @strs[i].color.red += @strs[i].spred @strs[i].color.red = @strs[i].tcolor.red if (@strs[i].tcolor.red-@strs[i].color.red).abs<@strs[i].spred.abs end if @strs[i].tcolor.green != @strs[i].color.green @strs[i].color.green += @strs[i].spgreen @strs[i].color.green = @strs[i].tcolor.green if (@strs[i].tcolor.green-@strs[i].color.green).abs<@strs[i].spgreen.abs end if @strs[i].tcolor.blue != @strs[i].color.blue @strs[i].color.blue += @strs[i].spblue @strs[i].color.blue = @strs[i].tcolor.blue if (@strs[i].tcolor.blue-@strs[i].color.blue).abs<@strs[i].spblue.abs end if @strs[i].tcolor.alpha != @strs[i].color.alpha @strs[i].color.alpha += @strs[i].spalpha @strs[i].color.alpha = @strs[i].tcolor.alpha if (@strs[i].tcolor.alpha-@strs[i].color.alpha).abs<@strs[i].spalpha.abs end end end @color = @strs[0].color if @strs[-1].color == @strs[-1].tcolor @ccount = 0 @on_change_color = false else @on_change = true end end #-------------------------------------------------------------------------- # ● 透明度変更 #-------------------------------------------------------------------------- def change_opacity @ocount += 1 for i in 0...@strs.size if (@ointerval * i) / @ocount == 0 if @strs[i].topacity != @strs[i].opacity @strs[i].opacity += @strs[i].spopacity @strs[i].opacity = @strs[i].topacity if (@strs[i].topacity-@strs[i].opacity).abs<@strs[i].spopacity.abs end end end @opacity = @strs[0].opacity if @strs[-1].opacity == @strs[-1].topacity @ocount = 0 @on_change_opacity = false else @on_change = true end end #-------------------------------------------------------------------------- # ● フラッシュ進行 #-------------------------------------------------------------------------- def change_flash for i in 0...@strs.size if (@finterval * i) == @fcount @strs[i].flash(@fcolor, @duration) end @strs[i].update() end if (@strs.size - 1) * @finterval + @duration == @fcount @fcount = 0 @on_flash = false else @on_change = true end @fcount += 1 end #-------------------------------------------------------------------------- # ● 位置記憶 #-------------------------------------------------------------------------- def memory_place @strs.each{|i| i.mx = i.x i.my = i.y i.mz = i.z i.fx = i.x i.fy = i.y } end #-------------------------------------------------------------------------- # ● 拡大率記憶 #-------------------------------------------------------------------------- def memory_zoom @strs.each{|i| i.mzoom_x = i.zoom_x i.mzoom_y = i.zoom_y } end #-------------------------------------------------------------------------- # ● 色記憶 #-------------------------------------------------------------------------- def memory_color @strs.each{|i|i.mcolor = i.color.clone} end #-------------------------------------------------------------------------- # ● 透明度記憶 #-------------------------------------------------------------------------- def memory_opacity @strs.each{|i|i.mopacity = i.opacity} end #-------------------------------------------------------------------------- # ● 全部記憶 #-------------------------------------------------------------------------- def memory_all @strs.each{|i| i.mx = i.x i.my = i.y i.mz = i.z i.fx = i.x i.fy = i.y i.mzoom_x = i.zoom_x i.mzoom_y = i.zoom_y i.mcolor = i.color.clone i.mopacity = i.opacity } end #-------------------------------------------------------------------------- # ● 破棄 #-------------------------------------------------------------------------- def dispose @strs.each{|i|i.dispose} @strs.clear @value = nil end end #============================================================================== # ■ Scoreview #------------------------------------------------------------------------------ #  数字表示クラス(1桁の数字画像を取り替えることによる書き換え) #============================================================================== class Scoreview < Textview #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(x,y,z, value, pos = 0, size = 22, color = nil) @numbers = CacheString::number(size) #数字用ビットマップセット super end #-------------------------------------------------------------------------- # ● 数値画像作成 #-------------------------------------------------------------------------- def make_sprite tvalue = @value digit = 0 check = false while tvalue >= 0 digit1st = tvalue % 10 if @strs[digit] == nil @strs[digit] = Sprite_textview.new() @strs[digit].color = @color @strs[digit].mx = @x @strs[digit].my = @y @strs[digit].mz = @z @strs[digit].mzoom_x = @zoom_x @strs[digit].mzoom_y = @zoom_y @strs[digit].mcolor = @color @strs[digit].mopacity = @opacity check = true end @strs[digit].bitmap = @numbers[digit1st] tvalue /= 10 digit += 1 if tvalue == 0 while @strs[digit] != nil @strs[digit].bitmap = @numbers[10] digit += 1 end break end end if check set_pos() refresh() end end #-------------------------------------------------------------------------- # ● 位置調整 #-------------------------------------------------------------------------- def set_pos dx, dy = 0, 0 #縦書き if @vertical #原点x操作 case @pos % 3 when 1 dy = @strs.size * @size / 2 when 2 dy = @strs.size * @size end for i in 0...@strs.size @strs[i].oy = -(@strs.size - 1 - i) * @size + dy end #原点y操作 case @pos / 3 when 1 dx = @size / 2 when 2 dx = @size end @strs.each{|i|i.ox = dx} #横書き else #原点x操作 case @pos % 3 when 1 dx = @strs.size * @size / 4 when 2 dx = @strs.size * @size / 2 end for i in 0...@strs.size @strs[i].ox = -(@strs.size - 1 - i) * @size / 2 + dx end #原点y操作 case @pos / 3 when 1 dy = @size / 2 when 2 dy = @size end @strs.each{|i|i.oy = dy} end end end #============================================================================== # ■ Sprite_textview #------------------------------------------------------------------------------ #  Textview用のSpriteクラス #============================================================================== class Sprite_textview < Sprite attr_accessor :fx attr_accessor :fy attr_accessor :mx attr_accessor :my attr_accessor :mz attr_accessor :mzoom_x attr_accessor :mzoom_y attr_accessor :mcolor attr_accessor :mopacity attr_accessor :tx attr_accessor :ty attr_accessor :tz attr_accessor :tzoom_x attr_accessor :tzoom_y attr_accessor :tcolor attr_accessor :topacity attr_accessor :spx attr_accessor :spy attr_accessor :spz attr_accessor :spzoom_x attr_accessor :spzoom_y attr_accessor :spred attr_accessor :spgreen attr_accessor :spblue attr_accessor :spalpha attr_accessor :spopacity end #============================================================================== # ■ CacheString #------------------------------------------------------------------------------ #  文字列画像をキャッシュするモジュール #============================================================================== module CacheString @cache = Hash.new #各サイズBitmapを保存するためのハッシュ #-------------------------------------------------------------------------- # ● 個別数字画像の配列のキャッシュ #-------------------------------------------------------------------------- def self.number(size = 22) unless @cache.include?(size*1000) #ハッシュ内にキーが存在しなければ array = Array.new(10){|i| #10個の配列を作成 tmp = Bitmap.new(size/2, size) #数字1桁分のビットマップを作成 tmp.font.size = size #フォントサイズ指定 tmp.draw_text(0, 0, size/2, size, "#{i}")#1桁の数字描画 tmp #配列に返す } array.push Bitmap.new(size/2, size) @cache[size*1000] = array end @cache[size*1000] #ビットマップ配列を返す end @onedot = Bitmap.new(1, 1) #-------------------------------------------------------------------------- # ● 個別画像の配列のキャッシュ #-------------------------------------------------------------------------- def self.string(chr, size = 22) key = chr + "#{size}" #文字列とサイズでキーを作成 unless @cache.include?(key) #ハッシュ内にキーが存在しなければ tmp = @onedot #1ドットビットマップ tmp.font.size = size #フォントサイズ設定 text_size = tmp.text_size(chr) #テクストサイズ取得 width = text_size.width #幅 height = text_size.height #高さ tmp = Bitmap.new(width, height) #取得したサイズのビットマップ生成 tmp.font.size = size #フォントサイズ再設定 tmp.draw_text(0, 0, width, height, chr)#描画 @cache[key] = tmp #キャッシュへ end @cache[key] #ビットマップを返す end end