From e0ada1bc081bb4aed5487cb1a10696888cb5d03b Mon Sep 17 00:00:00 2001 From: t3kt Date: Mon, 8 Dec 2014 22:37:15 -0500 Subject: [PATCH] game event logging (see #18 and #12) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i spent too much time on that… --- src/Ball.h | 2 + src/Brick.h | 6 +- src/GameEvents.cpp | 72 +++++++++++++------ src/GameEvents.h | 156 ++++++++++++++++++++++++++++++++++++---- src/Paddle.h | 2 + src/Player.h | 5 +- src/RoundManager.cpp | 2 + src/SpaceController.cpp | 1 + src/Wall.h | 2 + 9 files changed, 210 insertions(+), 38 deletions(-) diff --git a/src/Ball.h b/src/Ball.h index ddea57e..290a58e 100644 --- a/src/Ball.h +++ b/src/Ball.h @@ -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; }; diff --git a/src/Brick.h b/src/Brick.h index 714720b..ac8fcc1 100644 --- a/src/Brick.h +++ b/src/Brick.h @@ -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; }; diff --git a/src/GameEvents.cpp b/src/GameEvents.cpp index 04d5c84..4e3dcb0 100644 --- a/src/GameEvents.cpp +++ b/src/GameEvents.cpp @@ -9,44 +9,70 @@ #include "GameEvents.h" #include +template +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(); } + diff --git a/src/GameEvents.h b/src/GameEvents.h index de648d9..e3b6045 100644 --- a/src/GameEvents.h +++ b/src/GameEvents.h @@ -10,13 +10,33 @@ #define __bleepout__GameEvents__ #include +#include +#include #include "GameObject.h" #include "Player.h" #include "Brick.h" #include "Paddle.h" #include "Ball.h" #include "Wall.h" -#include + +template +void outputField(std::ostream& os, const char* label, const T* obj) { + os << label << ": "; + if (obj) + os << *obj; + else + os << "(null)"; +} + +template +void outputField(std::ostream& os, const T* obj) { + outputField(os, T::typeName(), obj); +} + +class EmptyEventArgs { +public: + void output(std::ostream& os) const { } +}; template class ObjectEventArgs { @@ -24,10 +44,23 @@ class ObjectEventArgs { 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 +std::ostream& operator<<(std::ostream& os, const ObjectEventArgs& e) { + e.output(os); + return os; +} + template class BallHitObjectEventArgs : public ObjectEventArgs { public: @@ -35,16 +68,31 @@ class BallHitObjectEventArgs : public ObjectEventArgs { : _ball(ball), ObjectEventArgs(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::object()); + os << ")"; + } private: Ball* _ball; }; +template +std::ostream& operator<<(std::ostream& os, const BallHitObjectEventArgs& e) { + e.output(os); + return os; +} + typedef BallHitObjectEventArgs BallHitPaddleEventArgs; typedef BallHitObjectEventArgs BallHitBrickEventArgs; typedef BallHitObjectEventArgs BallHitWallEventArgs; typedef BallHitObjectEventArgs BallHitBallEventArgs; -class CollisionLogger; +class CollisionEventLogger; class CollisionEventSource { public: @@ -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 - 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); @@ -88,7 +136,7 @@ class CollisionEventSource { ofNotifyEvent(ballHitBallEvent, e); } private: - ofPtr _logger; + ofPtr _logger; }; class BallOwnerChangedEventArgs { @@ -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 PlayerEventArgs; typedef ObjectEventArgs BallEventArgs; +class RoundStateEventLogger; + + class RoundStateEventSource { public: ofEvent ballOwnerChangedEvent; @@ -131,8 +217,34 @@ class RoundStateEventSource { ofEvent ballRespawnedEvent; ofEvent playerLostEvent; ofEvent playerLivesChangedEvent; - ofEvent roundEndedEvent; + ofEvent roundEndedEvent; + void enableLogging(ofLogLevel level); + void disableLogging(); + + template + 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 + 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); @@ -163,24 +275,44 @@ class RoundStateEventSource { ofNotifyEvent(playerLivesChangedEvent, e); } void notifyRoundEnded() { - ofEventArgs e; + EmptyEventArgs e; ofNotifyEvent(roundEndedEvent, e); } +private: + ofPtr _logger; }; +class PlayerEventLogger; + class PlayerEventSource { public: - ofEvent playerAdded; - ofEvent playerRemoved; + ofEvent playerAddedEvent; + ofEvent playerRemovedEvent; + + template + void attachListener(Listener& listener) { + ofAddListener(playerAddedEvent, &listener, &Listener::onPlayerAdded); + ofAddListener(playerRemovedEvent, &listener, &Listener::onPlayerRemoved); + } + template + 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 _logger; }; #endif /* defined(__bleepout__GameEvents__) */ diff --git a/src/Paddle.h b/src/Paddle.h index a9dbd34..9a954f8 100644 --- a/src/Paddle.h +++ b/src/Paddle.h @@ -22,6 +22,8 @@ class Paddle : public GameObject, public ofxBox2dRect { Player* player() { return _player; } void output(std::ostream& os) const override; + + static const char* typeName() { return "paddle"; } private: Player* _player; }; diff --git a/src/Player.h b/src/Player.h index 95d9bb6..8297c18 100644 --- a/src/Player.h +++ b/src/Player.h @@ -41,9 +41,12 @@ class Player : public GameObject { setLives(_lives + amount); return _lives; } + + void output(std::ostream& os) const override; + + static const char* typeName() { return "player"; } private: - void output(std::ostream& os) const override; Paddle* _paddle; int _score; diff --git a/src/RoundManager.cpp b/src/RoundManager.cpp index 5dce969..a82c858 100644 --- a/src/RoundManager.cpp +++ b/src/RoundManager.cpp @@ -28,6 +28,8 @@ void RoundController::setup() { _spaceController->setup(); _logicController->setup(); + _logicController->enableLogging(OF_LOG_NOTICE); + _spaceController->enableLogging(OF_LOG_NOTICE); _spaceController->attachListener(*_logicController); diff --git a/src/SpaceController.cpp b/src/SpaceController.cpp index cb29ac2..96ebbd0 100644 --- a/src/SpaceController.cpp +++ b/src/SpaceController.cpp @@ -131,6 +131,7 @@ void SpaceController::ballHitObject(Ball *ball, GameObject *obj) { break; case GAME_OBJECT_WALL: notifyBallHitWall(ball, static_cast(obj)); + break; default: break; } diff --git a/src/Wall.h b/src/Wall.h index 4164152..c6f833a 100644 --- a/src/Wall.h +++ b/src/Wall.h @@ -17,6 +17,8 @@ class Wall : public GameObject, public ofxBox2dEdge { Wall(bool isExit) : GameObject(GAME_OBJECT_WALL), _isExit(isExit) {} bool isExit() const { return _isExit; } + + static const char* typeName() { return "wall"; } private: bool _isExit; };