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

Author Topic: BFWK Announced  (Read 2428 times)

0 Members and 1 Guest are viewing this topic.

kitteh-warrior

  • Guest
BFWK Announced
« on: July 11, 2015, 03:38:26 am »
Hello, BFWK is my rather miniscule project that I started working on a little while ago now.

TLDR; https://bitbucket.org/bucket-jesus/bfwk

Brief History
Over time, I came to realise that I am making code in little testing projects that are essentially copied and pasted from one to another. Thus, I started making this. It is modular to fit my needs as I work on completely random minor projects constantly. I came up with the name "basicFramework", and thought that it was far too long, so I shortened it to "BFWK".

Brief Overview
BFWK allows for an "easier" (opinions may vary) experience when working with a project. It encapsulates the processing of sf::Event's, sf::RenderTarget::draw()'s, and its own bfwk::BaseObject::update()'s, and pushes them to the currently active bfwk::BaseFrame. BFWK allows for the ability to let it call the update/draw cycles via another thread (default), or to use the main one.

Specific Breakdown

bfwk::Window
The Window class of this framework essentially owns the sf::RenderWindow and FrameHandler, forwards events to the FrameHandler, as well as dispatching update/draw calls to the FrameHandler (only in monothreaded mode).

The usual usage scenarios of Window is:
bfwk::Window window;
window.getRenderWindow()->create(sf::VideoMode(800, 600), "Example");
window.launch();

bfwk::FrameHandler
The FrameHandler ("Frame" in the context of this framework is meant as a verb, the objects you make and attach to it are "framed" together in the Window) controls the updating/drawing of the currently selected BaseFrame. It also forwards events to the currently selected BaseFrame and controls the refresh rate of the update/draw cycles.

Typical usage scenario's of FrameHandler are:
getFrameHandler()->setFrame<TestFrame>("Additional params");
getFrameHandler()->setRefreshTime( sf::seconds( 1.f / 60.f ) );

bfwk::BaseFrame
BaseFrame is the abstract base class that all frames must inherit from if they are to work within the FrameHandler. This class receives the forwarded update/draw/event calls from the FrameHandler.

A good example of inheriting from this and handling all of the functionality required is in the Frame class.

bfwk::Frame
The Frame class is a typical abstract implementation of the BaseFrame class. It allows for the addition and removal of multiple BaseObjects from it's internal containers, custom background colour, dispatching of events/updates/draws to the current BaseObjects, as well as allows the modularity of its own internal pure virtual draw/update/event calls (after all of the objects).

A Frame is typically inherited as follows:
class MyFrame : public bfwk::Frame {
public:
    FirstFrame( bfwk::FrameHandler* parent );
    ~FirstFrame();
private:
    void update();
    void draw();
    void initial();
    void handleEvents( sf::Event const* event );
};

The initial() function is called via the FrameHandler in the event that the Frame has been selected. Some calculations require the sf::RenderWindow to be opened, so this function was created. The sf::RenderWindow is guaranteed to be open at the beginning of this call (under typical usage).

bfwk::BaseObject
BaseObject is an abstract class that is inherited to any "object" that you wish to add the the Frame class provided by BFWK. A class made from BaseObject that is non-abstract should be a leaf object in this train of calls (Window (Event) -> FrameHandler (Event, Update, Draw) -> BaseFrame (Event, Update, Draw) -> Frame (Event, Update, Draw) -> BaseObject (Event, Update, Draw*)).
*the BaseObject will only get the draw call if it inherits from sf::Drawable.

Classes that inherit from BaseObject that also inherit from sf::Drawable will get drawn to the sf::RenderWindow via a draw call. If your object is only logical, or if for some other reason doesn't require to ever be drawn, then simply do not inherit from sf::Drawable.

An example of a possible leaf Object:
class MyObject : public bfwk::BaseObject {
public:
    MyObject( bfwk::BaseFrame* parent );
    ~MyObject();
private:
    void update();
    void handleEvents( sf::Event const* event );
    bool const getActive();
};

The getActive() function is to tell the parent Frame whether there should be events forwarded, or not.

Okay, cool... where is it?
BFWK was uploaded to Bitbucket (it was on Github, but since I mostly use Bitbucket for everything else, I pulled it over there and now I only maintain it on Bitbucket.)

To re-enforce the prerequisites that are clearly states in the README.md file:
  • SFML 2.3 (or later; may work for previous versions, but not tested)
  • SFML_ROOT environment variable pointing to the root of the SFML folder (there is an option in CMake to set this if you do not want to have an environment variable)
  • For examples, you must have the graphics, window, and system components of SFML built
  • A compiler with C++14 support (due to the use of std::make_unique<T>( args ... ))

My Uses
As I previously said, I started working on this to more easily make small projects more quickly and test things out. Though, currently I am working on a more serious project with modularity in mind, but I do not have enough information gathered to discuss much of that.

In the mean time, finding bugs and suggesting good places for optimisation will be greatly appreciated. I am relatively new to making CMake projects, but I think it should work on Windows and Linux. I am uncertain about Mac, as I have heard people say things tend to not work the best in such a case.


Example
When working with BFWK, you must design your own frame class, that is based off of the bfwk::Frame class, one possible implementation is:
class ExampleFrame final : public bfwk::Frame {
    private:
        sf::VertexArray va; //simple vertex array that gets drawn via this frame
    public:
        ExampleFrame( bfwk::FrameHandler* parent )
            : bfwk::Frame( parent ) {
            va.resize( 4 );
            va.setPrimitiveType( sf::Quads );
            va[0].color = sf::Color::Red; //change all colours to red
            va[1].color = sf::Color::Red;
            va[2].color = sf::Color::Red;
            va[3].color = sf::Color::Red;
        }

        void handleEvents( sf::Event const * event ) {
            switch( event->type ) {
                case sf::Event::Closed:
                    getRenderWindow()->close();
                    break;

                default:
                    break;
            }
        }

        void update( sf::Time const& time ) {
            sf::Vector2f boxPosition( getRenderWindow()->getView().getCenter() + getRenderWindow()->getView().getSize() / 2.f - sf::Vector2f( 50.f, 50.f ) );
            va[0].position = boxPosition - sf::Vector2f( 20, 20 );
            va[1].position = {boxPosition.x + 20, boxPosition.y - 20};
            va[2].position = boxPosition + sf::Vector2f( 20, 20 );
            va[3].position = {boxPosition.x - 20, boxPosition.y + 20};
        }

        void draw() {
            getRenderWindow()->draw( va );
        }

        void initial() {
            std::cout << "Resize the window to see the object move!" << std::endl;
        }
};

Then, of course, you must call the setFrame<T>() function of the FrameHandler for the Window, supplying your class as the template:

int main( int argc, char **argv ) {
    try {
        bfwk::Window window; //create the window
        window.getFrameHandler()->setFrame<ExampleFrame>(); //set the initial frame
        window.getRenderWindow()->create( sf::VideoMode( 800, 600 ), "bfwk Example!" ); //create the render window
        window.launch(); //then launch the window

    } catch( std::runtime_error e ) {
        std::cout << "Runtime Error! : " << e.what() << std::endl;
    }

    return 0;
}

Due to the use of exceptions (primarily for me testing the framework on different machines, whereas some don't like the use of multiple threads for drawing), it is recommended to embed at least the bfwk::Window::launch() call within a try/catch. Also, when designing your bfwk::Frame class, you must let bfwk::FrameHandler access it in some way, because it instantiates it on its own.

Edit: included a small example of bfwk::Frame usage. If you wish to see how bfwk::BaseObjects are used and get added to it, simply look at the examples directory of the Bitbucket repository.
« Last Edit: July 11, 2015, 07:36:09 pm by kitteh-warrior »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: BFWK Announced
« Reply #1 on: July 11, 2015, 07:05:55 pm »
Sounds interesting! Some parts are a bit abstract, do you have a small example to show the BFWK frames? Maybe not a whole project, rather one or a few code snippets that show them in action and give a nice feeling what they can do :)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

kitteh-warrior

  • Guest
Re: BFWK Announced
« Reply #2 on: July 11, 2015, 07:35:23 pm »
There are examples in the "examples" directory of the repository. I have updated my original post here. :)

On a side note, I was working on a bfwk::NetworkFrame class that encapsulates binary1248's SFNUL's functions, but omitted it currently due to inefficiency of it (and horrible made!), though once I remake it I will include that into the repository.