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

KDE's Doxygen guidelines are available online.