1 /*
2     SPDX-FileCopyrightText: 2012 Roney Gomes <roney477@gmail.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 /**
8  * @class KGrScene  kgrscene.h
9  * @short The QGraphicsScene that represents KGoldrunner on the screen.
10  *
11  * In the KGoldrunner scene, the KGoldrunner level-layouts use tile-coordinates
12  * that run from (1, 1) to (28, 20). To simplify programming, these are exactly
13  * the same as the cell co-ordinates used in the game-engine (or model).
14  *
15  * The central grid has internal coordinates running from (-1, -1) to (30, 22),
16  * making 32x24 spaces. The empty space around the level-layout (2 cells wide
17  * all around) is designed to absorb over-enthusiastic mouse actions, which
18  * could otherwise cause accidents on other windows or the surrounding desktop.
19  *
20  * Rows -1, 0, 29 and 30 usually contain titles and scores, which could have
21  * fractional co-ordinates. Row 0, row 21, column 0 and column 29 can also
22  * contain border-tiles (as in the Egyptian theme).
23  *
24  * The hero and enemies (sprites) will have fractional co-ordinates as they move
25  * from one cell to another. Other graphics items (tiles) always have whole
26  * number co-ordinates (e.g. bricks, ladders and concrete). Empty spaces have
27  * no graphic item and the background shows through them.
28  *
29  * The width and height of the view will rarely be an exact number of tiles, so
30  * there will be unused strips outside the 32x24 tile spaces. The sceneRect() is
31  * set larger than 24 tiles by 32 tiles to allow for this and its top left
32  * corner has negative fractional co-ordinates that are calculated but never
33  * actually used. Their purpose is to ensure that (1, 1) is always the top left
34  * corner of the KGoldrunner level layout, whatever the size/shape of the view.
35  */
36 #ifndef KGRSCENE_H
37 #define KGRSCENE_H
38 
39 #include <QGraphicsScene>
40 
41 #include "kgrglobals.h"
42 
43 class KGrView;
44 class KGrSprite;
45 class KGrRenderer;
46 class KGameRenderedItem;
47 class QTimeLine;
48 
49 enum StartFrame     {RIGHTWALK1 = 1,  RIGHTWALK2,  RIGHTWALK3,  RIGHTWALK4,
50                      RIGHTWALK5,  RIGHTWALK6,  RIGHTWALK7,  RIGHTWALK8,
51                      LEFTWALK1,   LEFTWALK2,   LEFTWALK3,   LEFTWALK4,
52                      LEFTWALK5,   LEFTWALK6,   LEFTWALK7,   LEFTWALK8,
53                      RIGHTCLIMB1, RIGHTCLIMB2, RIGHTCLIMB3, RIGHTCLIMB4,
54                      RIGHTCLIMB5, RIGHTCLIMB6, RIGHTCLIMB7, RIGHTCLIMB8,
55                      LEFTCLIMB1,  LEFTCLIMB2,  LEFTCLIMB3,  LEFTCLIMB4,
56                      LEFTCLIMB5,  LEFTCLIMB6,  LEFTCLIMB7,  LEFTCLIMB8,
57                      CLIMB1,      CLIMB2,
58                      FALL1,       FALL2,
59                      DIGBRICK1 = 1, DIGBRICK2, DIGBRICK3, DIGBRICK4,
60                      DIGBRICK5,
61                      DIGBRICK6, DIGBRICK7, DIGBRICK8, DIGBRICK9};
62 
63 class KGrScene : public QGraphicsScene
64 {
65     Q_OBJECT
66 public:
67     explicit KGrScene       (KGrView * view);
68     ~KGrScene               () override;
69 
70     /**
71      * Redraw the scene whenever the current theme has changed.
72      */
73     void changeTheme        ();
74 
75     /**
76      * Redraw the scene whenever the view widget is resized.
77      */
78     void changeSize         ();
79 
80     /**
81      * Set the current level number.  It is used to select a background.
82      *
83      * @param level         The current level number.
84      */
85     void setLevel (unsigned int level);
86 
87     /**
88      * Set the text for the title of the current level.
89      *
90      * @param newTitle      The title of the current level.
91      */
92     void setTitle (const QString & newTitle);
93 
94     void setReplayMessage (const QString & msg);
95 
96     void showReplayMessage (bool onOff);
97 
98     void setHasHintText (const QString & msg);
99 
100     void setPauseResumeText (const QString & msg);
101 
102     void goToBlack();
103     void fadeIn (bool inOut);
104 
105     /**
106      * Get the current size of the squared region occupied by a single visual
107      * element (characters, ladders, bricks etc.).
108      */
tileSize()109     QSize tileSize          () const { return QSize (m_tileSize, m_tileSize); }
110 
111     /**
112      * Get a pointer to the scene's renderer.
113      */
renderer()114     KGrRenderer * renderer  () const { return m_renderer; }
115 
setGoldEnemiesRule(bool showIt)116     inline void setGoldEnemiesRule (bool showIt) { enemiesShowGold = showIt; }
117 
118 public Q_SLOTS:
119     void showLives          (long lives);
120 
121     void showScore          (long score);
122 
123     int  makeSprite         (const char type, int i, int j);
124 
125     void animate            (bool missed);
126     void gotGold            (const int spriteId, const int i, const int j,
127                              const bool spriteHasGold, const bool lost = false);
128     void showHiddenLadders  (const QList<int> & ladders, const int width);
129     void deleteSprite       (const int id);
130     void deleteAllSprites   ();
131 
132     /**
133      * Requests the view to display a particular type of tile at a particular
134      * cell, or make it empty and show the background (tileType = FREE). Used
135      * when loading level-layouts and also to make gold disappear/appear, hidden
136      * ladders appear or cells to be painted by the game editor.  If there was
137      * something in the cell already, tileType = FREE acts as an erase function.
138      *
139      * @param i            The column-number of the cell to paint.
140      * @param j            The row-number of the cell to paint.
141      * @param type         The type of tile to paint (gold, brick, ladder, etc).
142      */
143     void paintCell          (const int i, const int j, const char type);
144 
145     /**
146      * Requests the view to display an animation of a runner or dug brick at a
147      * particular cell, cancelling and superseding any current animation.
148      *
149      * @param id           The ID of the sprite (dug brick).
150      * @param repeating    If true, repeat the animation (false for dug brick).
151      * @param i            The column-number of the cell.
152      * @param j            The row-number of the cell.
153      * @param time         The time in which to traverse one cell.
154      * @param dirn         The direction of motion (always STAND for dug brick).
155      * @param type         The type of animation (run, climb, open/close brick).
156      */
157     void startAnimation    (const int id, const bool repeating,
158                             const int i, const int j, const int time,
159                             const Direction dirn, const AnimationType type);
160 
161     /**
162      * Just as the game starts, ensure that all frames of the "hero" and "enemy"
163      * sprites have been rendered. This is to avoid hiccups in animation in the
164      * first few seconds of play or demo.
165      */
166     void preRenderSprites();
167 
168     void setMousePos (const int i, const int j);
169     void getMousePos (int & i, int & j);
170 
171 Q_SIGNALS:
172     void fadeFinished();
173     void redrawEditToolbar();
174 
175 private:
176     /*
177      * Actions performed whenever the viewport is resized or a different theme
178      * is loaded.
179      */
180     void redrawScene    ();
181 
182     /*
183      * Load and set the size and position of the KGameRenderedItem's which make
184      * up the border layout.
185      */
186     void drawBorder     ();
187 
188     /*
189      * Draw a frame around the playing area when there are no border tiles.
190      */
191     void drawFrame       ();
192 
193     /*
194      * Load and set the size and position of the background image for the
195      * current level.
196      *
197      * @param level The current level.
198      */
199     void loadBackground (const int level);
200 
201     /*
202      * Add a new element, with coordinates x and y, to the border-layout.
203      *
204      * @param spriteKey The sprite key of the requested item.
205      * @param x         The item's x coordinate.
206      * @param y         The item's y coordinate.
207      */
208     void setBorderTile  (const QString &spriteKey, const int x, const int y);
209 
210     /*
211      * Resize a game's visual element.
212      *
213      * @param tile      The element to be resized.
214      * @param tileSize  The new size.
215      */
216     void setTile        (KGameRenderedItem * tile, const int tileSize,
217                          const int i, const int j);
218 
219     KGrView             *   m_view;
220     KGrRenderer         *   m_renderer;
221     KGameRenderedItem   *   m_background;
222     unsigned int            m_level;
223 
224     QGraphicsRectItem   *   m_frame;
225 
226     // Text items.
227     QGraphicsSimpleTextItem * m_title;
228     QGraphicsSimpleTextItem * m_replayMessage;
229     QGraphicsSimpleTextItem * m_livesText;
230     QGraphicsSimpleTextItem * m_scoreText;
231     QGraphicsSimpleTextItem * m_hasHintText;
232     QGraphicsSimpleTextItem * m_pauseResumeText;
233 
234     int                     m_heroId;
235     int                     m_tilesWide;
236     int                     m_tilesHigh;
237     int                     m_tileSize;
238     int                     m_toolbarTileSize;
239 
240     bool                    m_sizeChanged;
241     bool                    m_themeChanged;
242 
243     // The animated sprites for dug bricks, hero and enemies.
244     QList <KGrSprite *> m_sprites;
245 
246     // The visible elements of the scenario (tiles and borders), excluding the
247     // background picture and the animated sprites.
248     QVector <KGameRenderedItem *> m_tiles;
249 
250     // The type of each tile stored in m_tiles.
251     QByteArray m_tileTypes;
252 
253     bool enemiesShowGold;		// Show or conceal if enemies have gold.
254 
255     int m_topLeftX;
256     int m_topLeftY;
257 
258     QCursor * m_mouse;
259 
260     void setTextFont (QGraphicsSimpleTextItem * t, double fontFraction);
261     void placeTextItems();
262 
263     QGraphicsRectItem * m_spotlight;		// Fade-out/fade-in item.
264     QTimeLine *         m_fadingTimeLine;	// Timing for fade-out/fade-in.
265     QRadialGradient     m_gradient;		// Black with circular hole.
266     qreal               m_maxRadius;
267 
268 private Q_SLOTS:
269     void drawSpotlight (qreal ratio);		// Animate m_spotlight.
270 };
271 
272 #endif // KGRSCENE_H
273