Pub/Sub classes that I ripped off from http://codewrangler.home.comcast.net/~codewrangler/tech_info/patterns_code.html:
Code:
#include <list>
#ifndef _OBSERVER_H
#define _OBSERVER_H
class Publisher;
class Subscriber
{
public:
virtual ~Subscriber();
virtual void update(const Publisher& publisher);
protected:
Subscriber();
};
Subscriber::Subscriber(){};
Subscriber::~Subscriber(){};
void Subscriber::update(const Publisher& publisher){};
class Publisher
{
public:
virtual ~Publisher();
virtual void attach(Subscriber*);
virtual void detach(Subscriber*);
virtual bool notify(); // bool return for a failure condition
protected:
Publisher(); // protected default ctor
private:
typedef std::list<Subscriber*> ObsList;
typedef ObsList::iterator ObsListIter;
ObsList mSubscribers;
};
Publisher::Publisher(){};
Publisher::~Publisher(){};
void Publisher::attach (Subscriber* obs) {
mSubscribers.push_back(obs);
}
void Publisher::detach (Subscriber* obs) {
mSubscribers.remove(obs);
}
bool Publisher::notify () {
ObsList detachList;
for (ObsListIter i (mSubscribers.begin()); i != mSubscribers.end(); ++i) {
(*i)->update(*this);
}
for (ObsListIter j (detachList.begin()); j != detachList.end(); ++j) {
detach(*j);
}
return true; // always return true for now
}
#endif /* _OBSERVER_H */
#ifndef _OBSERVER_H
#define _OBSERVER_H
class Publisher;
class Subscriber
{
public:
virtual ~Subscriber();
virtual void update(const Publisher& publisher);
protected:
Subscriber();
};
Subscriber::Subscriber(){};
Subscriber::~Subscriber(){};
void Subscriber::update(const Publisher& publisher){};
class Publisher
{
public:
virtual ~Publisher();
virtual void attach(Subscriber*);
virtual void detach(Subscriber*);
virtual bool notify(); // bool return for a failure condition
protected:
Publisher(); // protected default ctor
private:
typedef std::list<Subscriber*> ObsList;
typedef ObsList::iterator ObsListIter;
ObsList mSubscribers;
};
Publisher::Publisher(){};
Publisher::~Publisher(){};
void Publisher::attach (Subscriber* obs) {
mSubscribers.push_back(obs);
}
void Publisher::detach (Subscriber* obs) {
mSubscribers.remove(obs);
}
bool Publisher::notify () {
ObsList detachList;
for (ObsListIter i (mSubscribers.begin()); i != mSubscribers.end(); ++i) {
(*i)->update(*this);
}
for (ObsListIter j (detachList.begin()); j != detachList.end(); ++j) {
detach(*j);
}
return true; // always return true for now
}
#endif /* _OBSERVER_H */
The Input class:
Code:
#include "SDL/SDL.h"
#include "Observer.h"
#ifndef _INPUT_H
#define _INPUT_H
class Input : public Publisher
{
private:
Uint8 *keystates;
SDL_Event event[100];
public:
void processEvent(SDL_Event event);
bool getKeystate(SDLKey keystate);
SDL_Event getLatestEvents();
void addToLatestEvents(SDL_Event);
Input();
};
Input::Input(){};
void Input::processEvent(SDL_Event lastEvent)
{
keystates = SDL_GetKeyState(NULL);
this->addToLatestEvents(lastEvent);
notify();
}
bool Input::getKeystate(SDLKey keystate)
{
return keystates[keystate];
}
SDL_Event Input::getLatestEvents()
{
return event[0];
}
void Input::addToLatestEvents(SDL_Event latestEvent)
{
for(int i = 1; i < 100; i++){
event[i] = event[i-1];
}
event[0] = latestEvent;
}
#endif /* _INPUT_H */
#include "Observer.h"
#ifndef _INPUT_H
#define _INPUT_H
class Input : public Publisher
{
private:
Uint8 *keystates;
SDL_Event event[100];
public:
void processEvent(SDL_Event event);
bool getKeystate(SDLKey keystate);
SDL_Event getLatestEvents();
void addToLatestEvents(SDL_Event);
Input();
};
Input::Input(){};
void Input::processEvent(SDL_Event lastEvent)
{
keystates = SDL_GetKeyState(NULL);
this->addToLatestEvents(lastEvent);
notify();
}
bool Input::getKeystate(SDLKey keystate)
{
return keystates[keystate];
}
SDL_Event Input::getLatestEvents()
{
return event[0];
}
void Input::addToLatestEvents(SDL_Event latestEvent)
{
for(int i = 1; i < 100; i++){
event[i] = event[i-1];
}
event[0] = latestEvent;
}
#endif /* _INPUT_H */
The unfinished Character class:
Code:
using namespace std;
#include <string>
#include <vector>
#include <iostream>
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "constants.h"
#include "Input.h"
#include "Observer.h"
#ifndef _CHARACTER_H
#define _CHARACTER_H
class Character : public Subscriber
{
private:
int offSet;
int xVelocity;
int yVelocity;
int frame;
int status;
int width;
int height;
int clips;
vector<SDL_Rect*> walk_left;
vector<SDL_Rect*> walk_right;
SDL_Surface* character;
void moveLeft();
void moveRight();
void moveDown();
void moveUp();
void halt();
Input& mInput;
public:
explicit Character();
virtual ~Character();
Character(Input&,string,int,int,int);
void handle_events();
void show();
virtual void update(const Publisher&);
};
Character::Character(Input& inputAddress, string filename, int w, int h, int c) : mInput(inputAddress)
{
//Attach Character as Subscriber of Input Subject
mInput.attach(this);
offSet = 0;
xVelocity = 0;
yVelocity = 0;
frame = 0;
status = CHARACTER_RIGHT;
width = w;
height = h;
clips = c;
character = load_image( filename );
if( character == NULL )
{
cout << "error - couldn't load image for character";
}
for(int i = 0; i < clips; i++){
SDL_Rect* toAdd = new SDL_Rect;
toAdd->x = 0;
toAdd->y = i * height;
toAdd->w = width;
toAdd->h = height;
walk_left.push_back(toAdd);
SDL_Rect* toAdd2 = new SDL_Rect;
toAdd2->x = width;
toAdd2->y = i * height;
toAdd2->w = width;
toAdd2->h = height;
walk_right.push_back(toAdd2);
}
}
//Update Character's Action from Input
void Character::update(const Publisher& publisher)
{
if (&publisher == &mInput) {
if(mInput.getKeystate(SDLK_RIGHT)){
this->moveRight();
}
if(mInput.getKeystate(SDLK_LEFT)){
this->moveLeft();
}
if(mInput.getKeystate(SDLK_DOWN)){
this->moveDown();
}
if(mInput.getKeystate(SDLK_UP)){
this->moveUp();
}
if(!mInput.getKeystate(SDLK_RIGHT) && !mInput.getKeystate(SDLK_LEFT)){
this->halt();
}
}
}
void Character::moveLeft()
{
xVelocity = -(width / 4);
}
void Character::moveRight()
{
xVelocity = width / 4;
}
void Character::moveDown()
{
}
void Character::moveUp()
{
}
void Character::halt()
{
xVelocity = 0;
}
void Character::show()
{
//If Character is moving left
if( xVelocity < 0 )
{
//Set the animation to left
status = CHARACTER_LEFT;
//Move to the next frame in the animation
frame++;
}
//If Character is moving right
else if( xVelocity > 0 )
{
//Set the animation to right
status = CHARACTER_RIGHT;
//Move to the next frame in the animation
frame++;
}
//If Character standing
else
{
//Restart the animation
frame = 0;
}
//Loop the animation
if( frame >= clips )
{
frame = 0;
}
//Show the stick figure
if( status == CHARACTER_RIGHT )
{
apply_surface( offSet, SCREEN_HEIGHT - height, character, screen, walk_right[ frame ] );
}
else if( status == CHARACTER_LEFT )
{
apply_surface( offSet, SCREEN_HEIGHT - height, character, screen, walk_left[ frame ] );
}
}
Character::~Character()
{
mInput.detach(this);
SDL_FreeSurface( character );
}
#endif /* _CHARACTER_H */
#include <string>
#include <vector>
#include <iostream>
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "constants.h"
#include "Input.h"
#include "Observer.h"
#ifndef _CHARACTER_H
#define _CHARACTER_H
class Character : public Subscriber
{
private:
int offSet;
int xVelocity;
int yVelocity;
int frame;
int status;
int width;
int height;
int clips;
vector<SDL_Rect*> walk_left;
vector<SDL_Rect*> walk_right;
SDL_Surface* character;
void moveLeft();
void moveRight();
void moveDown();
void moveUp();
void halt();
Input& mInput;
public:
explicit Character();
virtual ~Character();
Character(Input&,string,int,int,int);
void handle_events();
void show();
virtual void update(const Publisher&);
};
Character::Character(Input& inputAddress, string filename, int w, int h, int c) : mInput(inputAddress)
{
//Attach Character as Subscriber of Input Subject
mInput.attach(this);
offSet = 0;
xVelocity = 0;
yVelocity = 0;
frame = 0;
status = CHARACTER_RIGHT;
width = w;
height = h;
clips = c;
character = load_image( filename );
if( character == NULL )
{
cout << "error - couldn't load image for character";
}
for(int i = 0; i < clips; i++){
SDL_Rect* toAdd = new SDL_Rect;
toAdd->x = 0;
toAdd->y = i * height;
toAdd->w = width;
toAdd->h = height;
walk_left.push_back(toAdd);
SDL_Rect* toAdd2 = new SDL_Rect;
toAdd2->x = width;
toAdd2->y = i * height;
toAdd2->w = width;
toAdd2->h = height;
walk_right.push_back(toAdd2);
}
}
//Update Character's Action from Input
void Character::update(const Publisher& publisher)
{
if (&publisher == &mInput) {
if(mInput.getKeystate(SDLK_RIGHT)){
this->moveRight();
}
if(mInput.getKeystate(SDLK_LEFT)){
this->moveLeft();
}
if(mInput.getKeystate(SDLK_DOWN)){
this->moveDown();
}
if(mInput.getKeystate(SDLK_UP)){
this->moveUp();
}
if(!mInput.getKeystate(SDLK_RIGHT) && !mInput.getKeystate(SDLK_LEFT)){
this->halt();
}
}
}
void Character::moveLeft()
{
xVelocity = -(width / 4);
}
void Character::moveRight()
{
xVelocity = width / 4;
}
void Character::moveDown()
{
}
void Character::moveUp()
{
}
void Character::halt()
{
xVelocity = 0;
}
void Character::show()
{
//If Character is moving left
if( xVelocity < 0 )
{
//Set the animation to left
status = CHARACTER_LEFT;
//Move to the next frame in the animation
frame++;
}
//If Character is moving right
else if( xVelocity > 0 )
{
//Set the animation to right
status = CHARACTER_RIGHT;
//Move to the next frame in the animation
frame++;
}
//If Character standing
else
{
//Restart the animation
frame = 0;
}
//Loop the animation
if( frame >= clips )
{
frame = 0;
}
//Show the stick figure
if( status == CHARACTER_RIGHT )
{
apply_surface( offSet, SCREEN_HEIGHT - height, character, screen, walk_right[ frame ] );
}
else if( status == CHARACTER_LEFT )
{
apply_surface( offSet, SCREEN_HEIGHT - height, character, screen, walk_left[ frame ] );
}
}
Character::~Character()
{
mInput.detach(this);
SDL_FreeSurface( character );
}
#endif /* _CHARACTER_H */
Using this setup any class can inherit from Subscriber and have access to the current keystate array and latest 100 events. Don't know if I'll need that, though...
Thanks, Gold Cray.