Skip to content

Commit

Permalink
game event logging (see #18 and #12)
Browse files Browse the repository at this point in the history
i spent too much time on that…
  • Loading branch information
t3kt committed Dec 9, 2014
1 parent 10f4ef8 commit e0ada1b
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 38 deletions.
2 changes: 2 additions & 0 deletions src/Ball.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class Ball : public GameObject, public ofxBox2dCircle {
void setPlayer(Player* player) { _player = player; }

void output(std::ostream& os) const override;

static const char* typeName() { return "ball"; }
private:
Player* _player;
};
Expand Down
6 changes: 4 additions & 2 deletions src/Brick.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ class Brick : public GameObject, public ofxBox2dRect {
public:
Brick() : GameObject(GAME_OBJECT_BRICK), _value(1) {}

void output(std::ostream& os) const override;

int value() const { return _value; }
void setValue(int value) { _value = value; }

void output(std::ostream& os) const override;

static const char* typeName() { return "brick"; }
private:
int _value;
};
Expand Down
72 changes: 49 additions & 23 deletions src/GameEvents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,44 +9,70 @@
#include "GameEvents.h"
#include <ofLog.h>

template<typename EventType>
static void logEvent(ofLogLevel level, const char* name, const EventType& e) {
ofLog log(level);
log << "EVENT{" << name << "}: ";
std::ostringstream sstr;
e.output(sstr);
log << sstr.str();
}

class CollisionLogger {
public:
CollisionLogger(ofLogLevel level) : _level(level) { }

void onBallHitPaddle(BallHitPaddleEventArgs& e) {
ofLog(_level) << "EVENT: ballHitPaddle: " << *(e.ball())
<< " " << *(e.object());
#define EVENT_LOGGER_CALLBACK(EventName, ArgsType) \
void on##EventName(ArgsType& e) { \
logEvent(_level, #EventName, e);\
}

void onBallHitBrick(BallHitBrickEventArgs& e) {
ofLog(_level) << "EVENT: ballHitBrick: " << *(e.ball())
<< " " << e.object();
}
class CollisionEventLogger {
public:
CollisionEventLogger(ofLogLevel level) : _level(level) { }

void onBallHitWall(BallHitWallEventArgs& e) {
ofLog(_level) << "EVENT: ballHitWall: " << *(e.ball())
<< " " << *(e.object());
}

void onBallHitBall(BallHitBallEventArgs& e) {
ofLog(_level) << "EVENT: ballHitBall: " << *(e.ball())
<< " " << *(e.object());
}
EVENT_LOGGER_CALLBACK(BallHitPaddle, BallHitPaddleEventArgs);
EVENT_LOGGER_CALLBACK(BallHitBrick, BallHitBrickEventArgs);
EVENT_LOGGER_CALLBACK(BallHitWall, BallHitWallEventArgs);
EVENT_LOGGER_CALLBACK(BallHitBall, BallHitBallEventArgs);
private:
ofLogLevel _level;
};


void CollisionEventSource::enableLogging(ofLogLevel level) {
disableLogging();
_logger.reset(new CollisionLogger(level));
_logger.reset(new CollisionEventLogger(level));
attachListener(*_logger);
}

void CollisionEventSource::disableLogging() {
if (_logger)
removeListener(*_logger);
detachListener(*_logger);
_logger.reset();
}

class RoundStateEventLogger {
public:
RoundStateEventLogger(ofLogLevel level) : _level(level) { }

EVENT_LOGGER_CALLBACK(BallOwnerChanged, BallOwnerChangedEventArgs);
EVENT_LOGGER_CALLBACK(BrickDestroyed, BrickDestroyedEventArgs);
EVENT_LOGGER_CALLBACK(PlayerScoreChanged, PlayerEventArgs);
EVENT_LOGGER_CALLBACK(BallDestroyed, BallEventArgs);
EVENT_LOGGER_CALLBACK(BallRespawned, BallEventArgs);
EVENT_LOGGER_CALLBACK(PlayerLost, PlayerEventArgs);
EVENT_LOGGER_CALLBACK(PlayerLivesChanged, PlayerEventArgs);
EVENT_LOGGER_CALLBACK(RoundEnded, EmptyEventArgs);
private:
ofLogLevel _level;
};

void RoundStateEventSource::enableLogging(ofLogLevel level) {
disableLogging();
_logger.reset(new RoundStateEventLogger(level));
attachListener(*_logger);
}

void RoundStateEventSource::disableLogging() {
if (_logger)
detachListener(*_logger);
_logger.reset();
}


156 changes: 144 additions & 12 deletions src/GameEvents.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,89 @@
#define __bleepout__GameEvents__

#include <ofTypes.h>
#include <ofLog.h>
#include <iostream>
#include "GameObject.h"
#include "Player.h"
#include "Brick.h"
#include "Paddle.h"
#include "Ball.h"
#include "Wall.h"
#include <ofLog.h>

template<typename T>
void outputField(std::ostream& os, const char* label, const T* obj) {
os << label << ": ";
if (obj)
os << *obj;
else
os << "(null)";
}

template<typename T>
void outputField(std::ostream& os, const T* obj) {
outputField(os, T::typeName(), obj);
}

class EmptyEventArgs {
public:
void output(std::ostream& os) const { }
};

template<typename T>
class ObjectEventArgs {
public:
explicit ObjectEventArgs(T* obj) : _object(obj) { }

T* object() { return _object; }
const T* object() const { return _object; }

void output(std::ostream& os) const {
os << "(";
outputField(os, object());
os << ")";
}
private:
T* _object;
};

template<typename T>
std::ostream& operator<<(std::ostream& os, const ObjectEventArgs<T>& e) {
e.output(os);
return os;
}

template<typename T>
class BallHitObjectEventArgs : public ObjectEventArgs<T> {
public:
BallHitObjectEventArgs(Ball* ball, T* object)
: _ball(ball), ObjectEventArgs<T>(object) { }

Ball* ball() { return _ball; }
const Ball* ball() const { return _ball; }

void output(std::ostream& os) const {
os << "(";
outputField(os, ball());
os << " ";
outputField(os, ObjectEventArgs<T>::object());
os << ")";
}
private:
Ball* _ball;
};

template<typename T>
std::ostream& operator<<(std::ostream& os, const BallHitObjectEventArgs<T>& e) {
e.output(os);
return os;
}

typedef BallHitObjectEventArgs<Paddle> BallHitPaddleEventArgs;
typedef BallHitObjectEventArgs<Brick> BallHitBrickEventArgs;
typedef BallHitObjectEventArgs<Wall> BallHitWallEventArgs;
typedef BallHitObjectEventArgs<Ball> BallHitBallEventArgs;

class CollisionLogger;
class CollisionEventLogger;

class CollisionEventSource {
public:
Expand All @@ -57,15 +105,15 @@ class CollisionEventSource {
void attachListener(Listener& listener) {
ofAddListener(ballHitPaddleEvent, &listener, &Listener::onBallHitPaddle);
ofAddListener(ballHitBrickEvent, &listener, &Listener::onBallHitBrick);
ofAddListener(ballHitWallEvent, &listener, &Listener::onBallHitWall);
ofAddListener(ballHitBallEvent, &listener, &Listener::onBallHitBall);
ofAddListener(ballHitWallEvent, &listener, &Listener::onBallHitWall);
}
template<typename Listener>
void removeListener(Listener& listener) {
void detachListener(Listener& listener) {
ofRemoveListener(ballHitPaddleEvent, &listener, &Listener::onBallHitPaddle);
ofRemoveListener(ballHitBrickEvent, &listener, &Listener::onBallHitBrick);
ofRemoveListener(ballHitWallEvent, &listener, &Listener::onBallHitWall);
ofRemoveListener(ballHitBallEvent, &listener, &Listener::onBallHitBall);
ofRemoveListener(ballHitWallEvent, &listener, &Listener::onBallHitWall);
}

void enableLogging(ofLogLevel level);
Expand All @@ -88,7 +136,7 @@ class CollisionEventSource {
ofNotifyEvent(ballHitBallEvent, e);
}
private:
ofPtr<CollisionLogger> _logger;
ofPtr<CollisionEventLogger> _logger;
};

class BallOwnerChangedEventArgs {
Expand All @@ -99,29 +147,67 @@ class BallOwnerChangedEventArgs {
: _ball(ball), _player(player), _previousPlayer(previousPlayer) {}

Ball* ball() { return _ball; }
const Ball* ball() const { return _ball; }

Player* player() { return _player; }
const Player* player() const { return _player; }

Player* previousPlayer() { return _previousPlayer; }
const Player* previousPlayer() const { return _previousPlayer; }

void output(std::ostream& os) const {
os << "(";
outputField(os, ball());
os << " ";
outputField(os, player());
os << " ";
outputField(os, "previousPlayer", previousPlayer());
os << ")";
}
private:
Ball* _ball;
Player* _player;
Player* _previousPlayer;
};

std::ostream& operator<<(std::ostream& os, const BallOwnerChangedEventArgs& e) {
e.output(os);
return os;
}

class BrickDestroyedEventArgs {
public:
BrickDestroyedEventArgs(Brick* brick, Ball* ball)
: _brick(brick), _ball(ball) { }

Brick* brick() { return _brick; }
const Brick* brick() const { return _brick; }
Ball* ball() { return _ball; }
const Ball* ball() const { return _ball; }

void output(std::ostream& os) const {
os << "(";
outputField(os, brick());
os << " ";
outputField(os, ball());
os << ")";
}
private:
Brick* _brick;
Ball* _ball;
};

std::ostream& operator<<(std::ostream& os, const BrickDestroyedEventArgs& e) {
e.output(os);
return os;
}

typedef ObjectEventArgs<Player> PlayerEventArgs;
typedef ObjectEventArgs<Ball> BallEventArgs;

class RoundStateEventLogger;


class RoundStateEventSource {
public:
ofEvent<BallOwnerChangedEventArgs> ballOwnerChangedEvent;
Expand All @@ -131,8 +217,34 @@ class RoundStateEventSource {
ofEvent<BallEventArgs> ballRespawnedEvent;
ofEvent<PlayerEventArgs> playerLostEvent;
ofEvent<PlayerEventArgs> playerLivesChangedEvent;
ofEvent<ofEventArgs> roundEndedEvent;
ofEvent<EmptyEventArgs> roundEndedEvent;

void enableLogging(ofLogLevel level);
void disableLogging();

template<typename Listener>
void attachListener(Listener& listener) {
ofAddListener(ballOwnerChangedEvent, &listener, &Listener::onBallOwnerChanged);
ofAddListener(brickDestroyedEvent, &listener, &Listener::onBrickDestroyed);
ofAddListener(playerScoreChangedEvent, &listener, &Listener::onPlayerScoreChanged);
ofAddListener(ballDestroyedEvent, &listener, &Listener::onBallDestroyed);
ofAddListener(ballRespawnedEvent, &listener, &Listener::onBallRespawned);
ofAddListener(playerLostEvent, &listener, &Listener::onPlayerLost);
ofAddListener(playerLivesChangedEvent, &listener, &Listener::onPlayerLivesChanged);
ofAddListener(roundEndedEvent, &listener, &Listener::onRoundEnded);
}

template<typename Listener>
void detachListener(Listener& listener) {
ofRemoveListener(ballOwnerChangedEvent, &listener, &Listener::onBallOwnerChanged);
ofRemoveListener(brickDestroyedEvent, &listener, &Listener::onBrickDestroyed);
ofRemoveListener(playerScoreChangedEvent, &listener, &Listener::onPlayerScoreChanged);
ofRemoveListener(ballDestroyedEvent, &listener, &Listener::onBallDestroyed);
ofRemoveListener(ballRespawnedEvent, &listener, &Listener::onBallRespawned);
ofRemoveListener(playerLostEvent, &listener, &Listener::onPlayerLost);
ofRemoveListener(playerLivesChangedEvent, &listener, &Listener::onPlayerLivesChanged);
ofRemoveListener(roundEndedEvent, &listener, &Listener::onRoundEnded);
}
protected:
void notifyBallOwnerChanged(Ball* ball, Player* player, Player* previousPlayer) {
BallOwnerChangedEventArgs e(ball, player, previousPlayer);
Expand Down Expand Up @@ -163,24 +275,44 @@ class RoundStateEventSource {
ofNotifyEvent(playerLivesChangedEvent, e);
}
void notifyRoundEnded() {
ofEventArgs e;
EmptyEventArgs e;
ofNotifyEvent(roundEndedEvent, e);
}
private:
ofPtr<RoundStateEventLogger> _logger;
};

class PlayerEventLogger;

class PlayerEventSource {
public:
ofEvent<PlayerEventArgs> playerAdded;
ofEvent<PlayerEventArgs> playerRemoved;
ofEvent<PlayerEventArgs> playerAddedEvent;
ofEvent<PlayerEventArgs> playerRemovedEvent;

template<typename Listener>
void attachListener(Listener& listener) {
ofAddListener(playerAddedEvent, &listener, &Listener::onPlayerAdded);
ofAddListener(playerRemovedEvent, &listener, &Listener::onPlayerRemoved);
}
template<typename Listener>
void detachListener(Listener& listener) {
ofRemoveListener(playerAddedEvent, &listener, &Listener::onPlayerAdded);
ofRemoveListener(playerRemovedEvent, &listener, &Listener::onPlayerRemoved);
}

void enableLogging(ofLogLevel level);
void disableLogging();
protected:
void notifyPlayerAdded(Player* player) {
PlayerEventArgs e(player);
ofNotifyEvent(playerAdded, e);
ofNotifyEvent(playerAddedEvent, e);
}
void notifyPlayerRemoved(Player* player) {
PlayerEventArgs e(player);
ofNotifyEvent(playerRemoved, e);
ofNotifyEvent(playerRemovedEvent, e);
}
private:
ofPtr<PlayerEventLogger> _logger;
};

#endif /* defined(__bleepout__GameEvents__) */
Loading

0 comments on commit e0ada1b

Please sign in to comment.