Implemented pool flipping.
[kaya.git] / lib / board / pool.rb
blob90ca19ed87d8d0aa8bf8f7b464153f64f491de3e
1 require 'item'
3 class Pool < Qt::GraphicsItemGroup
4   BACKGROUND_ZVALUE = -10
5   
6   include Observable
7   include ItemUtils
8   
9   attr_reader :rect, :scene, :items
10   attr_reader :animator
11   
12   def initialize(scene, theme, game)
13     super(nil, scene)
14     @scene = scene
15     @scene.add_element(self)
16     
17     @theme = theme
18     @game = game
19     
20     @items = []
21     @size = Point.new(3, 5)
22     
23     @type_values = Hash.new(-1)
24     if @game.respond_to? :types
25       @game.types.each_with_index do |type, index|
26         @type_values[type] = index
27       end
28     end
29     
30     @animator = PoolAnimator.new(self)
31     @flipped = false
32   end
33   
34   def flip(value)
35     @flipped = value
36   end
37   
38   def flipped?
39     @flipped
40   end
41   
42   def redraw
43     pieces = @items.map do |item|
44       destroy_item(item)
45       item.name
46     end
47     @items = []
48     
49     pieces.each_with_index do |piece, index|
50       add_piece(index, piece)
51     end
52   end
54   def set_geometry(rect)
55     @rect = rect
56     
57     self.pos = @rect.top_left.to_f
58     
59     side = (@rect.width / @size.x).floor
60     @unit = Qt::Point.new(side, side)
61     redraw
62   end
63   
64   def add_piece(index, piece, opts = {})
65     opts = opts.merge :pos => to_real(index),
66                       :name => piece
67     item = create_item index, @theme.pieces.pixmap(piece, @unit), opts
68     items.insert(index, item)
69     item
70   end
71   
72   def remove_item(index, *args)
73     item = items.delete_at(index)
74     unless item.nil? or args.include?(:keep)
75       destroy_item item
76     end
77     item
78   end
79   
80   def on_click(pos, press_pos)
81     
82   end
83   
84   def on_drag(pos)
85     index = to_logical(pos)
86     item = items[index]
87     if item
88       fire :drag => { :index => index,
89                       :item => item }
90     end
91   end
92   
93   def on_drop(old_pos, pos, data)
94     if data[:item]
95       fire :drop => data
96     end
97   end
98   
99   def to_logical(p)
100     y = p.y.to_f
101     if @flipped
102       y = rect.height - y
103     end
104     result = Point.new((p.x.to_f / @unit.x).floor,
105                        (y / @unit.y).floor)
106     y = result.y
107     x = y % 2 == 0 ? result.x : @size.x - result.x - 1
108     x + y * @size.x
109   end
110   
111   def to_real(index)
112     x = index % @size.x
113     y = index / @size.x
114     x = @size.x - x - 1 if y % 2 == 1
115     
116     rx = x * @unit.x
117     ry = if @flipped
118       rect.height - (y + 1) * @unit.y
119     else
120       y * @unit.y
121     end
122     
123     Qt::PointF.new(rx, ry)
124   end
125   
126   def compare(piece1, piece2)
127     [piece1.color.to_s, @type_values[piece1.type], piece1.type.to_s] <=>
128     [piece2.color.to_s, @type_values[piece2.type], piece2.type.to_s]
129   end