view src/net/kryshen/charamega/field.mirah @ 0:91ecd24948de

Imported.
author Mikhail Kryshen <mikhail@kryshen.net>
date Sat, 14 Jul 2012 05:46:29 +0400
parents
children 1e64a109812f
line source
1 #
2 # Copyright 2012 Mikhail Kryshen <mikhail@kryshen.net>
3 #
4 # This file is part of Charamega.
5 #
6 # Charamega is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # Charamega is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with Charamega. If not, see <http://www.gnu.org/licenses/>.
18 #
20 package net.kryshen.charamega
22 import java.awt.*
23 import java.awt.geom.*
24 import java.awt.event.*
25 import javax.swing.*
26 import java.util.List
28 class Field < JComponent
30 def initialize(game:Game)
31 @field_color = Color.WHITE
32 @border_color = Color.GRAY
33 @active_border_color = Color.DARK_GRAY
34 @symbol_color = Color.BLACK
35 @back_color = Color.LIGHT_GRAY
36 @face_color = Color.new(0xFFFDDD)
38 @game = game
40 setOpaque true
41 setDoubleBuffered true
43 begin
44 source = getClass.getResource("DejaVuSans.ttf").openStream
45 font = Font.createFont(Font.TRUETYPE_FONT, source)
46 ensure
47 source.close unless source.nil?
48 end
49 setFont font
51 enableEvents AWTEvent.MOUSE_EVENT_MASK
52 enableEvents AWTEvent.MOUSE_MOTION_EVENT_MASK
53 end
55 def processMouseEvent(event)
56 if isEnabled
57 if event.getID == MouseEvent.MOUSE_PRESSED
59 @hold = hit(event.getX, event.getY)
61 elsif event.getID == MouseEvent.MOUSE_RELEASED and
62 !@hold.nil? and @hold == hit(event.getX, event.getY)
64 @game.open @hold
65 repaint
66 elsif event.getID == MouseEvent.MOUSE_EXITED and
67 !@hovered.nil?
69 @hovered = nil
70 repaint
71 end
72 end
74 super
75 end
77 def processMouseMotionEvent(event)
78 if isEnabled
79 h = hit(event.getX, event.getY)
81 if event.getID == MouseEvent.MOUSE_DRAGGED
82 if h == @hold and h != @hovered
83 @hovered = h
84 repaint
85 end
87 if h != @hold and @hold == @hovered
88 @hovered = nil
89 repaint
90 end
92 elsif h != @hovered
93 @hovered = h
94 repaint
95 end
96 end
98 super
99 end
101 def paintComponent(g1)
102 g = Graphics2D(g1)
104 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
105 RenderingHints.VALUE_ANTIALIAS_ON)
106 g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
107 RenderingHints.VALUE_FRACTIONALMETRICS_ON)
109 w = getWidth
110 h = getHeight
112 g.setColor @field_color
113 g.fillRect 0, 0, w, h
115 insets = getInsets
116 w -= insets.left + insets.right
117 h -= insets.top + insets.bottom
119 layout = @game.layout(w, h)
120 time = System.nanoTime
122 max_cols = Math.ceil(double(@game.cards.size) / layout.size)
123 rh = double(h) / layout.size
124 card_size = Math.min(rh, double(w) / max_cols) / 1.4
125 font_size = card_size
126 font = g.getFont.deriveFont(float(font_size))
127 frc = g.getFontRenderContext
129 rm_scale = 2.0
131 outer = Rectangle2D.Double.new
132 inner = Rectangle2D.Double.new
133 border = Path2D.Double.new(Path2D.WIND_EVEN_ODD)
135 save_t = g.getTransform
137 y = rh / 2 + insets.top
138 layout.each do |row|
139 cw = double(w) / List(row).size
140 x = cw / 2 + insets.left
142 List(row).each do |e|
143 card = Card(e)
145 v = card.visible_state(time)
147 # Compute area potentially affected by the card.
148 if v < 1.0
149 paint_x = int(Math.floor(x - cw * rm_scale / 2 - 1))
150 paint_y = int(Math.floor(y - rh * rm_scale / 2 - 1))
151 paint_w = int(Math.ceil(cw * rm_scale + 2))
152 paint_h = int(Math.ceil(rh * rm_scale + 2))
153 else
154 paint_x = int(Math.floor(x - cw / 2 - 1))
155 paint_y = int(Math.floor(y - rh / 2 - 1))
156 paint_w = int(Math.ceil(cw + 2))
157 paint_h = int(Math.ceil(rh + 2))
158 end
160 if v > 0.0 and g.hitClip(paint_x, paint_y, paint_w, paint_h)
161 f = card.flip_state(time)
163 if v < 1.0 or (f > -1.0 and f < 1.0)
164 # Animation is in progress.
165 repaint 30, paint_x, paint_y, paint_w, paint_h
166 end
168 g.translate x, y
170 v_scale = rm_scale - Math.sqrt(v) * rm_scale
171 g.scale Math.abs(f) + v_scale, 1.0 + v_scale
173 g.rotate card.angle * v
175 outer.setRect(-card_size / 2, -card_size / 2,
176 card_size, card_size)
177 inner.setRect(1 - card_size / 2, 1 - card_size / 2,
178 card_size - 2, card_size - 2)
179 border.reset
180 border.append outer, false
181 border.append inner, false
183 if f > 0
184 g.setColor with_alpha(@face_color, v)
185 else
186 g.setColor with_alpha(@back_color, v)
187 end
189 g.fill inner
191 if f > 0
192 g.setColor with_alpha(@symbol_color, Math.sqrt(v))
194 gv = font.createGlyphVector(frc, String.valueOf(card.symbol))
195 sb = gv.getVisualBounds
197 # Scale down if the glyph does not fit.
198 tolerance = 0.95
199 scale = Math.min(inner.getWidth * tolerance / sb.getWidth,
200 inner.getHeight * tolerance / sb.getHeight)
201 save_t_2 = g.getTransform
202 g.scale scale, scale if scale < 1.0
204 g.drawGlyphVector(gv,
205 -float(sb.getX + sb.getWidth / 2),
206 -float(sb.getY + sb.getHeight / 2))
208 g.setTransform save_t_2
209 end
211 if card == @hovered
212 g.setColor with_alpha(@active_border_color, v)
213 else
214 g.setColor with_alpha(@border_color, v)
215 end
217 g.fill border
219 g.setTransform save_t
220 end
222 x += cw
223 end
225 y += rh
226 end
227 end
229 private
231 def hit(x:int, y:int)
232 insets = getInsets
233 size = getSize
234 @game.hit(x - insets.left,
235 y - insets.top,
236 size.width - insets.left - insets.right,
237 size.height - insets.top - insets.bottom)
238 end
240 def with_alpha(c:Color, alpha:double)
241 Color.new c.getRed, c.getGreen, c.getBlue, int(alpha * 255)
242 end
243 end