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{
58 Q_OBJECT
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{
199 Q_OBJECT
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{
278 Q_OBJECT
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{
359 Q_OBJECT
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{
518 Q_OBJECT
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
KGameIO variant for real-time games.
Definition kgameio.h:517
void signalReaction()
This signal is emitted when your computer player is meant to do something, or better is meant to be a...
Base class for IO devices for games.
Definition kgameio.h:57
void signalPrepareTurn(QDataStream &stream, bool turn, KGameIO *io, bool *send)
Signal generated when KPlayer::myTurn changes.
virtual int rtti() const =0
Run time identification.
IOMode
Identifies the KGameIO via the rtti function.
Definition kgameio.h:76
The KGameKeyIO class.
Definition kgameio.h:198
void signalKeyEvent(KGameIO *io, QDataStream &stream, QKeyEvent *m, bool *eatevent)
Signal handler for keyboard events.
The KGameMouseIO class.
Definition kgameio.h:277
void signalMouseEvent(KGameIO *io, QDataStream &stream, QMouseEvent *m, bool *eatevent)
Signal handler for mouse events.
The KGameProcessIO class.
Definition kgameio.h:358
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.
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()
Q_SIGNALSQ_SIGNALS
Q_SLOTSQ_SLOTS
virtual bool eventFilter(QObject *watched, QEvent *event)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 8 2024 12:03:04 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.