Implemented drag and drop.
[kaya.git] / lib / games / chess / animator.rb
blobc5eac8eedc47c854b9cb8892d492189b68a3b941
1 require 'animator_helper'
3 module Chess
4   class Animator
5     include AnimatorHelper
6     attr_reader :board
7     
8     def initialize(board)
9       @board = board
10     end
12     def specific_move!(piece, src, dst, opts = {})
13       path = if piece and piece.type == :knight and (not opts[:adjust])
14         Path::LShape
15       else
16         Path::Linear
17       end
18       move!(src, dst, path, opts)
19     end
21     def warp(state, opts = { :instant => true })
22       res = []
23       
24       state.board.each_square do |p|
25         new_piece = state.board[p]
26         old_item = @board.items[p]
27         
28         if new_piece
29           if not old_item
30             res << appear_on!(p, new_piece, opts)
31           elsif new_piece != old_item.name
32             res << morph_on!(p, new_piece, opts)
33           end
34         else
35           res << disappear_on!(p, opts) if old_item
36         end
37       end
39       group(*res)
40     end
41     
42     def forward(state, move, opts = {})
43       piece = state.board[move.dst]
44       capture = disappear_on! move.dst
45       
46       actual_move = if move.src.nil?
47         if opts[:dropped]
48           @board.items[move.dst] = opts[:dropped]
49           movement opts[:dropped], nil, move.dst, Path::Linear
50         elsif move.respond_to?(:dropped)
51           appear_on! move.dst, move.dropped
52         end
53       else
54         specific_move! piece, move.src, move.dst, opts
55       end
56       
57       extra = if move.type == :king_side_castling
58         specific_move! piece, move.dst + Point.new(1, 0), move.dst - Point.new(1, 0)
59       elsif move.type == :queen_side_castling
60         specific_move! piece, move.dst - Point.new(2, 0), move.dst + Point.new(1, 0)
61       end
62       
63       rest = warp(state, :instant => false)
64       main = group(capture, actual_move, extra)
65       
66       sequence(main, rest)
67     end
68     
69     def back(state, move, opts = {})
70       actual_move = if move.src.nil?
71         disappear_on! move.dst
72       else
73         piece = state.board[move.src]
74         specific_move! piece, move.dst, move.src
75       end
76       
77       extra = if move.type == :king_side_castling
78         specific_move! piece, move.dst - Point.new(1, 0), move.dst + Point.new(1, 0)
79       elsif move.type == :queen_side_castling
80         specific_move! piece, move.dst + Point.new(1, 0), move.dst - Point.new(2, 0)
81       end
82       rest = warp(state, :instant => false)
83       
84       main = group(actual_move, extra)
85       sequence(main, rest)
86     end
87   end
88 end