Add path specification for movement animations.
[kaya.git] / lib / animations.rb
blob8321b91da357fad870e790b1c51d9f2d854c810d
1 require 'animation_field'
2 require 'factory'
4 module Animations
5   LENGTH = 100
6   
7   def group(*animations)
8     anim = animations.dup.compact
9     Animation.new("group (#{anim.size})") do |i|
10       anim.reject! do |a| 
11         a[i]
12       end
13       anim.empty?
14     end
15   end
16   
17   def sequence(*animations)
18     anim = animations.dup.compact
19     return nil if anim.empty?
20     Animation.new("sequence (#{anim.size})") do |i|
21       if anim.first[i]
22         anim.shift
23       end
24       anim.empty?
25     end
26   end
27   
28   def movement(item, src, dst, path_factory)
29     if item
30       src = board.to_real(src)
31       dst = board.to_real(dst)
32       path = path_factory.new(src, dst)
33       
34       SimpleAnimation.new "move to #{dst}", LENGTH, nil,
35         lambda {|i| item.pos = src + path[i] },
36         lambda { item.pos = dst }
37     end
38   end
40   def disappear(item, name = "disappear")
41     if item
42       SimpleAnimation.new name, LENGTH,
43         lambda { item.opacity = 1.0; item.visible = true },
44         lambda {|t| item.opacity = 1.0 - t },
45         lambda { item.remove }
46     end
47   end
48   
49   def appear(item, name = "appear")
50     SimpleAnimation.new name, LENGTH,
51       lambda { item.opacity = 0.0; item.visible = true },
52       lambda {|i| item.opacity = i },
53       lambda { item.opacity = 1.0 }
54   end
55   
56   def instant_appear(p, piece, name = "appear")
57     Animation.new(name) { board.add_piece p, piece }
58   end
59   
60   def instant_disappear(p, name = "disappear")
61     Animation.new(name) { board.remove_item p }
62   end
63 end
65 module Path
66   Linear = Factory.new do |src, dst|
67     delta = dst - src
68     lambda {|i| delta * i }
69   end
71   class LShape
72     FACTOR = Math.exp(3.0) - 1
73     def initialize(src, dst)
74       @delta = dst - src
75       nonlin = lambda{|i| (Math.exp(3.0 * i) - 1) / FACTOR }
76       lin = lambda {|i| i }
77       if @delta.x.abs < @delta.y.abs
78         @x = lin
79         @y = nonlin
80       else
81         @y = lin
82         @x = nonlin
83       end
84     end
85     
86     def [](i)
87       Qt::PointF.new(@delta.x * @x[i], @delta.y * @y[i])
88     end
89   end
90 end