[Kde-games-devel] A design issue when using C++

Kevin Krammer kevin.krammer at gmx.at
Sat Mar 14 11:43:34 CET 2009


Hi Ian,

On Saturday 14 March 2009, Ian Wadham wrote:

[snip]

> The problem is that each runner (the hero and each enemy) sometimes needs
> to know what is going on outside the square he is in.  For example, the
> hero needs to know where to head next, based on where the pointer is or
> what key has been pressed and an enemy needs to know if he can enter a
> square which might be occupied by another enemy.
>
> To solve this problem, I have added a number of "helper" methods to the
> KGrLevelPlayer class, while I have been hacking away at the KGrHero and
> KGrEnemy code, but the methods are all <public>.
>
> That seems not at all elegant.  It would make no sense, for example, for
> the KGrGame class that creates a KGrLevelPlayer object to call these
> "helper" methods.  They are only meaningful in the context of a KGrHero
> or KGrEnemy method.  Of course, I can easily avoid such meaningless
> calls in practice (and have done that) and so the code all works OK.

Right, Since you are not exposing any public API, you don't have to worry too 
much about access restrictions.

> I thought of having KGrHero and KGrEnemy double-inherit the level
> player and making the helper methods <protected>, but I am keen to
> keep overheads low (one level has 25 enemies, all active 50 times
> a second) and there is not much family "relationship" between the
> KGrLevelPlayer and runner objects, no more than between a soccer
> player and a soccer match, say.

No, this is definitely wrong, your runners are not the play controllers but 
participants.

What you can easily do is to create a runner related "view" on your 
LevelPlayer object which contains only the methods needed for the runners.
(potentially two different ones, one for the hero, one for the enemies).
Then you pass a pointer to that to the runners instead.

Since the LevelPlayer creates runners and the view object(s), it decides who 
to pass it to, who gains access to that methods.

The simplest implementation of such views is to make their classes friends of 
the LevelPlayer so they can just forward the calls to the LevelPlayer 
instance.

A bit like this:

class EnemyView
{
  friend class LevelPlayer;

public:
  Directiony getDirection( int i, int j )
 {
    return mLevelPlayer->getEnemyDirectiony( i, j );
  }

private:
  // Level Player is our friend and can thus call the private constructor
  // Nobody else can create instances of the view
  EnemyView( LevelPlayer *levelPlayer ) : mLevelPlayer( levelPlayer ) {}

  LevelPlayer *mLevelPlayer;
};

class LevelPlayer
{
  friend class EnemyView;

public:
  LevelPlayer() :mEnemyView( new EnemyView( this ) )  {}

  void init()
  {
    Enemy *enemy = new Enemy( mEnemyView );
  }

private:
  EnemyView *mEnemyView;

  Direction getEnemyDirection(int i, int j);
};

Cheers,
Kevin
-- 
Kevin Krammer, KDE developer, xdg-utils developer
KDE user support, developer mentoring
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part.
Url : http://mail.kde.org/pipermail/kde-games-devel/attachments/20090314/4b435620/attachment.sig 


More information about the kde-games-devel mailing list