BMVC for RGSS 1.00
1. BMVC是什么?
BMVC是RGSS中实现多个窗口或者精灵,或者他们的混合架构的一个脚本,可以用来简化代码。
 相对于单个的窗体Window/精灵Sprite而言,BMVC可以同时有多个显示对象被控制。比如应用物品时,物品描述窗口,物品选择窗口和对象选择窗口是三个窗口,但有关联。可以用BMVC实现。
 而相对于场景Scene而言,BMVC比Scene要轻量,也可以嵌入Scene中。
 所以也可以放在事件中,比如一个物品选择窗口,没必要创建一个类。
BMVC是RGSS系列上对MVC模式(http://zh.wikipedia.org/wiki/MVC)的一个特化实现,因为RGSS默认脚本本身已经实现一系列与模型有关的东西比如$game_…,这里只需要和他们建立各种关系即可,这种关系模型在本脚本叫做BindingModel,故本脚本命名为BindingModel-View-Controller
2. 如何使用?
有两个重要的方法,一个是K,一个是B,K创建视图和有关的控制器,B创建和模型的绑定。
写在K里面的self.xxx,如果他是一个window或者sprite的话,会自动update和dispose
第一个例子,显示一个有Hello world的窗口,按回车(Input::C)时退出,因为不含任何可变的数据,所以没有用到B。
1 2 3 4 5 6 7  | K{   a = self.window = Window.new   a.width = 132   a.height = 132   self.bitmap = a.contents = Bitmap.new(100, 100)   self.bitmap.draw_text(a.contents.rect, "Hello world") }.run :C => :exit  | 
下面这个例子的窗口将要显示一个全局变量$a,并且当你按下回车键时,$a会加上1,并且显示也对应变化,注意变化的部分用B{}括起来。相对于上面那个例子,实际上就是把不变的”Hello world”换成了变化的$a.to_s,这里我们用B{$a.to_s}括起来。(同时加上了contents.clear清除内容这样的行为,不然前后写的文字会重叠在一起)
1 2 3 4 5 6 7 8 9 10 11  | $a = 0 K{   a = self.mywindow = Window.new   self.mywindow.width = 132   self.mywindow.height = 132   self.bitmap = self.mywindow.contents = Bitmap.new(100, 100)   B{     self.bitmap.clear     self.bitmap.draw_text(0, 0, 100, 100, B{$a.to_s})   } }.run :B => :exit, :C => proc{$a += 1}  | 
因为按下回车键时,$a加上了1,所以$a.to_s会变化,B{$a.to_s}会把这个变化反馈给外面那个B{},
因此重新进行了绘制.
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203  | module Kittiko end module Kittiko::BindingModel   attr_accessor :block   def self.stack     @stack ||= []   end   def changed?     @changed   end   def check_block     @check_block ||= []   end   def add_block(&b)     check_block << Kittiko::Binding.new(&b)   end   def B(&b)     if Kittiko::BindingModel.stack[-1] && !Kittiko::BindingModel.stack[-1].sealed       Kittiko::BindingModel.stack[-1].add_block &b       b.call     else       b.call     end   end   def calc     @cache = block.call   end   def update_binding     if check_block.empty?       @cache ||= calc     else       if @model_cache != (a = check_block.map{|x| x.calc})         @model_cache = a         @cache ||= calc       else         @cache       end     end   end end class Kittiko::Binding   include Kittiko::BindingModel   attr_accessor :sealed   def initialize(&b)     self.sealed = false     Kittiko::BindingModel.stack.push self     self.block = b     b.call if b     Kittiko::BindingModel.stack.pop     self.sealed = true   end end class Kittiko::Container   include Kittiko::BindingModel   attr_accessor :sealed   def initialize(str, &b)     @__symbols__ = []     self.sealed = false     Kittiko::BindingModel.stack.push self     instance_eval str         instance_eval &b if b     self.block = proc{}     Kittiko::BindingModel.stack.pop     self.sealed = true   end   def method_missing(sym, *args)     @__symbols__.push(('@'+sym.to_s.chomp("=")).to_sym)     (class << self; self; end).send :attr_accessor, sym.to_s.chomp("=")     send sym, *args   end   def each     @__symbols__.each do |x| yield instance_variable_get(x) end   end   def reverse_each     @__symbols__.reverse.each do |x| yield instance_variable_get(x) end   end   def update     each{|x| x.update if x.respond_to?(:update)}     update_binding   end   def dispose     reverse_each{|x| x.dispose  if x.respond_to?(:dispose)}   end   def run_proc(v)     case v       when Symbol         send v       when Kittiko::Container         v.run       when Proc         instance_eval &v       else         instance_eval v     end   end   def run_loop(opt = {})     @exit = false     until @exit       run_once(opt)     end   end   def run_once(opt = {})     Graphics.update     Input.update     update     opt.each{|k, v|       run_proc(v) if case k         when Symbol           Input.trigger?(Input.const_get(k))         when Proc           instance_eval &k         end     }   end   def run(opt = {})     run_loop opt     dispose   end   def exit     @exit = true   end   def self.uniform_define_setter(*symbols)     symbols.each do |sym|          class_eval "           def #{sym}(value)              each{|x| x.#{sym} = value }           end         "     end   end   uniform_define_setter :ox, :oy, :x, :y, :zoom_x, :zoom_y, :angle,                          :opacity, :content_opacity, :back_opacity,                         :z, :width, :height, :active, :mirror, :bush_depth,                         :blend_type, :color, :tone, :visible end def K(a = "", &b)   return Kittiko::Container if a == "" && !b   Kittiko::Container.new(a, &b) end class Kittiko::EventBase   def self.keypress?(k)     proc{Input.press?(Input.const_get(k))}   end   def self.keytrigger?(k)     proc{Input.trigger?(Input.const_get(k))}   end   def self.keyrepeat?(k)     proc{Input.repeat?(Input.const_get(k))}   end end class Kittiko::Scope   def self.[](name)       BindObject.new(name)   end   class BindObject     def initialize(name)       @name = name     end     [:+, :-, :*, :/, :<, :>, :==, :>=, :<=].each{|x|       class_eval %{         def #{x}(rhs)           u = @name           lambda{ instance_variable_get(u) #{x} rhs}         end       }     }   end end E = Kittiko::EventBase S = Kittiko::Scope  | 
没看懂咋用呢咋办?==