view src/net/kryshen/charamega/field.mirah @ 15:8ed3a7b4f6e9

Changed homepage URL.
author Mikhail Kryshen <mikhail@kryshen.net>
date Sun, 26 Jan 2014 16:12:22 +0400
parents 6e6b00d95d0b
children
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
42 setPreferredSize Dimension.new(790, 500)
44 begin
45 source = getClass.getResourceAsStream("DejaVuSans.ttf")
46 font = Font.createFont(Font.TRUETYPE_FONT, source)
47 ensure
48 source.close unless source.nil?
49 end
50 setFont font
52 enableEvents AWTEvent.MOUSE_EVENT_MASK
53 enableEvents AWTEvent.MOUSE_MOTION_EVENT_MASK
54 end
56 def processMouseEvent(event)
57 if isEnabled
58 if event.getID == MouseEvent.MOUSE_PRESSED
60 @hold = hit(event.getX, event.getY)
62 elsif event.getID == MouseEvent.MOUSE_RELEASED and
63 !@hold.nil? and @hold == hit(event.getX, event.getY)
65 @game.open @hold
66 repaint
67 elsif event.getID == MouseEvent.MOUSE_EXITED and
68 !@hovered.nil?
70 @hovered = nil
71 repaint
72 end
73 end
75 super
76 end
78 def processMouseMotionEvent(event)
79 if isEnabled
80 h = hit(event.getX, event.getY)
82 if event.getID == MouseEvent.MOUSE_DRAGGED
83 if h == @hold and h != @hovered
84 @hovered = h
85 repaint
86 end
88 if h != @hold and @hold == @hovered
89 @hovered = nil
90 repaint
91 end
93 elsif h != @hovered
94 @hovered = h
95 repaint
96 end
97 end
99 super
100 end
102 def paintComponent(g1)
103 g = Graphics2D(g1)
105 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
106 RenderingHints.VALUE_ANTIALIAS_ON)
107 g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
108 RenderingHints.VALUE_FRACTIONALMETRICS_ON)
110 w = getWidth
111 h = getHeight
113 g.setColor @field_color
114 g.fillRect 0, 0, w, h
116 insets = getInsets
117 w -= insets.left + insets.right
118 h -= insets.top + insets.bottom
120 layout = @game.layout(w, h)
121 time = System.nanoTime
123 max_cols = Math.ceil(double(@game.cards.size) / layout.size)
124 rh = double(h) / layout.size
125 card_size = Math.min(rh, double(w) / max_cols) / 1.4
126 font_size = card_size
127 font = g.getFont.deriveFont(float(font_size))
128 frc = g.getFontRenderContext
130 rm_scale = 2.0
132 card_bounds = Rectangle2D.Double.new
134 save_t = g.getTransform
136 y = rh / 2 + insets.top
137 layout.each do |row|
138 cw = double(w) / List(row).size
139 x = cw / 2 + insets.left
141 List(row).each do |e|
142 card = Card(e)
144 v = card.visible_state(time)
146 # Compute area potentially affected by the card.
147 if v < 1.0
148 paint_x = int(Math.floor(x - cw * rm_scale / 2 - 1))
149 paint_y = int(Math.floor(y - rh * rm_scale / 2 - 1))
150 paint_w = int(Math.ceil(cw * rm_scale + 2))
151 paint_h = int(Math.ceil(rh * rm_scale + 2))
152 else
153 paint_x = int(Math.floor(x - cw / 2 - 1))
154 paint_y = int(Math.floor(y - rh / 2 - 1))
155 paint_w = int(Math.ceil(cw + 2))
156 paint_h = int(Math.ceil(rh + 2))
157 end
159 if v > 0.0 and g.hitClip(paint_x, paint_y, paint_w, paint_h)
160 f = card.flip_state(time)
162 if v < 1.0 or (f > -1.0 and f < 1.0)
163 # Animation is in progress.
164 repaint 30, paint_x, paint_y, paint_w, paint_h
165 end
167 g.translate x, y
169 v_scale = rm_scale - Math.sqrt(v) * rm_scale
170 g.scale Math.abs(f) + v_scale, 1.0 + v_scale
172 g.rotate card.angle * v
174 card_bounds.setRect(0 - card_size / 2, 0 - card_size / 2,
175 card_size, card_size)
177 if f > 0
178 g.setColor with_alpha(@face_color, v)
179 else
180 g.setColor with_alpha(@back_color, v)
181 end
183 g.fill card_bounds
185 if f > 0
186 g.setColor with_alpha(@symbol_color, Math.sqrt(v))
188 gv = font.createGlyphVector(frc, String.valueOf(card.symbol))
189 gb = gv.getVisualBounds
191 # Scale down if the glyph does not fit.
192 k = 0.9
193 scale = Math.min(card_bounds.width * k / gb.getWidth,
194 card_bounds.height * k / gb.getHeight)
195 save_t_2 = g.getTransform
196 g.scale scale, scale if scale < 1.0
198 g.drawGlyphVector(gv,
199 0 - float(gb.getX + gb.getWidth / 2),
200 0 - float(gb.getY + gb.getHeight / 2))
202 g.setTransform save_t_2
203 end
205 if card == @hovered
206 g.setColor with_alpha(@active_border_color, v)
207 else
208 g.setColor with_alpha(@border_color, v)
209 end
211 g.draw card_bounds
213 g.setTransform save_t
214 end
216 x += cw
217 end
219 y += rh
220 end
221 end
223 #private
225 def hit(x:int, y:int)
226 insets = getInsets
227 size = getSize
228 @game.hit(x - insets.left,
229 y - insets.top,
230 size.width - insets.left - insets.right,
231 size.height - insets.top - insets.bottom)
232 end
234 def with_alpha(c:Color, alpha:double)
235 Color.new c.getRed, c.getGreen, c.getBlue, int(alpha * 255)
236 end
237 end