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 <QObject>
16 #include <QString>
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  * \class KGameProcessIO kgameio.h <KGame/KGameIO>
352  *
353  * The KGameProcessIO class. It is used to create a computer player
354  * via a separate process and communicate transparently with it.
355  * Its counterpart is the KGameProcess class which needs
356  * to be used by the computer player. See its documentation
357  * for the definition of the computer player.
358  */
359 class KDEGAMESPRIVATE_EXPORT KGameProcessIO : public KGameIO
360 {
361  Q_OBJECT
362 
363 public:
364  /**
365  * Creates a computer player via a separate process. The process
366  * name is given as fully qualified filename.
367  * Example:
368  * \code
369  * KGameProcessIO *input;
370  * input=new KGameProcessIO(executable_file);
371  * connect(input,SIGNAL(signalPrepareTurn(QDataStream &,bool,KGameIO *,bool *)),
372  * this,SLOT(slotPrepareTurn(QDataStream &,bool,KGameIO *,bool *)));
373  * connect(input,SIGNAL(signalProcessQuery(QDataStream &,KGameProcessIO *)),
374  * this,SLOT(slotProcessQuery(QDataStream &,KGameProcessIO *)));
375  * \endcode
376  *
377  * @param name the filename of the process to start
378  */
379  explicit KGameProcessIO(const QString &name);
380 
381  /**
382  * Deletes the process input devices
383  */
384  ~KGameProcessIO() override;
385 
386  /**
387  * The identification of the IO
388  *
389  * @return ProcessIO
390  */
391  int rtti() const override;
392 
393  /**
394  * Send a message to the process. This is analogous to the sendMessage
395  * commands of KGame. It will result in a signal of the computer player
396  * on which you can react in the process player.
397  *
398  * @param stream - the actual data
399  * @param msgid - the id of the message
400  * @param receiver - not used
401  * @param sender - who send the message
402  */
403  void sendMessage(QDataStream &stream, int msgid, quint32 receiver, quint32 sender);
404 
405  /**
406  * Send a system message to the process. This is analogous to the sendMessage
407  * commands of KGame. It will result in a signal of the computer player
408  * on which you can react in the process player.
409  *
410  * @param stream - the actual data
411  * @param msgid - the id of the message
412  * @param receiver - not used
413  * @param sender - who send the message
414  */
415  void sendSystemMessage(QDataStream &stream, int msgid, quint32 receiver, quint32 sender);
416 
417  /**
418  * Init this device by setting the player and e.g. sending an
419  * init message to the device. Calling this function will emit
420  * the IOAdded signal on which you can react and initilise the
421  * computer player.
422  * This function is called automatically when adding the IO to
423  * a player.
424  */
425  void initIO(KPlayer *p) override;
426 
427  /**
428  * Notifies the IO device that the player's setTurn had been called
429  * Called by KPlayer. You can react on the @ref signalPrepareTurn to
430  * prepare a message for the process, i.e. either update it on
431  * the changes made to the game since the last turn or the initIO
432  * has been called or transmit your gamestatus now.
433  *
434  * @param turn is true/false
435  */
436  void notifyTurn(bool turn) override;
437 
438 protected:
439  /**
440  * Internal combined function for all message handling
441  */
442  void sendAllMessages(QDataStream &stream, int msgid, quint32 receiver, quint32 sender, bool usermsg);
443 
444 protected Q_SLOTS:
445  /**
446  * Internal message handler to receive data from the process
447  */
448  void receivedMessage(const QByteArray &receiveBuffer);
449 
450 Q_SIGNALS:
451  /**
452  * A computer query message is received. This is a 'dummy'
453  * message sent by the process if it needs to communicate
454  * with us. It is not forwarded over the network.
455  * Reacting to this message allows you to 'answer' questions
456  * of the process, e.g. sending addition data which the process
457  * needs to calculate a move.
458  *
459  * Example:
460  * \code
461  * void GameWindow::slotProcessQuery(QDataStream &stream,KGameProcessIO *reply)
462  * {
463  * int no;
464  * stream >> no; // We assume the process sends us an integer question number
465  * if (no==1) // but YOU have to do this in the process player
466  * {
467  * QByteArray buffer;
468  * QDataStream out(buffer,QIODevice::WriteOnly);
469  * reply->sendSystemMessage(out,4242,0,0); // lets reply something...
470  * }
471  * }
472  * \endcode
473  */
474  void signalProcessQuery(QDataStream &stream, KGameProcessIO *me);
475 
476  /**
477  * Signal generated when the computer player is added.
478  * You can use this to communicated with the process and
479  * e.g. send initialisation information to the process.
480  *
481  * @param game the KGameIO object itself
482  * @param stream the stream into which the move will be written
483  * @param p the player itself
484  * @param send set this to false if no move should be generated
485  */
486  void signalIOAdded(KGameIO *game, QDataStream &stream, KPlayer *p, bool *send);
487 
488  /** Text is received by the process on STDERR. This is usually a debug string.
489  * @param msg The text
490  */
491  void signalReceivedStderr(const QString &msg);
492 
493 private:
494  Q_DECLARE_PRIVATE_D(KGameIO::d, KGameProcessIO)
495  friend class KGameProcessIOPrivate;
496 #if KDEGAMESPRIVATE_BUILD_DEPRECATED_SINCE(7, 3)
497  // Unused, kept for ABI compatibility
498  const void *__kdegames_d_do_not_use;
499 #endif
500 
502 };
503 
504 /**
505  * \class KGameComputerIO kgameio.h <KGame/KGameIO>
506  *
507  * \brief KGameIO variant for real-time games
508  *
509  * The KGameComputerIO class. It is used to create a LOCAL computer player
510  * and communicate transparently with it.
511  * Question: Is this needed or is it overwritten anyway for a real game?
512  *
513  * You most probably don't want to use this if you want to design a turn based
514  * game/player. You'll rather use @ref KGameIO directly, i.e. subclass it
515  * yourself. You just need to use @ref KGameIO::signalPrepareTurn and/or @ref
516  * KGameIO::notifyTurn there.
517  *
518  * This is rather meant to be of use in real time games.
519  *
520  * @author <[email protected]>
521  */
522 class KDEGAMESPRIVATE_EXPORT KGameComputerIO : public KGameIO
523 {
524  Q_OBJECT
525 
526 public:
527  /**
528  * Creates a LOCAL computer player
529  *
530  */
531  KGameComputerIO();
532  explicit KGameComputerIO(KPlayer *player);
533  ~KGameComputerIO() override;
534 
535  int rtti() const override;
536 
537  /**
538  * The number of advance calls until the player (or rather: the IO)
539  * does something (default: 1).
540  */
541  void setReactionPeriod(int advanceCalls);
542  int reactionPeriod() const;
543 
544  /**
545  * Start a QTimer which calls advance every @p ms milli seconds.
546  */
547  void setAdvancePeriod(int ms);
548 
549  void stopAdvancePeriod();
550 
551  /**
552  * Ignore calls number of advance calls. if calls is -1 then all
553  * following advance calls are ignored until unpause is called.
554  *
555  * This simply prevents the internal advance counter to be increased.
556  *
557  * You may want to use this to emulate a "thinking" computer player. Note
558  * that this means if you increase the advance period (see
559  * setAdvancePeriod), i.e. if you change the speed of your game, your
560  * computer player thinks "faster".
561  * @param calls Number of advance calls to be ignored
562  */
563  void pause(int calls = -1);
564 
565  /**
566  * Equivalent to pause(0). Immediately continue to increase the internal
567  * advance counter.
568  */
569  void unpause();
570 
571 public Q_SLOTS:
572  /**
573  * Works kind of similar to QCanvas::advance. Increase the internal
574  * advance counter. If @p reactionPeriod is reached the counter is set back to
575  * 0 and @ref signalReaction is emitted. This is when the player is meant
576  * to do something (move its units or so).
577  *
578  * This is very useful if you use QCanvas as you can use this in your
579  * QCanvas::advance call. The advantage is that if you change the speed
580  * of the game (i.e. change QCanvas::setAdvancePeriod) the computer
581  * player gets slower as well.
582  *
583  * If you don't use QCanvas you can use setAdvancePeriod to get
584  * the same result. Alternatively you can just use a QTimer.
585  *
586  */
587  virtual void advance();
588 
589 Q_SIGNALS:
590  /**
591  * This signal is emitted when your computer player is meant to do
592  * something, or better is meant to be allowed to do something.
593  */
594  void signalReaction();
595 
596 protected:
597  /**
598  * Default implementation simply emits signalReaction
599  */
600  virtual void reaction();
601 
602 private:
603  Q_DECLARE_PRIVATE_D(KGameIO::d, KGameComputerIO)
604  friend class KGameComputerIOPrivate;
605 #if KDEGAMESPRIVATE_BUILD_DEPRECATED_SINCE(7, 3)
606  // Unused, kept for ABI compatibility
607  const void *__kdegames_d_do_not_use;
608 #endif
609 
611 };
612 
613 #endif
virtual void initIO(KPlayer *p)
Init this device by setting the player and e.g.
Definition: kgameio.cpp:77
virtual void notifyTurn(bool b)
Notifies the IO device that the player's setTurn had been called Called by KPlayer.
Definition: kgameio.cpp:82
Q_SLOTSQ_SLOTS
Base class for IO devices for games.
Definition: kgameio.h:56
IOMode
Identifies the KGameIO via the rtti function.
Definition: kgameio.h:76
The main KDE game object.
Definition: kgame.h:55
Base class for a game player.
Definition: kplayer.h:59
virtual bool eventFilter(QObject *watched, QEvent *event)
Q_SCRIPTABLE Q_NOREPLY void pause()
Q_SIGNALSQ_SIGNALS
virtual int rtti() const =0
Run time identification.
KGameIO variant for real-time games.
Definition: kgameio.h:522
Q_DISABLE_COPY(Class)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon May 8 2023 03:49:44 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.