File indexing completed on 2024-05-12 04:04:32

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