=begin = スプライトによる擬似Windowクラス 組み込みクラスであるWindowクラスをSpriteで再現してみました。 z座標がばらけてしまっているのが玉に瑕 Window_Baseの親に指定しても結構いけます。 改造しないと使い道がありません。 Author:: 半生 Date:: 2010/11/29 Version:: 0.1.0.0 URL:: http://www.tktkgame.com/ =end class SP_Window class Sprite_Part < ::Sprite_Base attr_reader :opacity attr_reader :visible def initialize(parent_win) super(parent_win.viewport) @parent_win = parent_win @skin = parent_win.windowskin @opacity = 255 @visible = true end def skin=(new_skin) if @skin != new_skin @skin = new_skin refresh end @skin end def opacity=(op) @opacity = op super(@opacity * @parent_win.opacity / 255) @opacity end def refresh end def fix_position end def dispose self.bitmap.dispose if self.bitmap.is_a?(Bitmap) self.bitmap = nil super end end class Sprite_Back < Sprite_Part def initialize(parent_win) super(parent_win) fix_position refresh end def refresh self.bitmap.dispose if self.bitmap.is_a?(Bitmap) self.bitmap = Bitmap.new([@width, 4].max, [@height, 4].max) return if @width < 4 or @height < 4 # body dest_rect = Rect.new(2, 2, @width - 4, @height - 4) src_rect = Rect.new(0, 0, 64, 64) self.bitmap.stretch_blt(dest_rect, @skin, src_rect) # border # border-top dest_rect = Rect.new(16, 0, @width - 32, 16) src_rect = Rect.new(80, 0, 32, 16) self.bitmap.stretch_blt(dest_rect, @skin, src_rect) # border-bottom dest_rect = Rect.new(16, @height - 16, @width - 32, 16) src_rect = Rect.new(80, 48, 32, 16) self.bitmap.stretch_blt(dest_rect, @skin, src_rect) # border-left dest_rect = Rect.new(0, 16, 16, @height - 32) src_rect = Rect.new(64, 16, 16, 32) self.bitmap.stretch_blt(dest_rect, @skin, src_rect) # border-right dest_rect = Rect.new(@width -16, 16, 16, @height - 32) src_rect = Rect.new(112, 16, 16, 32) self.bitmap.stretch_blt(dest_rect, @skin, src_rect) # corners src_rect = Rect.new(64, 0, 16, 16) self.bitmap.blt(0, 0, @skin, src_rect) src_rect = Rect.new(112, 0, 16, 16) self.bitmap.blt(@width - 16, 0, @skin, src_rect) src_rect = Rect.new(64, 48, 16, 16) self.bitmap.blt(0, @height - 16, @skin, src_rect) src_rect = Rect.new(112, 48, 16, 16) self.bitmap.blt(@width - 16, @height - 16, @skin, src_rect) end def visible=(v) @visible = v super(v & @parent_win.visible) @visible end def fix_position if @width != @parent_win.width or @height != @parent_win.height @width = @parent_win.width @height = @parent_win.height self.refresh end self.x = @parent_win.x self.y = @parent_win.y + @height / 2 self.z = @parent_win.z self.oy = @height / 2 end end class Sprite_Content < Sprite_Part def initialize(parent_win) super(parent_win) width = [@parent_win.width - 32, 4].max height = [@parent_win.height - 32, 4].max self.bitmap = Bitmap.new(width, height) fix_position refresh end def bitmap=(bm) self.bitmap.dispose if self.bitmap.is_a?(Bitmap) super fix_position end def fix_position self.x = @parent_win.x + 16 self.y = @parent_win.y + 16 self.z = @parent_win.z + 1 self.src_rect = Rect.new(@parent_win.ox, @parent_win.oy, [@parent_win.width - 32, 0].max, [@parent_win.height - 32, 0].max) end def visible=(v) @visible = v super(v & @parent_win.visible & (@parent_win.openness == 255)) @visible end def skin=(new_skin) new_skin end end class Sprite_Cursor < Sprite_Part attr_reader :cursor_rect def initialize(parent_win) super(parent_win) @rx = 0 @ry = 0 @width = 0 @height = 0 @cursor_rect = Rect.new(@rx, @ry, @width, @height) @cursor_rect_old = @cursor_rect.dup @duration = 0 fix_position refresh end def refresh self.bitmap.dispose if self.bitmap.is_a?(Bitmap) self.bitmap = Bitmap.new([@width, 4].max, [@height, 4].max) return if @width < 4 or @height < 4 # body dest_rect = Rect.new(2, 2, @width - 4, @height - 4) src_rect = Rect.new(66, 66, 28, 28) self.bitmap.stretch_blt(dest_rect, @skin, src_rect) # border # border-top dest_rect = Rect.new(2, 0, @width - 4, 2) src_rect = Rect.new(66, 64, 28, 2) self.bitmap.stretch_blt(dest_rect, @skin, src_rect) # border-bottom dest_rect = Rect.new(2, @height - 2, @width - 4, 2) src_rect = Rect.new(66, 94, 28, 2) self.bitmap.stretch_blt(dest_rect, @skin, src_rect) # border-left dest_rect = Rect.new(0, 2, 2, @height - 4) src_rect = Rect.new(64, 66, 2, 28) self.bitmap.stretch_blt(dest_rect, @skin, src_rect) # border-right dest_rect = Rect.new(@width - 2, 2, 2, @height - 4) src_rect = Rect.new(94, 66, 2, 28) self.bitmap.stretch_blt(dest_rect, @skin, src_rect) # 四隅 src_rect = Rect.new(64, 64, 2, 2) self.bitmap.blt(0, 0, @skin, src_rect) src_rect = Rect.new(94, 64, 2, 2) self.bitmap.blt(@width - 2, 0, @skin, src_rect) src_rect = Rect.new(64, 94, 2, 2) self.bitmap.blt(0, @height - 2, @skin, src_rect) src_rect = Rect.new(94, 94, 2, 2) self.bitmap.blt(@width - 2, @height - 2, @skin, src_rect) end def update if @cursor_rect_old != @cursor_rect self.cursor_rect = @cursor_rect end if self.visible @duration = (@duration + 1) % 31 self.opacity = 50 + (Math.sin(@duration / 10) * 100).to_i end super() end def visible=(v) @visible = v super(v & @parent_win.visible & (@parent_win.openness == 255)) @visible end def fix_position self.x = @parent_win.x + @rx + 16 self.y = @parent_win.y + @ry + 16 self.z = @parent_win.z + 2 self.ox = @parent_win.ox self.oy = @parent_win.oy end def cursor_rect=(r) return r if r == @cursor_rect_old @cursor_rect = r @rx = @cursor_rect.x @ry = @cursor_rect.y self.fix_position if @width != @cursor_rect.width or @height != @cursor_rect.height @width = @cursor_rect.width @height = @cursor_rect.height refresh end @cursor_rect_old = @cursor_rect.dup return @cursor_rect end end # スクロール矢印 class Sprite_Arrow < Sprite_Part def initialize(parent_win, dir) super(parent_win) @dir = dir self.bitmap = Bitmap.new(16,16) self.ox = 8 self.oy = 8 fix_position refresh self.visible = false end def refresh self.bitmap.clear rect = Rect.new(0,0,16,16) case @dir when 2 rect.x = 88 rect.y = 8 when 4 rect.x = 72 rect.y = 24 when 6 rect.x = 104 rect.y = 24 when 8 rect.x = 88 rect.y = 40 else rect.x = 128 end self.bitmap.blt(0, 0, @skin, rect) end def fix_position case @dir when 2 self.x = @parent_win.x + @parent_win.width / 2 self.y = @parent_win.y + 4 when 4 self.x = @parent_win.x + 4 self.y = @parent_win.y + @parent_win.height / 2 when 6 self.x = @parent_win.x + @parent_win.width - 4 self.y = @parent_win.y + @parent_win.height / 2 when 8 self.x = @parent_win.x + @parent_win.width / 2 self.y = @parent_win.y + @parent_win.height - 4 end self.z = @parent_win.z + 2 end def visible=(v) @visible = v super(v & @parent_win.visible & (@parent_win.openness == 255)) @visible end end # ポーズ矢印 class Sprite_Pause < Sprite_Part QUARTER_FREQ = 15 V_POS = [0, -1, -2, -1] def initialize(parent_win) super(parent_win) @count = 0 @pattern = 0 self.ox = 8 self.visible = false self.bitmap = Bitmap.new(32, 32) fix_position refresh end def pattern_rect(ptn) Rect.new(ptn % 2, ptn / 2, 16, 16) end def refresh self.bitmap.clear self.bitmap.blt(0,0,@skin, Rect.new(96,64,64,64)) @count = 0 @pattern = 0 self.src_rect = pattern_rect(0) end def fix_position self.x = @parent_win.x + @parent_win.width / 2 self.y = @parent_win.y + @parent_win.height - 16 self.z = @parent_win.z + 2 end def update @count += 1 if @count > QUARTER_FREQ @count = 0 @pattern = (@pattern + 1) % 4 self.oy = V_POS[@pattern] pattern_rect(@pattern) end super end def visible=(v) @visible = v super(v & @parent_win.visible & (@parent_win.openness == 255)) @visible end end attr_reader :viewport attr_reader :x attr_reader :y attr_reader :z attr_reader :width attr_reader :height attr_reader :ox attr_reader :oy attr_reader :opacity attr_reader :active attr_reader :visible attr_reader :pause attr_reader :diposed attr_reader :windowskin attr_reader :openness def initialize(viewport=nil) @viewport = viewport @windowskin = Cache.system("Window") @width = width @height = height @x = 0 @y = 0 @width = 0 @height = 0 @z = 0 @ox = 0 @oy = 0 @opacity = 255 @back_opacity = 200 @contents_opacity = 255 @openness = 255 @visible = true @active = true @sp_cursor_duration = 0 @pause = false @disposed = false create_sprites end def create_sprites @sprites = {} # ウィンドウ背景 @sprites[:back] = Sprite_Back.new(self) # ウィンドウの中身 @sprites[:content] = Sprite_Content.new(self) # カーソル @sprites[:cursor] = Sprite_Cursor.new(self) # スクロール矢印 @sprites[:top_arrow] = Sprite_Arrow.new(self, 2) @sprites[:bottom_arrow] = Sprite_Arrow.new(self, 8) @sprites[:left_arrow] = Sprite_Arrow.new(self, 4) @sprites[:right_arrow] = Sprite_Arrow.new(self, 6) # ポーズサイン @sprites[:pause] = Sprite_Pause.new(self) end def refresh end def update @sprites.each_value do |sp| sp.update end end # ウィンドウの解放 def dispose dispose_sprites @disposed = true end # 使用したスプライトの解放 def dispose_sprites @sprites.each_value do |sp| sp.dispose end end def cursor_rect @sprites[:cursor].cursor_rect end def cursor_rect=(r) @sprites[:cursor].cursor_rect = r end def fix_sprites_position @sprites.each_value do |sp| sp.fix_position end end def width=(w) @width = w self.ox = self.ox fix_sprites_position @width end def height=(h) @height = h self.oy = self.oy fix_sprites_position @height end # X座標 def x=(value) @x = value fix_sprites_position @x end # Y座標 def y=(value) @y = value fix_sprites_position @y end def ox=(value) @ox = value # @ox = [ [value, 0].max, self.contents.width + 32 - @width ].min @sprites[:content].fix_position @sprites[:cursor].fix_position @sprites[:left_arrow].visible = (@ox > 0) @sprites[:right_arrow].visible = (self.contents.width + 32 - @ox > @width) end def oy=(value) @oy = value # @oy = [ [value, 0].max, self.contents.height + 32 - @height ].min @sprites[:content].fix_position @sprites[:cursor].fix_position @sprites[:top_arrow].visible = (@oy > 0) @sprites[:bottom_arrow].visible = (self.contents.height + 32 - @oy > @height) end # Z座標 def z=(value) @z = value fix_sprites_position @z end def viewport=(v) @viewport = v @sprites.each_value do |sp| sp.viewport = @viewport end @viewport end def active=(value) @active = value @sprites[:cursor].visible = @active @active end def pause=(v) @pause = v @sprites[:pause].visible = v @pause end # 全体の不透明度 def opacity=(value) return if @opacity == value @opacity = value @sprites.each_value do |sp| sp.opacity = sp.opacity end end def visible=(v) @visible = v @sprites.each_value do |sp| sp.visible = sp.visible end @visible end # 背景の不透明度 def back_opacity=(value) @back_opacity = value @sprites[:back].opacity = @back_opacity @back_opacity end # 内容の不透明度 def contents_opacity=(value) @contents_opacity = value @sprites[:content].opacity = @contents_opacity @contents_opacity end # 内容 def contents @sprites[:content].bitmap end def contents=(bitmap) @sprites[:content].bitmap = bitmap @sprites[:right_arrow].visible = (self.contents.width + 32 - @ox > @width) @sprites[:bottom_arrow].visible = (self.contents.height+ 32 - @oy > @height) end def openness=(op) return @openness if @openness == op @openness = [[op, 0].max, 255].min @sprites.each_value do |sp| sp.visible = sp.visible end @sprites[:back].zoom_y = @openness / 255.0 @openness end # スキンの変更 def windowskin=(skin) return if @windowskin == skin @windowskin = skin @sprites.each_value do |sp| sp.skin = @windowskin end end end