File indexing completed on 2025-02-02 07:28:22
0001 /* 0002 Copyright (C) 2002-2005, Jason Katz-Brown <jasonkb@mit.edu> 0003 Copyright 2010 Stefan Majewsky <majewsky@gmx.net> 0004 0005 This program is free software; you can redistribute it and/or modify 0006 it under the terms of the GNU General Public License as published by 0007 the Free Software Foundation; either version 2 of the License, or 0008 (at your option) any later version. 0009 0010 This program is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 GNU General Public License for more details. 0014 0015 You should have received a copy of the GNU General Public License 0016 along with this program; if not, write to the Free Software 0017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0018 */ 0019 0020 #ifndef GAME_H 0021 #define GAME_H 0022 0023 #include "ball.h" 0024 0025 #include "tagaro/scene.h" 0026 0027 #include <QGraphicsView> 0028 #include <KConfigGroup> 0029 #include <KGameSound> 0030 0031 class KolfGame; 0032 class KGameRenderer; 0033 0034 namespace Kolf 0035 { 0036 class Wall; 0037 } 0038 namespace Tagaro 0039 { 0040 class Board; 0041 } 0042 namespace Kolf 0043 { 0044 class ItemFactory; 0045 KGameRenderer* renderer(); 0046 Tagaro::Board* findBoard(QGraphicsItem* item); //TODO: temporary HACK 0047 b2World* world(); //TODO: temporary HACK (should be inside KolfGame, but various places outside the game need to create CanvasItems) 0048 } 0049 0050 enum Direction { D_Left, D_Right, Forwards, Backwards }; 0051 enum Amount { Amount_Less, Amount_Normal, Amount_More }; 0052 enum class Sound { 0053 BlackHole, 0054 BlackHoleEject, 0055 BlackHolePutIn, 0056 Bumper, 0057 Hit, 0058 Holed, 0059 HoleINone, 0060 Puddle, 0061 Wall, 0062 WooHoo 0063 }; 0064 0065 class BallStateInfo 0066 { 0067 public: 0068 int id; 0069 QPoint spot; 0070 BallState state; 0071 bool beginningOfHole; 0072 int score; 0073 }; 0074 class BallStateList : public QList<BallStateInfo> 0075 { 0076 public: 0077 int hole; 0078 int player; 0079 bool canUndo; 0080 Vector vector; 0081 }; 0082 0083 class Player 0084 { 0085 public: 0086 Player() : m_ball(new Ball(nullptr, Kolf::world())) {} 0087 Ball *ball() const { return m_ball; } 0088 void setBall(Ball *ball) { m_ball = ball; } 0089 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; } 0090 0091 QList<int> scores() const { return m_scores; } 0092 void setScores(const QList<int> &newScores) { m_scores = newScores; } 0093 int score(int hole) const { return m_scores.at(hole - 1); } 0094 int lastScore() const { return m_scores.last(); } 0095 int firstScore() const { return m_scores.first(); } 0096 0097 void addStrokeToHole(int hole) { (*(m_scores.begin() + (hole -1)))++; } 0098 void setScoreForHole(int score, int hole) { (*(m_scores.begin() + (hole - 1))) = score; } 0099 void subtractStrokeFromHole(int hole) { (*(m_scores.begin() + (hole -1))--); } 0100 void resetScore(int hole) { (*(m_scores.begin() + (hole - 1))) = 0; } 0101 void addHole() { m_scores.append(0); } 0102 unsigned int numHoles() const { return m_scores.count(); } 0103 0104 QString name() const { return m_name; } 0105 void setName(const QString &name) { m_name = name; m_ball->setName(name); } 0106 0107 void setId(int id) { m_id = id; } 0108 int id() const { return m_id; } 0109 0110 private: 0111 Ball *m_ball; 0112 QList<int> m_scores; 0113 QString m_name; 0114 int m_id; 0115 }; 0116 0117 typedef QList<Player> PlayerList; 0118 0119 class Putter : public QGraphicsLineItem, public CanvasItem 0120 { 0121 public: 0122 Putter(QGraphicsItem* parent, b2World* world); 0123 0124 void go(Direction, Amount amount = Amount_Normal); 0125 void setOrigin(double x, double y); 0126 double curLen() const { return guideLineLength; } 0127 double curAngle() const { return angle; } 0128 int curDeg() const { return rad2deg(angle); } 0129 virtual void showInfo(); 0130 virtual void hideInfo(); 0131 void setAngle(double news) { angle = news; finishMe(); } 0132 void setDeg(int news) { angle = deg2rad(news); finishMe(); } 0133 double curMaxAngle() const { return maxAngle; } 0134 virtual void setVisible(bool yes); 0135 void saveAngle(Ball *ball) { angleMap[ball] = angle; } 0136 void setAngle(Ball *ball); 0137 void resetAngles() { angleMap.clear(); setZValue(999999); } 0138 void moveBy(double dx, double dy) override; 0139 void setShowGuideLine(bool yes); 0140 0141 QPointF getPosition() const override { return QGraphicsItem::pos(); } 0142 private: 0143 QPointF midPoint; 0144 double maxAngle; 0145 double angle; 0146 double oneDegree; 0147 QMap<Ball *, double> angleMap; 0148 double guideLineLength, putterWidth; 0149 void finishMe(); 0150 QGraphicsLineItem *guideLine; 0151 bool m_showGuideLine; 0152 }; 0153 0154 class HoleInfo; 0155 class HoleConfig : public Config 0156 { 0157 Q_OBJECT 0158 0159 public: 0160 HoleConfig(HoleInfo *holeInfo, QWidget *); 0161 0162 private Q_SLOTS: 0163 void authorChanged(const QString &); 0164 void parChanged(int); 0165 void maxStrokesChanged(int); 0166 void nameChanged(const QString &); 0167 void borderWallsChanged(bool); 0168 0169 private: 0170 HoleInfo *holeInfo; 0171 }; 0172 class HoleInfo : public CanvasItem 0173 { 0174 public: 0175 explicit HoleInfo(b2World* world) : CanvasItem(world) { setSimulationType(CanvasItem::NoSimulation); m_lowestMaxStrokes = 4; } 0176 ~HoleInfo() override {} 0177 void setPar(int newpar) { m_par = newpar; } 0178 int par() const { return m_par; } 0179 void setMaxStrokes(int newMaxStrokes) { m_maxStrokes = newMaxStrokes; } 0180 int lowestMaxStrokes() const { return m_lowestMaxStrokes; } 0181 int maxStrokes() const { return m_maxStrokes; } 0182 bool hasMaxStrokes() const { return m_maxStrokes != m_lowestMaxStrokes; } 0183 void setAuthor(const QString &newauthor) { m_author = newauthor; } 0184 QString author() const { return m_author; } 0185 0186 void setName(const QString &newname) { m_name = newname; } 0187 void setUntranslatedName(const QString &newname) { m_untranslatedName = newname; } 0188 QString name() const { return m_name; } 0189 QString untranslatedName() const { return m_untranslatedName; } 0190 0191 Config *config(QWidget *parent) override { return new HoleConfig(this, parent); } 0192 void borderWallsChanged(bool yes); 0193 bool borderWalls() const { return m_borderWalls; } 0194 0195 QPointF getPosition() const override { return QPointF(); } 0196 private: 0197 QString m_author; 0198 QString m_name; 0199 QString m_untranslatedName; 0200 bool m_borderWalls; 0201 int m_par; 0202 int m_maxStrokes; 0203 int m_lowestMaxStrokes; 0204 }; 0205 0206 class StrokeCircle : public QGraphicsItem 0207 { 0208 public: 0209 explicit StrokeCircle(QGraphicsItem *parent); 0210 0211 void setValue(double v); 0212 double value(); 0213 void setMaxValue(double m); 0214 void setSize(const QSizeF& size); 0215 void setThickness(double t); 0216 double thickness() const; 0217 double width() const; 0218 double height() const; 0219 void paint (QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override; 0220 QRectF boundingRect() const override; 0221 bool collidesWithItem(const QGraphicsItem*, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const override; 0222 0223 private: 0224 double dvalue, dmax; 0225 double ithickness, iwidth, iheight; 0226 }; 0227 0228 struct CourseInfo 0229 { 0230 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; } 0231 CourseInfo(); 0232 0233 QString name; 0234 QString untranslatedName; 0235 QString author; 0236 unsigned int holes; 0237 unsigned int par; 0238 }; 0239 0240 class KolfGame : public QGraphicsView 0241 { 0242 Q_OBJECT 0243 0244 public: 0245 KolfGame(const Kolf::ItemFactory& factory, PlayerList *players, const QString &filename, QWidget *parent=nullptr); 0246 ~KolfGame() override; 0247 void setFilename(const QString &filename); 0248 QString curFilename() const { return filename; } 0249 void emitLargestHole() { Q_EMIT largestHole(highestHole); } 0250 QGraphicsScene *scene() const { return course; } 0251 void removeItem(QGraphicsItem *item) { m_topLevelQItems.removeAll(item); } 0252 bool askSave(bool); 0253 bool isEditing() const { return editing; } 0254 int currentHole() { return curHole; } 0255 void setStrict(bool yes) { strict = yes; } 0256 // returns true when you shouldn't do anything 0257 bool isPaused() const { return paused; } 0258 Ball *curBall() const { return (*curPlayer).ball(); } 0259 void updateMouse(); 0260 void ballMoved(); 0261 void setBorderWalls(bool); 0262 bool isInPlay() { return inPlay; } 0263 bool isInfoShowing() { return m_showInfo; } 0264 void stoppedBall(); 0265 QString courseName() const { return holeInfo.name(); } 0266 void hidePutter() { putter->setVisible(false); } 0267 void ignoreEvents(bool ignore) { m_ignoreEvents = ignore; } 0268 0269 void setSelectedItem(CanvasItem* citem); 0270 0271 static void scoresFromSaved(KConfig*, PlayerList &players); 0272 static void courseInfo(CourseInfo &info, const QString &filename); 0273 void playSound(Sound soundType); 0274 0275 public Q_SLOTS: 0276 void pause(); 0277 void unPause(); 0278 void save(); 0279 void toggleEditMode(); 0280 void setModified(bool mod = true); 0281 void addNewObject(const QString& identifier); 0282 void addNewHole(); 0283 void switchHole(int); 0284 void switchHole(const QString &); 0285 void nextHole(); 0286 void prevHole(); 0287 void firstHole(); 0288 void lastHole(); 0289 void randHole(); 0290 void showInfoDlg(bool = false); 0291 void resetHole(); 0292 void clearHole(); 0293 void setShowInfo(bool yes); 0294 void toggleShowInfo(); 0295 void updateShowInfo(); 0296 void setUseMouse(bool yes) { m_useMouse = yes; } 0297 void setUseAdvancedPutting(bool yes); 0298 void setShowGuideLine(bool yes); 0299 void setSound(bool yes); 0300 void undoShot(); 0301 void timeout(); 0302 void saveScores(KConfig *); 0303 void startFirstHole(int hole); 0304 void sayWhosGoing(); 0305 0306 Q_SIGNALS: 0307 void holesDone(); 0308 void newHole(int); 0309 void parChanged(int, int); 0310 void titleChanged(const QString &); 0311 void largestHole(int); 0312 void scoreChanged(int, int, int); 0313 void newPlayersTurn(Player *); 0314 void newSelectedItem(CanvasItem *); 0315 void checkEditing(); 0316 void editingStarted(); 0317 void editingEnded(); 0318 void inPlayStart(); 0319 void inPlayEnd(); 0320 void maxStrokesReached(const QString &); 0321 void currentHole(int); 0322 void modifiedChanged(bool); 0323 void newStatusText(const QString &); 0324 0325 private Q_SLOTS: 0326 void shotDone(); 0327 void holeDone(); 0328 void startNextHole(); 0329 void fastTimeout(); 0330 void putterTimeout(); 0331 void autoSaveTimeout(); 0332 0333 void emitMax(); 0334 0335 protected: 0336 void mouseMoveEvent(QMouseEvent *e) override; 0337 void mousePressEvent(QMouseEvent *e) override; 0338 void mouseReleaseEvent(QMouseEvent *e) override; 0339 void mouseDoubleClickEvent(QMouseEvent *e) override; 0340 0341 void handleMousePressEvent(QMouseEvent *e); 0342 void handleMouseDoubleClickEvent(QMouseEvent *e); 0343 void handleMouseMoveEvent(QMouseEvent *e); 0344 void handleMouseReleaseEvent(QMouseEvent *e); 0345 void keyPressEvent(QKeyEvent *e) override; 0346 void keyReleaseEvent(QKeyEvent *e) override; 0347 0348 //resizes view to make sure it is square and calls resizeAllItems 0349 void resizeEvent(QResizeEvent *) override; 0350 0351 QPoint viewportToViewport(const QPoint &p); 0352 0353 private: 0354 Tagaro::Scene *course; 0355 Tagaro::Board *courseBoard; 0356 Putter *putter; 0357 PlayerList *players; 0358 PlayerList::Iterator curPlayer; 0359 Ball *whiteBall; 0360 StrokeCircle *strokeCircle; 0361 0362 QTimer *timer; 0363 QTimer *autoSaveTimer; 0364 QTimer *fastTimer; 0365 QTimer *putterTimer; 0366 bool regAdv; 0367 0368 const Kolf::ItemFactory& m_factory; 0369 QList<QGraphicsItem*> m_topLevelQItems; //includes balls, but not putter 0370 QList<QGraphicsItem*> m_moveableQItems; 0371 0372 QList<Kolf::Wall *> borderWalls; 0373 0374 int timerMsec; 0375 int autoSaveMsec; 0376 int fastTimerMsec; 0377 int putterTimerMsec; 0378 0379 void puttPress(); 0380 void puttRelease(); 0381 bool inPlay; 0382 bool putting; 0383 bool stroking; 0384 bool finishStroking; 0385 double strength; 0386 double maxStrength; 0387 int puttCount; 0388 bool puttReverse; 0389 0390 int curHole; 0391 int highestHole; 0392 int curPar; 0393 0394 int wallWidth; 0395 int height; 0396 int width; 0397 int margin; 0398 0399 int advancePeriod; 0400 0401 int lastDelId; 0402 0403 bool paused; 0404 0405 QString filename; 0406 bool recalcHighestHole; 0407 void openFile(); 0408 0409 bool strict; 0410 0411 bool editing; 0412 QGraphicsItem *selectedItem; 0413 0414 //For intro banner 0415 Tagaro::SpriteObjectItem *banner; 0416 0417 KGameSound m_soundBlackHole; 0418 KGameSound m_soundBlackHoleEject; 0419 KGameSound m_soundBlackHolePutIn; 0420 KGameSound m_soundBumper; 0421 KGameSound m_soundHit; 0422 KGameSound m_soundHoled; 0423 KGameSound m_soundHoleINone; 0424 KGameSound m_soundPuddle; 0425 KGameSound m_soundWall; 0426 KGameSound m_soundWooHoo; 0427 bool m_sound; 0428 0429 bool m_ignoreEvents; 0430 0431 HoleInfo holeInfo; 0432 QMap<QString, QPointF> savedState; 0433 0434 BallStateList ballStateList; 0435 void loadStateList(); 0436 void recreateStateList(); 0437 void addHoleInfo(BallStateList &list); 0438 0439 bool dontAddStroke; 0440 0441 bool addingNewHole; 0442 int scoreboardHoles; 0443 inline void resetHoleScores(); 0444 0445 bool m_showInfo; 0446 0447 bool infoShown; 0448 0449 KConfig *cfg; 0450 KConfigGroup cfgGroup; 0451 0452 inline void addBorderWall(const QPoint &start, const QPoint &end); 0453 void shotStart(); 0454 void startBall(const Vector &vector); 0455 0456 bool modified; 0457 0458 inline bool allPlayersDone(); 0459 0460 bool m_useMouse; 0461 bool m_useAdvancedPutting; 0462 0463 QString playerWhoMaxed; 0464 }; 0465 0466 #endif