1 | /* **************************************************************************** |
2 | This file is part of the game 'KJumpingCube' |
3 | |
4 | Copyright (C) 1998-2000 by Matthias Kiefer |
5 | <matthias.kiefer@gmx.de> |
6 | |
7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 2 of the License, or |
10 | (at your option) any later version. |
11 | |
12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with this program; if not, write to the Free Software |
19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
20 | |
21 | **************************************************************************** */ |
22 | #include "kcubewidget.h" |
23 | |
24 | #include <QPainter> |
25 | #include <QMouseEvent> |
26 | #include <QPaintEvent> |
27 | #include <QPixmap> |
28 | |
29 | /* ****************************************************** ** |
30 | ** static elements ** |
31 | ** ****************************************************** */ |
32 | bool KCubeWidget::_clicksAllowed=true; |
33 | |
34 | void KCubeWidget::enableClicks(bool flag) |
35 | { |
36 | _clicksAllowed=flag; |
37 | } |
38 | |
39 | /* ****************************************************** ** |
40 | ** public functions ** |
41 | ** ****************************************************** */ |
42 | |
43 | KCubeWidget::KCubeWidget (QWidget* parent) |
44 | : QFrame(parent) |
45 | { |
46 | setMinimumSize (20,20); |
47 | setFrameStyle(QFrame::Panel | QFrame::Raised); |
48 | int h = height(); |
49 | int w = width(); |
50 | setLineWidth ((h<w?h:w) / 14); // Make QFrame::Raised width proportional. |
51 | |
52 | setCoordinates (0, 0, 2); |
53 | |
54 | migrating = 0; |
55 | m_scale = 1.0; |
56 | m_row = 0; |
57 | m_col = 0; |
58 | m_owner = Nobody; |
59 | m_value = 1; |
60 | |
61 | pixmaps = 0; |
62 | blinking = None; |
63 | |
64 | // show values |
65 | update(); |
66 | } |
67 | |
68 | KCubeWidget::~KCubeWidget() |
69 | { |
70 | } |
71 | |
72 | void KCubeWidget::setPixmaps (QList<QPixmap> * ptr) |
73 | { |
74 | pixmaps = ptr; |
75 | } |
76 | |
77 | void KCubeWidget::setOwner (Player newOwner) |
78 | { |
79 | if (newOwner != m_owner) { |
80 | m_owner = newOwner; |
81 | updateColors(); |
82 | } |
83 | } |
84 | |
85 | void KCubeWidget::setValue(int newValue) |
86 | { |
87 | if (newValue != m_value) { |
88 | m_value = newValue; |
89 | update(); |
90 | } |
91 | } |
92 | |
93 | void KCubeWidget::shrink (qreal scale) |
94 | { |
95 | migrating = 0; |
96 | m_scale = scale; |
97 | update(); |
98 | } |
99 | |
100 | void KCubeWidget::expand (qreal scale) |
101 | { |
102 | migrating = 1; |
103 | m_scale = scale; |
104 | blinking = None; // Remove overloaded cube's dark color. |
105 | update(); |
106 | } |
107 | |
108 | void KCubeWidget::migrateDot (int rowDiff, int colDiff, int step, Player player) |
109 | { |
110 | migrating = 2; |
111 | qreal scale = (step < 4) ? 1.0 - 0.3 * step : 0.0; |
112 | m_rowDiff = rowDiff * scale; // Calculate relative position of dot. |
113 | m_colDiff = colDiff * scale; |
114 | // If owner changes, fade in new color as dot approaches centre of cube. |
115 | m_player = player; |
116 | m_opacity = (step < 4) ? 0.2 * (step + 1) : 1.0; |
117 | update(); |
118 | } |
119 | |
120 | void KCubeWidget::setCoordinates (int row, int col, int limit) |
121 | { |
122 | m_row = row; |
123 | m_col = col; |
124 | m_limit = limit; |
125 | } |
126 | |
127 | /* ****************************************************** ** |
128 | ** public slots ** |
129 | ** ****************************************************** */ |
130 | |
131 | void KCubeWidget::reset() |
132 | { |
133 | blinking = None; |
134 | setValue (1); |
135 | setOwner (Nobody); |
136 | update(); |
137 | } |
138 | |
139 | |
140 | void KCubeWidget::updateColors() |
141 | { |
142 | update(); |
143 | } |
144 | |
145 | /* ****************************************************** ** |
146 | ** Event handler ** |
147 | ** ****************************************************** */ |
148 | |
149 | void KCubeWidget::mouseReleaseEvent(QMouseEvent *e) |
150 | { |
151 | // only accept click if it was inside this cube |
152 | if(e->x()< 0 || e->x() > width() || e->y() < 0 || e->y() > height()) |
153 | return; |
154 | |
155 | if(e->button() == Qt::LeftButton && _clicksAllowed) { |
156 | e->accept(); |
157 | emit clicked (m_row, m_col); |
158 | } |
159 | } |
160 | |
161 | void KCubeWidget::paintEvent(QPaintEvent * /* ev unused */) |
162 | { |
163 | if ((pixmaps == 0) || (pixmaps->isEmpty())) |
164 | return; |
165 | |
166 | int width = this->width(); |
167 | int height = this->height(); |
168 | |
169 | QPainter p(this); |
170 | |
171 | SVGElement el = Neutral; |
172 | if (owner() == One) |
173 | el = Player1; |
174 | else if (owner() == Two) |
175 | el = Player2; |
176 | |
177 | // if ((migrating == 2) && (m_player != owner())) // && (m_scale < 0.5)) |
178 | // el = m_element; |
179 | |
180 | int pmw = pixmaps->at(el).width(); |
181 | int pmh = pixmaps->at(el).height(); |
182 | p.drawPixmap ((width - pmw)/2, (height - pmh)/2, pixmaps->at(el)); |
183 | if ((migrating == 2) && (m_player != owner())) { |
184 | el = (m_player == One) ? Player1 : Player2; |
185 | p.setOpacity (m_opacity); // Cube is being captured: fade in new color. |
186 | p.drawPixmap ((width - pmw)/2, (height - pmh)/2, pixmaps->at(el)); |
187 | p.setOpacity (1.0); |
188 | } |
189 | |
190 | QPixmap pip = pixmaps->at(Pip); |
191 | int dia = pip.width(); |
192 | |
193 | // Normally scale = 1.0, but it will be less during the first part of an |
194 | // animation that shows a cube taking over its neighboring cubes. |
195 | |
196 | int w = m_scale * width; // The size of the pattern of pips. |
197 | int h = m_scale * height; |
198 | int cx = width/2; // The center point of the cube face. |
199 | int cy = height/2; |
200 | int tlx = (width - w) / 2; // The top left corner of the pattern of pips. |
201 | int tly = (height - h) / 2; |
202 | |
203 | int points = (migrating == 1) ? 0 : value(); |
204 | if (migrating == 2) { |
205 | int dRow = m_rowDiff * width / 2; |
206 | int dCol = m_colDiff * height / 2; |
207 | p.drawPixmap (cx + dRow - dia/2, cy + dCol - dia/2, pip); |
208 | } |
209 | |
210 | switch (points) { |
211 | case 0: |
212 | // Show the pattern of pips migrating to neighboring cubes: |
213 | // one pip in the center and one migrating to each neighbor. |
214 | p.drawPixmap (cx - dia/2, cy - dia/2, pip); |
215 | if (m_scale > 1.0) { // The migrating dots have all left this cube. |
216 | break; |
217 | } |
218 | if (m_row > 0) // Neighbor above, if any. |
219 | p.drawPixmap (tlx - dia/2, cy - dia/2, pip); |
220 | if (m_row < m_limit) // Neighbor below, if any. |
221 | p.drawPixmap (width - tlx - dia/2, cy - dia/2, pip); |
222 | if (m_col > 0) // Neighbor to left, if any. |
223 | p.drawPixmap (cx - dia/2, tly - dia/2, pip); |
224 | if (m_col < m_limit) // Neighbor to right, if any. |
225 | p.drawPixmap (cx - dia/2, height - tly - dia/2, pip); |
226 | break; |
227 | |
228 | // Otherwise show a pattern for the current number of pips. It may be |
229 | // scaled down during the first part of an animation that shows a cube |
230 | // taking over its neighboring cubes. |
231 | case 1: |
232 | p.drawPixmap (tlx + (w - dia)/2, tly + (h - dia)/2, pip); |
233 | break; |
234 | |
235 | case 3: |
236 | p.drawPixmap (tlx + (w - dia)/2, tly + (h - dia)/2, pip); |
237 | case 2: |
238 | p.drawPixmap (tlx + (w/2 - dia)/2, tly + (h/2 - dia)/2, pip); |
239 | p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (3*h/2 - dia)/2, pip); |
240 | break; |
241 | |
242 | case 5: |
243 | p.drawPixmap (tlx + (w - dia)/2, tly + (h - dia)/2, pip); |
244 | case 4: |
245 | p.drawPixmap (tlx + (w/2 - dia)/2, tly + (h/2 - dia)/2, pip); |
246 | p.drawPixmap (tlx + (w/2 - dia)/2, tly + (3*h/2 - dia)/2, pip); |
247 | p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (h/2 - dia)/2, pip); |
248 | p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (3*h/2 - dia)/2, pip); |
249 | break; |
250 | |
251 | case 8: |
252 | p.drawPixmap (tlx + (w - dia)/2, tly + 2*h/3 - dia/2, pip); |
253 | case 7: |
254 | p.drawPixmap (tlx + (w - dia)/2, tly + h/3 - dia/2, pip); |
255 | case 6: |
256 | p.drawPixmap (tlx + (w/2 - dia)/2, tly + (h/2 - dia)/2, pip); |
257 | p.drawPixmap (tlx + (w/2 - dia)/2, tly + (h - dia)/2, pip); |
258 | p.drawPixmap (tlx + (w/2 - dia)/2, tly + (3*h/2 - dia)/2, pip); |
259 | p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (h/2 - dia)/2, pip); |
260 | p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (h - dia)/2, pip); |
261 | p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (3*h/2 - dia)/2, pip); |
262 | break; |
263 | |
264 | default: |
265 | QString s; |
266 | s.sprintf("%d" ,points); |
267 | p.setPen(Qt::black); |
268 | p.drawText(tlx + w/2,tly + h/2,s); |
269 | break; |
270 | } |
271 | |
272 | // This is used to highlight a cube and also to perform the hint animation. |
273 | switch (blinking) { |
274 | case Light: |
275 | p.drawPixmap ((width - pmw)/2, (height - pmh)/2, pixmaps->at(BlinkLight)); |
276 | break; |
277 | case Dark: |
278 | p.drawPixmap ((width - pmw)/2, (height - pmh)/2, pixmaps->at(BlinkDark)); |
279 | break; |
280 | default: |
281 | break; |
282 | } |
283 | migrating = 0; |
284 | m_scale = 1.0; |
285 | |
286 | p.end(); |
287 | } |
288 | |
289 | #include "kcubewidget.moc" |
290 | |