KDEGames

kgameio.h
1 /*
2  This file is part of the KDE games library
3  SPDX-FileCopyrightText: 2001 Martin Heni <kde at heni-online.de>
4  SPDX-FileCopyrightText: 2001 Andreas Beckermann <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-only
7 */
8 
9 #ifndef __KGAMEIO_H__
10 #define __KGAMEIO_H__
11 
12 // own
13 #include "libkdegamesprivate_export.h"
14 // Qt
15 #include <QString>
16 #include <QObject>
17 // Std
18 #include <memory>
19 
20 class QEvent;
21 class QGraphicsScene;
22 class QKeyEvent;
23 class QMouseEvent;
24 class KPlayer;
25 class KGame;
26 class KGameIOPrivate;
27 class KGameKeyIOPrivate;
28 class KGameMouseIOPrivate;
29 class KGameProcessIOPrivate;
30 class KGameComputerIOPrivate;
31 
32 /**
33  * \class KGameIO kgameio.h <KGame/KGameIO>
34  *
35  * \short Base class for IO devices for games
36  *
37  * This is the master class for
38  * creating IO game devices. You cannot use it directly.
39  * Either take one of the classes derived from it or
40  * you have to create your own IO class derived from it (more probably).
41  *
42  * The idea behind this class is to provide a common interface
43  * for input devices into your game. By programming a KGameIO
44  * device you need not distinguish the actual IO in the game
45  * anymore. All work is done by the IO's. This allows very
46  * easy reuse in other games as well.
47  * A further advantage of using the IO's is that you can exchange
48  * the control of a player at runtime. E.g. you switch a player
49  * to be controlled by the computer or vice versa.
50  *
51  * To achieve this you have to make all of your player inputs through a
52  * KGameIO. You will usually call KGameIO::sendInput to do so.
53  *
54  * @author Martin Heni <kde at heni-online.de>
55  */
56 class KDEGAMESPRIVATE_EXPORT KGameIO : public QObject
57 {
58  Q_OBJECT
59 
60 public:
61  /**
62  * Constructs a KGameIO object
63  */
64  KGameIO();
65  explicit KGameIO(KPlayer*);
66  ~KGameIO() override;
67 
68  /**
69  * Gives debug output of the game status
70  */
71  void Debug();
72 
73  /**
74  * Identifies the KGameIO via the rtti function
75  */
76  enum IOMode {GenericIO=1,KeyIO=2,MouseIO=4,ProcessIO=8,ComputerIO=16};
77  /**
78  * Run time identification. Predefined values are from IOMode
79  * You MUST overwrite this in derived classes!
80  *
81  * @return rtti value
82  */
83  virtual int rtti() const = 0; // Computer, network, local, ...
84 
85  /**
86  * This function returns the player who owns this IO
87  *
88  * @return the player this IO device is plugged into
89  */
90  KPlayer *player() const;
91 
92  /**
93  * Equivalent to player()->game()
94  * @return the @ref KGame object of this player
95  **/
96  KGame* game() const;
97 
98  /**
99  * Sets the player to which this IO belongs to. This
100  * is done automatically when adding a device to a
101  * player
102  *
103  * @param p the player
104  */
105  void setPlayer(KPlayer *p);
106 
107  /**
108  * Init this device by setting the player and e.g. sending an
109  * init message to the device. This initialisation message is
110  * very useful for computer players as you can transmit the
111  * game status to them and only update this status in the setTurn
112  * commands.
113  *
114  * Called by @ref KPlayer::addGameIO only!
115  */
116  virtual void initIO(KPlayer *p);
117 
118  /**
119  * Notifies the IO device that the player's setTurn had been called
120  * Called by KPlayer
121  *
122  * This emits @ref signalPrepareTurn and sends the turn if the send
123  * parameter is set to true.
124  *
125  * @param b turn is true/false
126  */
127  virtual void notifyTurn(bool b);
128 
129  /**
130  * Send an input message using @ref KPlayer::forwardInput
131  **/
132  bool sendInput(QDataStream& stream, bool transmit = true, quint32 sender = 0);
133 
134 Q_SIGNALS:
135  /**
136  * Signal generated when @ref KPlayer::myTurn changes. This can either be
137  * when you get the turn status or when you lose it.
138  *
139  * The datastream has to be filled with a move. If you set (or leave) the
140  * send parameter to FALSE then nothing happens: the datastream will be
141  * ignored. If you set it to TRUE @ref sendInput is used to
142  * send the move.
143  *
144  * Often you want to ignore this signal (leave send=FALSE) and send the
145  * message later. This is usually the case for a human player as he probably
146  * doesn't react immediately. But you can still use this e.g. to notify the
147  * player about the turn change.
148  *
149  * Example:
150  * \code
151  * void GameWindow::slotPrepareTurn(QDataStream &stream,bool b,KGameIO *input,bool * )
152  * {
153  * KPlayer *player=input->player();
154  * if (!player->myTurn()) return ;
155  * if (!b) return ; // only do something on setTurn(true)
156  * stream << 1 << 2 << 3; // Some data for the process
157  * }
158  * \endcode
159  *
160  * @param io the KGameIO object itself
161  * @param stream the stream into which the move will be written
162  * @param turn the argument of setTurn
163  * @param send set this to true to send the generated move using @ref
164  * sendInput
165  **/
166  void signalPrepareTurn(QDataStream & stream, bool turn, KGameIO *io, bool * send);
167 
168 protected:
169  explicit KGameIO(KGameIOPrivate &dd, KPlayer *player = nullptr);
170 
171 private:
172  Q_DECLARE_PRIVATE_D(d, KGameIO)
173  friend class KGameIOPrivate;
174  friend class KGameKeyIO;
175  friend class KGameMouseIO;
176  friend class KGameProcessIO;
177  friend class KGameComputerIO;
178  std::unique_ptr<KGameIOPrivate> const d;
179  // KF6 TODO: change private d to protected d_ptr, use normal Q_DECLARE_PRIVATE, remove subclass friends
180 
182 };
183 
184 /**
185  * \class KGameKeyIO kgameio.h <KGame/KGameIO>
186  *
187  * The KGameKeyIO class. It is used to process keyboard input
188  * from a widget and create moves for the player it belongs to.
189  * @author Martin Heni <kde at heni-online.de>
190  */
191 class KDEGAMESPRIVATE_EXPORT KGameKeyIO : public KGameIO
192 {
193  Q_OBJECT
194 
195 public:
196  /**
197  * Create a keyboard input devices. All keyboards
198  * inputs of the given widgets are passed through a signal
199  * handler signalKeyEvent and can be used to generate
200  * a valid move for the player.
201  * Note the widget you pass to the constructor must be
202  * the main window of your application, e.g. view->parentWidget()
203  * as QT does not forward your keyevents otherwise. This means
204  * that this might be a different widget compared to the one you
205  * use for mouse inputs!
206  * Example:
207  * \code
208  * KGameKeyIO *input;
209  * input=new KGameKeyIO(myWidget);
210  * connect(input,SIGNAL(signalKeyEvent(KGameIO *,QDataStream &,QKeyEvent *,bool *)),
211  * this,SLOT(slotKeyInput(KGameIO *,QDataStream &,QKeyEvent *,bool *)));
212  * \endcode
213  *
214  * @param parent The parents widget whose keyboard events * should be grabbed
215  */
216  explicit KGameKeyIO(QWidget *parent);
217  ~KGameKeyIO() override;
218 
219  /**
220  * The identification of the IO
221  *
222  * @return KeyIO
223  */
224  int rtti() const override;
225 
226 Q_SIGNALS:
227  /**
228  * Signal handler for keyboard events. This function is called
229  * on every keyboard event. If appropriate it can generate a
230  * move for the player the device belongs to. If this is done
231  * and the event is eaten eatevent needs to be set to true.
232  * What move you generate (i.e. what you write to the stream)
233  * is totally up to you as it will not be evaluated but forwarded
234  * to the player's/game's input move function
235  * Example:
236  * \code
237  * KPlayer *player=input->player(); // Get the player
238  * qint32 key=e->key();
239  * stream << key;
240  * eatevent=true;
241  * \endcode
242  *
243  * @param io the IO device we belong to
244  * @param stream the stream where we write our move into
245  * @param m The QKeyEvent we can evaluate
246  * @param eatevent set this to true if we processed the event
247  */
248  void signalKeyEvent(KGameIO *io,QDataStream &stream,QKeyEvent *m,bool *eatevent);
249 
250 protected:
251  /**
252  * Internal method to process the events
253  */
254  bool eventFilter( QObject *o, QEvent *e ) override;
255 
256 private:
257  Q_DECLARE_PRIVATE_D(KGameIO::d, KGameKeyIO)
258  friend class KGameKeyIOPrivate;
259 #if KDEGAMESPRIVATE_BUILD_DEPRECATED_SINCE(7, 3)
260  // Unused, kept for ABI compatibility
261  const void * __kdegames_d_do_not_use;
262 #endif
263 
265 };
266 
267 /**
268  * \class KGameMouseIO kgameio.h <KGame/KGameIO>
269  *
270  * The KGameMouseIO class. It is used to process mouse input
271  * from a widget and create moves for the player it belongs to.
272  * @author Martin Heni <kde at heni-online.de>
273  */
274 class KDEGAMESPRIVATE_EXPORT KGameMouseIO : public KGameIO
275 {
276  Q_OBJECT
277 
278 public:
279  /**
280  * Creates a mouse IO device. It captures all mouse
281  * event of the given widget and forwards them to the
282  * signal handler signalMouseEvent.
283  * Example:
284  * \code
285  * KGameMouseIO *input;
286  * input=new KGameMouseIO(mView);
287  * connect(input,SIGNAL(signalMouseEvent(KGameIO *,QDataStream &,QMouseEvent *,bool *)),
288  * this,SLOT(slotMouseInput(KGameIO *,QDataStream &,QMouseEvent *,bool *)));
289  * \endcode
290  *
291  * @param parent The widget whose events should be captured
292  * @param trackmouse enables mouse tracking (gives mouse move events)
293  */
294  explicit KGameMouseIO(QWidget *parent,bool trackmouse=false);
295  explicit KGameMouseIO(QGraphicsScene *parent,bool trackmouse=false);
296  ~KGameMouseIO() override;
297 
298  /**
299  * Manually activate or deactivate mouse tracking
300  *
301  * @param b true = tracking on
302  */
303  void setMouseTracking(bool b);
304  /**
305  * The identification of the IO
306  *
307  * @return MouseIO
308  */
309  int rtti() const override;
310 
311 Q_SIGNALS:
312  /**
313  * Signal handler for mouse events. This function is called
314  * on every mouse event. If appropriate it can generate a
315  * move for the player the device belongs to. If this is done
316  * and the event is eaten eatevent needs to be set to true.
317  * @see signalKeyEvent
318  * Example:
319  * \code
320  * KPlayer *player=input->player(); // Get the player
321  * qint32 button=e->button();
322  * stream << button;
323  * eatevent=true;
324  * \endcode
325  *
326  * @param io the IO device we belong to
327  * @param stream the stream where we write our move into
328  * @param m The QMouseEvent we can evaluate
329  * @param eatevent set this to true if we processed the event
330  */
331  void signalMouseEvent(KGameIO *io,QDataStream &stream,QMouseEvent *m,bool *eatevent);
332 
333 protected:
334  /**
335  * Internal event filter
336  */
337  bool eventFilter( QObject *o, QEvent *e ) override;
338 
339 private:
340  Q_DECLARE_PRIVATE_D(KGameIO::d, KGameMouseIO)
341  friend class KGameMouseIOPrivate;
342 #if KDEGAMESPRIVATE_BUILD_DEPRECATED_SINCE(7, 3)
343  // Unused, kept for ABI compatibility
344  const void * __kdegames_d_do_not_use;
345 #endif
346 
348 };
349 
350 
351 /**
352  * \class KGameProcessIO kgameio.h <KGame/KGameIO>
353  *
354  * The KGameProcessIO class. It is used to create a computer player
355  * via a separate process and communicate transparently with it.
356  * Its counterpart is the KGameProcess class which needs
357  * to be used by the computer player. See its documentation
358  * for the definition of the computer player.
359  */
360 class KDEGAMESPRIVATE_EXPORT KGameProcessIO : public KGameIO
361 {
362  Q_OBJECT
363 
364 public:
365  /**
366  * Creates a computer player via a separate process. The process
367  * name is given as fully qualified filename.
368  * Example:
369  * \code
370  * KGameProcessIO *input;
371  * input=new KGameProcessIO(executable_file);
372  * connect(input,SIGNAL(signalPrepareTurn(QDataStream &,bool,KGameIO *,bool *)),
373  * this,SLOT(slotPrepareTurn(QDataStream &,bool,KGameIO *,bool *)));
374  * connect(input,SIGNAL(signalProcessQuery(QDataStream &,KGameProcessIO *)),
375  * this,SLOT(slotProcessQuery(QDataStream &,KGameProcessIO *)));
376  * \endcode
377  *
378  * @param name the filename of the process to start
379  */
380  explicit KGameProcessIO(const QString& name);
381 
382  /**
383  * Deletes the process input devices
384  */
385  ~KGameProcessIO() override;
386 
387  /**
388  * The identification of the IO
389  *
390  * @return ProcessIO
391  */
392  int rtti() const override;
393 
394  /**
395  * Send a message to the process. This is analogous to the sendMessage
396  * commands of KGame. It will result in a signal of the computer player
397  * on which you can react in the process player.
398  *
399  * @param stream - the actual data
400  * @param msgid - the id of the message
401  * @param receiver - not used
402  * @param sender - who send the message
403  */
404  void sendMessage(QDataStream &stream,int msgid, quint32 receiver, quint32 sender);
405 
406  /**
407  * Send a system message to the process. This is analogous to the sendMessage
408  * commands of KGame. It will result in a signal of the computer player
409  * on which you can react in the process player.
410  *
411  * @param stream - the actual data
412  * @param msgid - the id of the message
413  * @param receiver - not used
414  * @param sender - who send the message
415  */
416  void sendSystemMessage(QDataStream &stream, int msgid, quint32 receiver, quint32 sender);
417 
418  /**
419  * Init this device by setting the player and e.g. sending an
420  * init message to the device. Calling this function will emit
421  * the IOAdded signal on which you can react and initilise the
422  * computer player.
423  * This function is called automatically when adding the IO to
424  * a player.
425  */
426  void initIO(KPlayer *p) override;
427 
428  /**
429  * Notifies the IO device that the player's setTurn had been called
430  * Called by KPlayer. You can react on the @ref signalPrepareTurn to
431  * prepare a message for the process, i.e. either update it on
432  * the changes made to the game since the last turn or the initIO
433  * has been called or transmit your gamestatus now.
434  *
435  * @param turn is true/false
436  */
437  void notifyTurn(bool turn) override;
438 
439  protected:
440  /**
441  * Internal combined function for all message handling
442  **/
443  void sendAllMessages(QDataStream &stream,int msgid, quint32 receiver, quint32 sender, bool usermsg);
444 
445  protected Q_SLOTS:
446  /**
447  * Internal message handler to receive data from the process
448  */
449  void receivedMessage(const QByteArray& receiveBuffer);
450 
451 
452 Q_SIGNALS:
453  /**
454  * A computer query message is received. This is a 'dummy'
455  * message sent by the process if it needs to communicate
456  * with us. It is not forwarded over the network.
457  * Reacting to this message allows you to 'answer' questions
458  * of the process, e.g. sending addition data which the process
459  * needs to calculate a move.
460  *
461  * Example:
462  * \code
463  * void GameWindow::slotProcessQuery(QDataStream &stream,KGameProcessIO *reply)
464  * {
465  * int no;
466  * stream >> no; // We assume the process sends us an integer question number
467  * if (no==1) // but YOU have to do this in the process player
468  * {
469  * QByteArray buffer;
470  * QDataStream out(buffer,QIODevice::WriteOnly);
471  * reply->sendSystemMessage(out,4242,0,0); // lets reply something...
472  * }
473  * }
474  * \endcode
475  */
476  void signalProcessQuery(QDataStream &stream,KGameProcessIO *me);
477 
478  /**
479  * Signal generated when the computer player is added.
480  * You can use this to communicated with the process and
481  * e.g. send initialisation information to the process.
482  *
483  * @param game the KGameIO object itself
484  * @param stream the stream into which the move will be written
485  * @param p the player itself
486  * @param send set this to false if no move should be generated
487  */
488  void signalIOAdded(KGameIO *game,QDataStream &stream,KPlayer *p,bool *send);
489 
490  /** Text is received by the process on STDERR. This is usually a debug string.
491  * @param msg The text
492  */
493  void signalReceivedStderr(const QString &msg);
494 
495 private:
496  Q_DECLARE_PRIVATE_D(KGameIO::d, KGameProcessIO)
497  friend class KGameProcessIOPrivate;
498 #if KDEGAMESPRIVATE_BUILD_DEPRECATED_SINCE(7, 3)
499  // Unused, kept for ABI compatibility
500  const void * __kdegames_d_do_not_use;
501 #endif
502 
504 };
505 
506 /**
507  * \class KGameComputerIO kgameio.h <KGame/KGameIO>
508  *
509  * \brief KGameIO variant for real-time games
510  *
511  * The KGameComputerIO class. It is used to create a LOCAL computer player
512  * and communicate transparently with it.
513  * Question: Is this needed or is it overwritten anyway for a real game?
514  *
515  * You most probably don't want to use this if you want to design a turn based
516  * game/player. You'll rather use @ref KGameIO directly, i.e. subclass it
517  * yourself. You just need to use @ref KGameIO::signalPrepareTurn and/or @ref
518  * KGameIO::notifyTurn there.
519  *
520  * This is rather meant to be of use in real time games.
521  *
522  * @author <[email protected]>
523  */
524 class KDEGAMESPRIVATE_EXPORT KGameComputerIO : public KGameIO
525 {
526  Q_OBJECT
527 
528 public:
529  /**
530  * Creates a LOCAL computer player
531  *
532  */
533  KGameComputerIO();
534  explicit KGameComputerIO(KPlayer* player);
535  ~KGameComputerIO() override;
536 
537  int rtti() const override;
538 
539  /**
540  * The number of advance calls until the player (or rather: the IO)
541  * does something (default: 1).
542  **/
543  void setReactionPeriod(int advanceCalls);
544  int reactionPeriod() const;
545 
546  /**
547  * Start a QTimer which calls advance every @p ms milli seconds.
548  **/
549  void setAdvancePeriod(int ms);
550 
551  void stopAdvancePeriod();
552 
553  /**
554  * Ignore calls number of advance calls. if calls is -1 then all
555  * following advance calls are ignored until unpause is called.
556  *
557  * This simply prevents the internal advance counter to be increased.
558  *
559  * You may want to use this to emulate a "thinking" computer player. Note
560  * that this means if you increase the advance period (see
561  * setAdvancePeriod), i.e. if you change the speed of your game, your
562  * computer player thinks "faster".
563  * @param calls Number of advance calls to be ignored
564  **/
565  void pause(int calls = -1);
566 
567  /**
568  * Equivalent to pause(0). Immediately continue to increase the internal
569  * advance counter.
570  **/
571  void unpause();
572 
573 public Q_SLOTS:
574  /**
575  * Works kind of similar to QCanvas::advance. Increase the internal
576  * advance counter. If @p reactionPeriod is reached the counter is set back to
577  * 0 and @ref signalReaction is emitted. This is when the player is meant
578  * to do something (move its units or so).
579  *
580  * This is very useful if you use QCanvas as you can use this in your
581  * QCanvas::advance call. The advantage is that if you change the speed
582  * of the game (i.e. change QCanvas::setAdvancePeriod) the computer
583  * player gets slower as well.
584  *
585  * If you don't use QCanvas you can use setAdvancePeriod to get
586  * the same result. Alternatively you can just use a QTimer.
587  *
588  **/
589  virtual void advance();
590 
591 Q_SIGNALS:
592  /**
593  * This signal is emitted when your computer player is meant to do
594  * something, or better is meant to be allowed to do something.
595  **/
596  void signalReaction();
597 
598 protected:
599  /**
600  * Default implementation simply emits signalReaction
601  **/
602  virtual void reaction();
603 
604 private:
605  Q_DECLARE_PRIVATE_D(KGameIO::d, KGameComputerIO)
606  friend class KGameComputerIOPrivate;
607 #if KDEGAMESPRIVATE_BUILD_DEPRECATED_SINCE(7, 3)
608  // Unused, kept for ABI compatibility
609  const void * __kdegames_d_do_not_use;
610 #endif
611 
613 };
614 
615 
616 #endif
virtual void notifyTurn(bool b)
Notifies the IO device that the player&#39;s setTurn had been called Called by KPlayer.
Definition: kgameio.cpp:85
const QLatin1String name
The KGameProcessIO class.
Definition: kgameio.h:360
The KGameMouseIO class.
Definition: kgameio.h:274
IOMode
Identifies the KGameIO via the rtti function.
Definition: kgameio.h:76
virtual bool eventFilter(QObject *watched, QEvent *event)
virtual void initIO(KPlayer *p)
Init this device by setting the player and e.g.
Definition: kgameio.cpp:80
Base class for a game player.
Definition: kplayer.h:60
Q_DISABLE_COPY(Class)
The main KDE game object.
Definition: kgame.h:57
KGameIO variant for real-time games.
Definition: kgameio.h:524
The KGameKeyIO class.
Definition: kgameio.h:191
virtual int rtti() const =0
Run time identification.
Base class for IO devices for games.
Definition: kgameio.h:56
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Dec 7 2021 22:34:14 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.