Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1075975 Posts in 44155 Topics- by 36120 Members - Latest Member: crochi

December 29, 2014, 07:58:23 PM
  Show Posts
Pages: [1]
1  Developer / Technical / Re: SDL Advice on: March 07, 2010, 08:55:17 PM
So what I ended up doing using an Observer pattern. Not sure if this is the best way to go about it but it seems to be working. The Input class inherits from the Publisher class and anything that needs to listen for SDL_Events inherits from the Subscriber class.

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 */

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 */

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 */

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...
2  Developer / Technical / Re: SDL Advice on: March 04, 2010, 09:19:32 AM
That'll do Smiley Thanks, Gold Cray.
3  Developer / Technical / SDL Advice on: March 03, 2010, 06:25:56 PM
Hi all. I'm pretty new here, and brand new with SDL. I've been doing the Lazy Foo tuts and they're pretty great, but I'm looking for advice about how to best separate my Event/Input code from the rest of my program. All of the examples on Lazy Foo and elsewhere use an event loop in main to capture key presses, like this:
Code:
while( SDL_PollEvent( &event ) ){
        switch( event.type ){
            /* Look for a keypress */
            case SDL_KEYDOWN:
                /* Check the SDLKey values and move change the coords */
                switch( event.key.keysym.sym ){
                    case SDLK_LEFT:
                        //do something
                        break;
                    case SDLK_RIGHT:
                        //do something
                        break;
                    case SDLK_UP:
                        //do something
                        break;
                    case SDLK_DOWN:
                        //do something
                        break;
                    default:
                        break;
                }
            }
        }
    }

This seems messy to me. Does anyone have an example of an input/event class that would capture all these events and broadcast them so that other classes can listen for them and act appropriately? Or am I thinking about this in the wrong way...

The way I see it, my Player1 class (just an example) would be able to listen for the directional buttons, space, ctrl, etc. while a Controller class of some sort would listen for Enter (pause), etc.

Anyone else working in SDL that could shed some light on this?
4  Community / Townhall / Re: The Obligatory Introduce Yourself Thread on: March 03, 2010, 06:06:03 PM
Hello TIGSource. I'm a 28yr old web developer and long-time TIGlurker. I've been playing videogames my whole life but just recently starting learning to develop them. A couple favorite games: Angband, Quest for Glory & King's Quest series, Zelda, Shadowrun, Super Mario Kart, and recently Braid, SF4.

I'm starting out with C++ & SDL with Netbeans as an IDE. Looking forward to joining the next compo!
Pages: [1]
Theme orange-lt created by panic