You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
572 lines
18 KiB
572 lines
18 KiB
/*
|
|
This file is part of the TDE games library
|
|
Copyright (C) 2001 Martin Heni (martin@heni-online.de)
|
|
Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de)
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License version 2 as published by the Free Software Foundation.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
/*
|
|
$Id$
|
|
*/
|
|
#ifndef __KGAMEIO_H__
|
|
#define __KGAMEIO_H__
|
|
|
|
#include <tqstring.h>
|
|
#include <tqobject.h>
|
|
#include <kdemacros.h>
|
|
class KPlayer;
|
|
class KGame;
|
|
class KProcess;
|
|
|
|
/**
|
|
* \short Base class for IO devices for games
|
|
*
|
|
* This is the master class for
|
|
* creating IO game devices. You cannot use it directly.
|
|
* Either take one of the classes derived from it or
|
|
* you have to create your own IO class derived from it (more probably).
|
|
*
|
|
* The idea behind this class is to provide a common interface
|
|
* for input devices into your game. By programming a KGameIO
|
|
* device you need not distinguish the actual IO in the game
|
|
* anymore. All work is done by the IO's. This allows very
|
|
* easy reuse in other games as well.
|
|
* A further advantage of using the IO's is that you can exchange
|
|
* the control of a player at runtime. E.g. you switch a player
|
|
* to be controlled by the computer or vice versa.
|
|
*
|
|
* To achieve this you have to make all of your player inputs through a
|
|
* KGameIO. You will usually call KGameIO::sendInput to do so.
|
|
*
|
|
* @author Martin Heni <martin@heni-online.de>
|
|
*/
|
|
class KDE_EXPORT KGameIO : public TQObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
|
|
public:
|
|
/**
|
|
* Constructs a KGameIO object
|
|
*/
|
|
KGameIO();
|
|
KGameIO(KPlayer*);
|
|
virtual ~KGameIO();
|
|
|
|
/**
|
|
* Gives debug output of the game status
|
|
*/
|
|
void Debug();
|
|
|
|
/**
|
|
* Identifies the KGameIO via the rtti function
|
|
*/
|
|
enum IOMode {GenericIO=1,KeyIO=2,MouseIO=4,ProcessIO=8,ComputerIO=16};
|
|
/**
|
|
* Run time idendification. Predefined values are from IOMode
|
|
* You MUST overwrite this in derived classes!
|
|
*
|
|
* @return rtti value
|
|
*/
|
|
virtual int rtti() const = 0; // Computer, network, local, ...
|
|
|
|
/**
|
|
* This function returns the player who owns this IO
|
|
*
|
|
* @return the player this IO device is plugged into
|
|
*/
|
|
KPlayer *player() const {return mPlayer;}
|
|
|
|
/**
|
|
* Equivalent to player()->game()
|
|
* @return the @ref KGame object of this player
|
|
**/
|
|
KGame* game() const;
|
|
|
|
/**
|
|
* Sets the player to which this IO belongs to. This
|
|
* is done automatically when adding a device to a
|
|
* player
|
|
*
|
|
* @param p the player
|
|
*/
|
|
void setPlayer(KPlayer *p) {mPlayer=p;}
|
|
|
|
/**
|
|
* Init this device by setting the player and e.g. sending an
|
|
* init message to the device. This initialisation message is
|
|
* very useful for computer players as you can transmit the
|
|
* game status to them and only update this status in the setTurn
|
|
* commands.
|
|
*
|
|
* Called by @ref KPlayer::addGameIO only!
|
|
*/
|
|
virtual void initIO(KPlayer *p);
|
|
|
|
/**
|
|
* Notifies the IO device that the player's setTurn had been called
|
|
* Called by KPlayer
|
|
*
|
|
* This emits @ref signalPrepareTurn and sends the turn if the send
|
|
* parameter is set to true.
|
|
*
|
|
* @param b turn is true/false
|
|
*/
|
|
virtual void notifyTurn(bool b);
|
|
|
|
/**
|
|
* Send an input message using @ref KPlayer::forwardInput
|
|
**/
|
|
bool sendInput(TQDataStream& stream, bool transmit = true, TQ_UINT32 sender = 0);
|
|
|
|
signals:
|
|
/**
|
|
* Signal generated when @ref KPlayer::myTurn changes. This can either be
|
|
* when you get the turn status or when you lose it.
|
|
*
|
|
* The datastream has to be filled with a move. If you set (or leave) the
|
|
* send parameter to FALSE then nothing happens: the datastream will be
|
|
* ignored. If you set it to TRUE @ref sendInput is used to
|
|
* send the move.
|
|
*
|
|
* Often you want to ignore this signal (leave send=FALSE) and send the
|
|
* message later. This is usually the case for a human player as he probably
|
|
* doesn't react immediately. But you can still use this e.g. to notify the
|
|
* player about the turn change.
|
|
*
|
|
* Example:
|
|
* \code
|
|
* void GameWindow::slotPrepareTurn(TQDataStream &stream,bool b,KGameIO *input,bool * )
|
|
* {
|
|
* KPlayer *player=input->player();
|
|
* if (!player->myTurn()) return ;
|
|
* if (!b) return ; // only do something on setTurn(true)
|
|
* stream << 1 << 2 << 3; // Some data for the process
|
|
* }
|
|
* \endcode
|
|
*
|
|
* @param io the KGameIO object itself
|
|
* @param stream the stream into which the move will be written
|
|
* @param turn the argument of setTurn
|
|
* @param send set this to true to send the generated move using @ref
|
|
* sendInput
|
|
**/
|
|
void signalPrepareTurn(TQDataStream & stream, bool turn, KGameIO *io, bool * send);
|
|
|
|
|
|
private:
|
|
KPlayer *mPlayer;
|
|
};
|
|
|
|
/**
|
|
* The KGameKeyIO class. It is used to process keyboard input
|
|
* from a widget and create moves for the player it belongs to.
|
|
* @author Martin Heni <martin@heni-online.de>
|
|
*/
|
|
class KDE_EXPORT KGameKeyIO : public KGameIO
|
|
{
|
|
Q_OBJECT
|
|
|
|
|
|
public:
|
|
/**
|
|
* Create a keyboard input devices. All keyboards
|
|
* inputs of the given widgets are passed through a signal
|
|
* handler signalKeyEvent and can be used to generate
|
|
* a valid move for the player.
|
|
* Note the widget you pass to the constructor must be
|
|
* the main window of your application, e.g. view->parentWidget()
|
|
* as QT does not forward your keyevents otherwise. This means
|
|
* that this might be a different widget comapred to the one you
|
|
* use for mouse inputs!
|
|
* Example:
|
|
* \code
|
|
* KGameKeyIO *input;
|
|
* input=new KGameKeyIO(myWidget);
|
|
* connect(input,TQT_SIGNAL(signalKeyEvent(KGameIO *,TQDataStream &,TQKeyEvent *,bool *)),
|
|
* this,TQT_SLOT(slotKeyInput(KGameIO *,TQDataStream &,TQKeyEvent *,bool *)));
|
|
* \endcode
|
|
*
|
|
* @param parent The parents widget whose keyboard events * should be grabbed
|
|
*/
|
|
KGameKeyIO(TQWidget *parent);
|
|
virtual ~KGameKeyIO();
|
|
|
|
/**
|
|
* The idendification of the IO
|
|
*
|
|
* @return KeyIO
|
|
*/
|
|
virtual int rtti() const;
|
|
|
|
signals:
|
|
/**
|
|
* Signal handler for keyboard events. This function is called
|
|
* on every keyboard event. If appropriate it can generate a
|
|
* move for the player the device belongs to. If this is done
|
|
* and the event is eaten eatevent needs to be set to true.
|
|
* What move you generate (i.e. what you write to the stream)
|
|
* is totally up to you as it will not be evaluated but forwared
|
|
* to the player's/game's input move function
|
|
* Example:
|
|
* \code
|
|
* KPlayer *player=input->player(); // Get the player
|
|
* TQ_INT32 key=e->key();
|
|
* stream << key;
|
|
* eatevent=true;
|
|
* \endcode
|
|
*
|
|
* @param io the IO device we belong to
|
|
* @param stream the stream where we write our move into
|
|
* @param m The TQKeyEvent we can evaluate
|
|
* @param eatevent set this to true if we processed the event
|
|
*/
|
|
void signalKeyEvent(KGameIO *io,TQDataStream &stream,TQKeyEvent *m,bool *eatevent);
|
|
|
|
protected:
|
|
/**
|
|
* Internal method to process the events
|
|
*/
|
|
bool eventFilter( TQObject *o, TQEvent *e );
|
|
};
|
|
|
|
/**
|
|
* The KGameMouseIO class. It is used to process mouse input
|
|
* from a widget and create moves for the player it belongs to.
|
|
* @author Martin Heni <martin@heni-online.de>
|
|
*/
|
|
class KDE_EXPORT KGameMouseIO : public KGameIO
|
|
{
|
|
Q_OBJECT
|
|
|
|
|
|
public:
|
|
/**
|
|
* Creates a mouse IO device. It captures all mouse
|
|
* event of the given widget and forwards them to the
|
|
* signal handler signalMouseEvent.
|
|
* Example:
|
|
* \code
|
|
* KGameMouseIO *input;
|
|
* input=new KGameMouseIO(mView);
|
|
* connect(input,TQT_SIGNAL(signalMouseEvent(KGameIO *,TQDataStream &,TQMouseEvent *,bool *)),
|
|
* this,TQT_SLOT(slotMouseInput(KGameIO *,TQDataStream &,TQMouseEvent *,bool *)));
|
|
* \endcode
|
|
*
|
|
* @param parent The widget whose events should be captured
|
|
* @param trackmouse enables mouse tracking (gives mouse move events)
|
|
*/
|
|
KGameMouseIO(TQWidget *parent,bool trackmouse=false);
|
|
virtual ~KGameMouseIO();
|
|
|
|
/**
|
|
* Manually activate or deactivate mouse tracking
|
|
*
|
|
* @param b true = tracking on
|
|
*/
|
|
void setMouseTracking(bool b);
|
|
/**
|
|
* The idendification of the IO
|
|
*
|
|
* @return MouseIO
|
|
*/
|
|
virtual int rtti() const;
|
|
|
|
signals:
|
|
/**
|
|
* Signal handler for mouse events. This function is called
|
|
* on every mouse event. If appropriate it can generate a
|
|
* move for the player the device belongs to. If this is done
|
|
* and the event is eaten eatevent needs to be set to true.
|
|
* @see signalKeyEvent
|
|
* Example:
|
|
* \code
|
|
* KPlayer *player=input->player(); // Get the player
|
|
* TQ_INT32 button=e->button();
|
|
* stream << button;
|
|
* eatevent=true;
|
|
* \endcode
|
|
*
|
|
* @param io the IO device we belong to
|
|
* @param stream the stream where we write our move into
|
|
* @param m The TQMouseEvent we can evaluate
|
|
* @param eatevent set this to true if we processed the event
|
|
*/
|
|
void signalMouseEvent(KGameIO *io,TQDataStream &stream,TQMouseEvent *m,bool *eatevent);
|
|
|
|
protected:
|
|
/**
|
|
* Internal event filter
|
|
*/
|
|
bool eventFilter( TQObject *o, TQEvent *e );
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* The KGameProcessIO class. It is used to create a computer player
|
|
* via a separate process and communicate transparetly with it.
|
|
* Its counterpart is the @ref KGameProcess class which needs
|
|
* to be used by the computer player. See its documentation
|
|
* for the definition of the computer player.
|
|
* @author Martin Heni <martin@heni-online.de>
|
|
*/
|
|
class KDE_EXPORT KGameProcessIO : public KGameIO
|
|
{
|
|
Q_OBJECT
|
|
|
|
|
|
public:
|
|
/**
|
|
* Creates a computer player via a separate process. The process
|
|
* name is given as fully qualified filename.
|
|
* Example:
|
|
* \code
|
|
* KGameProcessIO *input;
|
|
* input=new KGameProcessIO(executable_file);
|
|
* connect(input,TQT_SIGNAL(signalPrepareTurn(TQDataStream &,bool,KGameIO *,bool *)),
|
|
* this,TQT_SLOT(slotPrepareTurn(TQDataStream &,bool,KGameIO *,bool *)));
|
|
* connect(input,TQT_SIGNAL(signalProcessQuery(TQDataStream &,KGameProcessIO *)),
|
|
* this,TQT_SLOT(slotProcessQuery(TQDataStream &,KGameProcessIO *)));
|
|
* \endcode
|
|
*
|
|
* @param name the filename of the process to start
|
|
*/
|
|
KGameProcessIO(const TQString& name);
|
|
|
|
/**
|
|
* Deletes the process input devices
|
|
*/
|
|
virtual ~KGameProcessIO();
|
|
|
|
/**
|
|
* The idendification of the IO
|
|
*
|
|
* @return ProcessIO
|
|
*/
|
|
int rtti() const;
|
|
|
|
/**
|
|
* Send a message to the process. This is analogous to the sendMessage
|
|
* commands of KGame. It will result in a signal of the computer player
|
|
* on which you can react in the process player.
|
|
*
|
|
* @param stream - the actual data
|
|
* @param msgid - the id of the message
|
|
* @param receiver - not used
|
|
* @param sender - who send the message
|
|
*/
|
|
void sendMessage(TQDataStream &stream,int msgid, TQ_UINT32 receiver, TQ_UINT32 sender);
|
|
|
|
/**
|
|
* Send a system message to the process. This is analogous to the sendMessage
|
|
* commands of KGame. It will result in a signal of the computer player
|
|
* on which you can react in the process player.
|
|
*
|
|
* @param stream - the actual data
|
|
* @param msgid - the id of the message
|
|
* @param receiver - not used
|
|
* @param sender - who send the message
|
|
*/
|
|
void sendSystemMessage(TQDataStream &stream, int msgid, TQ_UINT32 receiver, TQ_UINT32 sender);
|
|
|
|
/**
|
|
* Init this device by setting the player and e.g. sending an
|
|
* init message to the device. Calling this function will emit
|
|
* the IOAdded signal on which you can react and initilise the
|
|
* computer player.
|
|
* This function is called automatically when adding the IO to
|
|
* a player.
|
|
*/
|
|
void initIO(KPlayer *p);
|
|
|
|
/**
|
|
* Notifies the IO device that the player's setTurn had been called
|
|
* Called by KPlayer. You can react on the @ref signalPrepareTurn to
|
|
* prepare a message for the process, i.e. either update it on
|
|
* the changes made to the game since the last turn or the initIO
|
|
* has been called or transmit your gamestatus now.
|
|
*
|
|
* @param turn is true/false
|
|
*/
|
|
virtual void notifyTurn(bool turn);
|
|
|
|
protected:
|
|
/**
|
|
* Internal ~ombined function for all message handling
|
|
**/
|
|
void sendAllMessages(TQDataStream &stream,int msgid, TQ_UINT32 receiver, TQ_UINT32 sender, bool usermsg);
|
|
|
|
protected slots:
|
|
/**
|
|
* Internal message handler to receive data from the process
|
|
*/
|
|
void receivedMessage(const TQByteArray& receiveBuffer);
|
|
|
|
|
|
signals:
|
|
/**
|
|
* A computer query message is received. This is a 'dummy'
|
|
* message sent by the process if it needs to communicate
|
|
* with us. It is not forwarded over the network.
|
|
* Reacting to this message allows you to 'answer' questions
|
|
* of the process, e.g. sending addition data which the process
|
|
* needs to calculate a move.
|
|
*
|
|
* Example:
|
|
* \code
|
|
* void GameWindow::slotProcessQuery(TQDataStream &stream,KGameProcessIO *reply)
|
|
* {
|
|
* int no;
|
|
* stream >> no; // We assume the process sends us an integer question numner
|
|
* if (no==1) // but YOU have to do this in the process player
|
|
* {
|
|
* TQByteArray buffer;
|
|
* TQDataStream out(buffer,IO_WriteOnly);
|
|
* reply->sendSystemMessage(out,4242,0,0); // lets reply something...
|
|
* }
|
|
* }
|
|
* \endcode
|
|
*/
|
|
void signalProcessQuery(TQDataStream &stream,KGameProcessIO *me);
|
|
|
|
/**
|
|
* Signal generated when the computer player is added.
|
|
* You can use this to communicated with the process and
|
|
* e.g. send initialisation information to the process.
|
|
*
|
|
* @param game the KGameIO object itself
|
|
* @param stream the stream into which the move will be written
|
|
* @param p the player itself
|
|
* @param send set this to false if no move should be generated
|
|
*/
|
|
void signalIOAdded(KGameIO *game,TQDataStream &stream,KPlayer *p,bool *send);
|
|
|
|
|
|
protected:
|
|
|
|
private:
|
|
class KGameProcessIOPrivate;
|
|
KGameProcessIOPrivate* d;
|
|
};
|
|
|
|
/**
|
|
* \brief KGameIO variant for real-time games
|
|
*
|
|
* The KGameComputerIO class. It is used to create a LOCAL computer player
|
|
* and communicate transparently with it.
|
|
* Question: Is this needed or is it overwritten anyway for a real game?
|
|
*
|
|
* You most probably don't want to use this if you want to design a turn based
|
|
* game/player. You'll rather use @ref KGameIO directly, i.e. subclass it
|
|
* yourself. You just need to use @ref KGameIO::signalPrepareTurn and/or @ref
|
|
* KGameIO::notifyTurn there.
|
|
*
|
|
* This is rather meant to be of use in real time games.
|
|
*
|
|
* @author <b_mann@gmx.de>
|
|
*/
|
|
class KDE_EXPORT KGameComputerIO : public KGameIO
|
|
{
|
|
Q_OBJECT
|
|
|
|
|
|
public:
|
|
/**
|
|
* Creates a LOCAL computer player
|
|
*
|
|
*/
|
|
KGameComputerIO();
|
|
KGameComputerIO(KPlayer* player);
|
|
~KGameComputerIO();
|
|
|
|
int rtti() const;
|
|
|
|
/**
|
|
* The number of advance calls until the player (or rather: the IO)
|
|
* does something (default: 1).
|
|
**/
|
|
void setReactionPeriod(int advanceCalls);
|
|
int reactionPeriod() const;
|
|
|
|
/**
|
|
* Start a TQTimer which calls advance every @p ms milli seconds.
|
|
**/
|
|
void setAdvancePeriod(int ms);
|
|
|
|
void stopAdvancePeriod();
|
|
|
|
/**
|
|
* Ignore calls number of advance calls. if calls is -1 then all
|
|
* following advance calls are ignored until unpause is called.
|
|
*
|
|
* This simply prevents the internal advance counter to be increased.
|
|
*
|
|
* You may want to use this to emulate a "thinking" computer player. Note
|
|
* that this means if you increase the advance period (see
|
|
* setAdvancePeriod), i.e. if you change the speed of your game, your
|
|
* computer player thinks "faster".
|
|
* @param calls Number of advance calls to be ignored
|
|
**/
|
|
void pause(int calls = -1);
|
|
|
|
/**
|
|
* Equivalent to pause(0). Immediately continue to increase the internal
|
|
* advance counter.
|
|
**/
|
|
void unpause();
|
|
|
|
public slots:
|
|
/**
|
|
* Works kind of similar to TQCanvas::advance. Increase the internal
|
|
* advance counter. If @p reactionPeriod is reached the counter is set back to
|
|
* 0 and @ref signalReaction is emitted. This is when the player is meant
|
|
* to do something (move its units or so).
|
|
*
|
|
* This is very useful if you use TQCanvas as you can use this in your
|
|
* TQCanvas::advance call. The advantage is that if you change the speed
|
|
* of the game (i.e. change TQCanvas::setAdvancePeriod) the computer
|
|
* player gets slower as well.
|
|
*
|
|
* If you don't use TQCanvas you can use setAdvancePeriod to get
|
|
* the same result. Alternatively you can just use a TQTimer.
|
|
*
|
|
**/
|
|
virtual void advance();
|
|
|
|
signals:
|
|
/**
|
|
* This signal is emitted when your computer player is meant to do
|
|
* something, or better is meant to be allowed to do something.
|
|
**/
|
|
void signalReaction();
|
|
|
|
protected:
|
|
/**
|
|
* Default implementation simply emits signalReaction
|
|
**/
|
|
virtual void reaction();
|
|
|
|
private:
|
|
void init();
|
|
|
|
private:
|
|
class KGameComputerIOPrivate;
|
|
KGameComputerIOPrivate* d;
|
|
};
|
|
|
|
|
|
#endif
|