RM的体系里每帧会调用一次update,在update里做一些数据的读取和更新,重新绘图之类的事情。如果整个update只做一件事,例如:
[pre lang="ruby"]
def update
recalculate_x
end
[/pre]
每次update时重新计算x值,这是每次update都需要考虑的,可以认为是一种单一的状态,直接写在update里也十分自然。
那么非单一状态是什么样的呢?假如我们需要等待用户的输入,获取到输入的时候重绘,但是update一秒钟会调用60次,它怎么知道这次调用应该做什么呢?是应该等待输入,还是用户已经输入了,应该处理重绘?
这时候我们可以用一个状态机去处理:
[pre lang="ruby"]
def update
case @current_state
when :wait_input
wait_input
when :redraw
redraw
end
end
def wait_input
if have_input?
@current_state = :redraw
end
end
那么看看Fiber可以如何简化这些状态,使用Fiber的等价代码:
[pre lang="ruby"]
def update
if @fiber
@fiber.resume
else
@fiber = Fiber.new {fiber_main}
end
end
def fiber_main
loop do
Fiber.yield until have_input?
draw_process
end
end
[/pre]
除了第一次调用到update会生成一个@fiber,之后的每次调用都是简单地唤醒@fiber。
而@fiber的代码,fiber_main,描述的就是我们的input-redraw流程。等待input然后直接redraw,由于原来的程序是一个循环,这里就直接塞在loop{}里。
如果have_input?为false,Fiber的控制权会移交到外部,等待下一次resume。而下一次update的@fiber.resume又会让执行的步骤回到until have_input?这一行,再次判断有无输入。