1/*
2 Copyright (C) 2002-2005, Jason Katz-Brown <jasonkb@mit.edu>
3 Copyright 2010 Stefan Majewsky <majewsky@gmx.net>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19
20#ifndef GAME_H
21#define GAME_H
22
23//#define SOUND
24
25#include <kolflib_export.h>
26#include "ball.h"
27
28#include "tagaro/scene.h"
29
30#include <QGraphicsView>
31#include <KLocale>
32#include <KConfigGroup>
33
34class QLabel;
35class QSlider;
36class QCheckBox;
37class QVBoxLayout;
38class KolfGame;
39class KGameRenderer;
40
41namespace Kolf
42{
43 class Wall;
44}
45namespace Tagaro
46{
47 class Board;
48}
49namespace Phonon
50{
51 class MediaObject;
52}
53namespace Kolf
54{
55 class ItemFactory;
56 KGameRenderer* renderer();
57 Tagaro::Board* findBoard(QGraphicsItem* item); //TODO: temporary HACK
58 b2World* world(); //TODO: temporary HACK (should be inside KolfGame, but various places outside the game need to create CanvasItems)
59}
60
61enum Direction { D_Left, D_Right, Forwards, Backwards };
62enum Amount { Amount_Less, Amount_Normal, Amount_More };
63
64class BallStateInfo
65{
66public:
67 void saveState(KConfigGroup *cfgGroup);
68 void loadState(KConfigGroup *cfgGroup);
69
70 int id;
71 QPoint spot;
72 BallState state;
73 bool beginningOfHole;
74 int score;
75};
76class BallStateList : public QList<BallStateInfo>
77{
78public:
79 int hole;
80 int player;
81 bool canUndo;
82 Vector vector;
83};
84
85class Player
86{
87public:
88 Player() : m_ball(new Ball(0, Kolf::world())) {}
89 Ball *ball() const { return m_ball; }
90 void setBall(Ball *ball) { m_ball = ball; }
91 BallStateInfo stateInfo(int hole) const { BallStateInfo ret; ret.spot = m_ball->pos().toPoint(); ret.state = m_ball->curState(); ret.score = score(hole); ret.beginningOfHole = m_ball->beginningOfHole(); ret.id = m_id; return ret; }
92
93 QList<int> scores() const { return m_scores; }
94 void setScores(const QList<int> &newScores) { m_scores = newScores; }
95 int score(int hole) const { return m_scores.at(hole - 1); }
96 int lastScore() const { return m_scores.last(); }
97 int firstScore() const { return m_scores.first(); }
98
99 void addStrokeToHole(int hole) { (*(m_scores.begin() + (hole -1)))++; }
100 void setScoreForHole(int score, int hole) { (*(m_scores.begin() + (hole - 1))) = score; }
101 void subtractStrokeFromHole(int hole) { (*(m_scores.begin() + (hole -1))--); }
102 void resetScore(int hole) { (*(m_scores.begin() + (hole - 1))) = 0; }
103 void addHole() { m_scores.append(0); }
104 unsigned int numHoles() const { return m_scores.count(); }
105
106 QString name() const { return m_name; }
107 void setName(const QString &name) { m_name = name; m_ball->setName(name); }
108
109 void setId(int id) { m_id = id; }
110 int id() const { return m_id; }
111
112private:
113 Ball *m_ball;
114 QList<int> m_scores;
115 QString m_name;
116 int m_id;
117};
118
119typedef QList<Player> PlayerList;
120
121class Putter : public QGraphicsLineItem, public CanvasItem
122{
123public:
124 Putter(QGraphicsItem* parent, b2World* world);
125
126 void go(Direction, Amount amount = Amount_Normal);
127 void setOrigin(double x, double y);
128 double curLen() const { return guideLineLength; }
129 double curAngle() const { return angle; }
130 int curDeg() const { return rad2deg(angle); }
131 virtual void showInfo();
132 virtual void hideInfo();
133 void setAngle(double news) { angle = news; finishMe(); }
134 void setDeg(int news) { angle = deg2rad(news); finishMe(); }
135 double curMaxAngle() const { return maxAngle; }
136 virtual void setVisible(bool yes);
137 void saveAngle(Ball *ball) { angleMap[ball] = angle; }
138 void setAngle(Ball *ball);
139 void resetAngles() { angleMap.clear(); setZValue(999999); }
140 virtual void moveBy(double dx, double dy);
141 void setShowGuideLine(bool yes);
142
143 virtual QPointF getPosition() const { return QGraphicsItem::pos(); }
144private:
145 QPointF midPoint;
146 double maxAngle;
147 double angle;
148 double oneDegree;
149 QMap<Ball *, double> angleMap;
150 double guideLineLength, putterWidth;
151 void finishMe();
152 QGraphicsLineItem *guideLine;
153 bool m_showGuideLine;
154};
155
156class HoleInfo;
157class HoleConfig : public Config
158{
159 Q_OBJECT
160
161public:
162 HoleConfig(HoleInfo *holeInfo, QWidget *);
163
164private slots:
165 void authorChanged(const QString &);
166 void parChanged(int);
167 void maxStrokesChanged(int);
168 void nameChanged(const QString &);
169 void borderWallsChanged(bool);
170
171private:
172 HoleInfo *holeInfo;
173};
174class HoleInfo : public CanvasItem
175{
176public:
177 HoleInfo(b2World* world) : CanvasItem(world) { setSimulationType(CanvasItem::NoSimulation); m_lowestMaxStrokes = 4; }
178 virtual ~HoleInfo() {}
179 void setPar(int newpar) { m_par = newpar; }
180 int par() const { return m_par; }
181 void setMaxStrokes(int newMaxStrokes) { m_maxStrokes = newMaxStrokes; }
182 int lowestMaxStrokes() const { return m_lowestMaxStrokes; }
183 int maxStrokes() const { return m_maxStrokes; }
184 bool hasMaxStrokes() const { return m_maxStrokes != m_lowestMaxStrokes; }
185 void setAuthor(QString newauthor) { m_author = newauthor; }
186 QString author() const { return m_author; }
187
188 void setName(QString newname) { m_name = newname; }
189 void setUntranslatedName(QString newname) { m_untranslatedName = newname; }
190 QString name() const { return m_name; }
191 QString untranslatedName() const { return m_untranslatedName; }
192
193 virtual Config *config(QWidget *parent) { return new HoleConfig(this, parent); }
194 void borderWallsChanged(bool yes);
195 bool borderWalls() const { return m_borderWalls; }
196
197 virtual QPointF getPosition() const { return QPointF(); }
198private:
199 QString m_author;
200 QString m_name;
201 QString m_untranslatedName;
202 bool m_borderWalls;
203 int m_par;
204 int m_maxStrokes;
205 int m_lowestMaxStrokes;
206};
207
208class StrokeCircle : public QGraphicsItem
209{
210public:
211 StrokeCircle(QGraphicsItem *parent);
212
213 void setValue(double v);
214 double value();
215 void setMaxValue(double m);
216 void setSize(const QSizeF& size);
217 void setThickness(double t);
218 double thickness() const;
219 double width() const;
220 double height() const;
221 virtual void paint (QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
222 virtual QRectF boundingRect() const;
223 virtual bool collidesWithItem(const QGraphicsItem*, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
224
225private:
226 double dvalue, dmax;
227 double ithickness, iwidth, iheight;
228};
229
230struct KOLFLIB_EXPORT CourseInfo
231{
232 CourseInfo(const QString &_name, const QString &_untranslatedName, const QString &_author, unsigned int _holes, unsigned int _par) { name = _name; untranslatedName = _untranslatedName, author = _author; holes = _holes; par = _par; }
233 CourseInfo();
234
235 QString name;
236 QString untranslatedName;
237 QString author;
238 unsigned int holes;
239 unsigned int par;
240};
241
242class KOLFLIB_EXPORT KolfGame : public QGraphicsView
243{
244 Q_OBJECT
245
246public:
247 KolfGame(const Kolf::ItemFactory& factory, PlayerList *players, const QString &filename, QWidget *parent=0);
248 ~KolfGame();
249 void setFilename(const QString &filename);
250 QString curFilename() const { return filename; }
251 void emitLargestHole() { emit largestHole(highestHole); }
252 QGraphicsScene *scene() const { return course; }
253 void removeItem(QGraphicsItem *item) { m_topLevelQItems.removeAll(item); }
254 bool askSave(bool);
255 bool isEditing() const { return editing; }
256 int currentHole() { return curHole; }
257 void setStrict(bool yes) { strict = yes; }
258 // returns true when you shouldn't do anything
259 bool isPaused() const { return paused; }
260 Ball *curBall() const { return (*curPlayer).ball(); }
261 void updateMouse();
262 void ballMoved();
263 void setBorderWalls(bool);
264 void setInPlay(bool yes) { inPlay = yes; }
265 bool isInPlay() { return inPlay; }
266 bool isInfoShowing() { return m_showInfo; }
267 void stoppedBall();
268 QString courseName() const { return holeInfo.name(); }
269 void hidePutter() { putter->setVisible(false); }
270 void ignoreEvents(bool ignore) { m_ignoreEvents = ignore; }
271
272 void setSelectedItem(CanvasItem* citem);
273
274 static void scoresFromSaved(KConfig*, PlayerList &players);
275 static void courseInfo(CourseInfo &info, const QString &filename);
276
277public slots:
278 void pause();
279 void unPause();
280 void save();
281 void toggleEditMode();
282 void setModified(bool mod = true);
283 void addNewObject(const QString& identifier);
284 void addNewHole();
285 void switchHole(int);
286 void switchHole(const QString &);
287 void nextHole();
288 void prevHole();
289 void firstHole();
290 void lastHole();
291 void randHole();
292 void playSound(const QString &file, float vol = 1);
293 void showInfoDlg(bool = false);
294 void resetHole();
295 void clearHole();
296 void setShowInfo(bool yes);
297 void toggleShowInfo();
298 void updateShowInfo();
299 void setUseMouse(bool yes) { m_useMouse = yes; }
300 void setUseAdvancedPutting(bool yes);
301 void setShowGuideLine(bool yes);
302 void setSound(bool yes);
303 void undoShot();
304 void timeout();
305 void saveScores(KConfig *);
306 void startFirstHole(int hole);
307 void sayWhosGoing();
308
309signals:
310 void holesDone();
311 void newHole(int);
312 void parChanged(int, int);
313 void titleChanged(const QString &);
314 void largestHole(int);
315 void scoreChanged(int, int, int);
316 void newPlayersTurn(Player *);
317 void newSelectedItem(CanvasItem *);
318 void checkEditing();
319 void editingStarted();
320 void editingEnded();
321 void inPlayStart();
322 void inPlayEnd();
323 void maxStrokesReached(const QString &);
324 void currentHole(int);
325 void modifiedChanged(bool);
326 void newStatusText(const QString &);
327
328private slots:
329 void shotDone();
330 void holeDone();
331 void startNextHole();
332 void fastTimeout();
333 void putterTimeout();
334 void autoSaveTimeout();
335
336 void emitMax();
337
338protected:
339 void mouseMoveEvent(QMouseEvent *e);
340 void mousePressEvent(QMouseEvent *e);
341 void mouseReleaseEvent(QMouseEvent *e);
342 void mouseDoubleClickEvent(QMouseEvent *e);
343
344 void handleMousePressEvent(QMouseEvent *e);
345 void handleMouseDoubleClickEvent(QMouseEvent *e);
346 void handleMouseMoveEvent(QMouseEvent *e);
347 void handleMouseReleaseEvent(QMouseEvent *e);
348 void keyPressEvent(QKeyEvent *e);
349 void keyReleaseEvent(QKeyEvent *e);
350
351 //resizes view to make sure it is square and calls resizeAllItems
352 void resizeEvent(QResizeEvent *);
353
354 QPoint viewportToViewport(const QPoint &p);
355
356private:
357 Tagaro::Scene *course;
358 Tagaro::Board *courseBoard;
359 Putter *putter;
360 PlayerList *players;
361 PlayerList::Iterator curPlayer;
362 Ball *whiteBall;
363 StrokeCircle *strokeCircle;
364
365 QTimer *timer;
366 QTimer *autoSaveTimer;
367 QTimer *fastTimer;
368 QTimer *putterTimer;
369 bool regAdv;
370
371 const Kolf::ItemFactory& m_factory;
372 QList<QGraphicsItem*> m_topLevelQItems; //includes balls, but not putter
373 QList<QGraphicsItem*> m_moveableQItems;
374
375 QList<Kolf::Wall *> borderWalls;
376
377 int timerMsec;
378 int autoSaveMsec;
379 int fastTimerMsec;
380 int putterTimerMsec;
381
382 void puttPress();
383 void puttRelease();
384 bool inPlay;
385 bool putting;
386 bool stroking;
387 bool finishStroking;
388 double strength;
389 double maxStrength;
390 int puttCount;
391 bool puttReverse;
392
393 int curHole;
394 int highestHole;
395 int curPar;
396
397 int wallWidth;
398 int height;
399 int width;
400 int margin;
401
402 int advancePeriod;
403
404 int lastDelId;
405
406 bool paused;
407
408 QString filename;
409 bool recalcHighestHole;
410 void openFile();
411
412 bool strict;
413
414 bool editing;
415 QGraphicsItem *selectedItem;
416
417 //For intro banner
418 Tagaro::SpriteObjectItem *banner;
419
420#ifdef SOUND
421 Phonon::MediaObject *m_player;
422#endif
423 bool m_sound;
424 QString soundDir;
425
426 bool m_ignoreEvents;
427
428 HoleInfo holeInfo;
429 QMap<QString, QPointF> savedState;
430
431 BallStateList ballStateList;
432 void loadStateList();
433 void recreateStateList();
434 void addHoleInfo(BallStateList &list);
435
436 bool dontAddStroke;
437
438 bool addingNewHole;
439 int scoreboardHoles;
440 inline void resetHoleScores();
441
442 bool m_showInfo;
443
444 bool infoShown;
445
446 KConfig *cfg;
447 KConfigGroup cfgGroup;
448
449 inline void addBorderWall(const QPoint &start, const QPoint &end);
450 void shotStart();
451 void startBall(const Vector &vector);
452
453 bool modified;
454
455 inline bool allPlayersDone();
456
457 bool m_useMouse;
458 bool m_useAdvancedPutting;
459
460 QString playerWhoMaxed;
461};
462
463#endif
464