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

Author Topic: Finding true Draw procedure/code for an OOP  (Read 4781 times)

0 Members and 1 Guest are viewing this topic.

fixus971

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
    • http://www.fixweb.it
Finding true Draw procedure/code for an OOP
« on: July 21, 2008, 12:25:07 pm »
Hi.
I have just done a nice demo with SFML. :D
Now I want to convert all in OOP using classes..

I have some problem with function Draw of my
 20 sprites of 4 types in this application.

I used example in SFML Tutorial: "class Missile"

Now I have to Draw it but Class don't know
 static sf::RenderWindow.

I try to start using a Global variable in Global.h:
static sf::RenderWindow rwin;

but go right only in main application file..
 used in class Missile for ex is compiled
 but don't make anything.

No errors reported.

If I pass rwin (sf::RenderWindow) by reference of metod
all go right and I have my sprites.

But I have many classes of sprites (7)
and so I try to find a better metod.

At last I have a class Missili
derived from Vector to store many Missile class
and I have to draw all.

:?:
Is right to use a draw metod in classes or I have other to do.
How to pass rwin (sf::RenderWindow) in many classes of sprites (/Vector)

1000thanks.
^_^=>Il calcolatore è straordinariamente veloce, accurato e stupido. Gli uomini sono incredibilmente lenti, imprecisi e creativi. L'insieme dei due costituisce una forza incalcolabile. (Albert Einstein)

fredreichbier

  • Newbie
  • *
  • Posts: 6
    • View Profile
Finding true Draw procedure/code for an OOP
« Reply #1 on: July 21, 2008, 03:53:30 pm »
Could you give us some code?

fixus971

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
    • http://www.fixweb.it
Finding true Draw procedure/code for an OOP
« Reply #2 on: July 21, 2008, 04:49:02 pm »
Sure.. but my project is more complex and use many files and classes.
I don't put in forum only because I need a example guide for OOP.


globals.h:
Code: [Select]
static sf::RenderWindow rwin;
static sf::String sfs;



Trasporter.cpp:
Code: [Select]
#include <SFML/Graphics.hpp>
#include <cmath>
#include <sstream>
#include "globals.h"
#include "impianto.h"

int main() {
    rwin.Create( sf::VideoMode( 1024, 768, 32 ), "Trasporter" ); //globalVar
    sfs.SetSize( 24.f );  //globalVar with font setup
    sfs.SetColor( sf::Color( 0, 0, 200) );

    Impianto impianto;


    sf::Image BackgroundIm, ImpiantoIm, CarroIm, PinzaIm, VascaIm, FornoIm, TelaioSpIm, TelaioUsIm, TelaioPlIm, LineaIm;

    if (
        !ImpiantoIm.LoadFromFile("datas/trasporter/Impianto.png") ||
.............................................
        return EXIT_FAILURE;
    }

    sprBackground.SetImage(BackgroundIm);
    sprImpianto.SetImage(ImpiantoIm);
............................................
    // Ciclo programma
    bool IsRunning = true;
    while (IsRunning) { // Programma simulazione in funzione
        sf::Event Event;
        while (rwin.GetEvent(Event)) { // Controllo eventi finestra applicazione compresi tasti premuti
            if (Event.Type == sf::Event::Closed) IsRunning = false;
            if (Event.Type == sf::Event::KeyPressed) {
                switch (Event.Key.Code) {
                case sf::Key::Escape:
                    IsRunning = false;
                    break;
                default:
                    break;
                }
            }
        }

            dtFrame = rwin.GetFrameTime() * dtFrameVel/100.f;
            Stazioni_Gest();

        // Draw all ///////////////

        rwin.Draw(sprImpianto);  // OK

        impianto.draw(rwin);       // Fail: no error / not drawed

        rwin.Display(); // Display things on screen
    } // while IsRunning

    return EXIT_SUCCESS;
}




impianto.h
Code: [Select]
#ifndef IMPIANTO_H_INCLUDED
#define IMPIANTO_H_INCLUDED
#include <SFML/Graphics.hpp>
#include "stazione.h"
#include "carro.h"
using namespace std;

class Impianto {
public:
    Impianto();
    ~Impianto();
    float get_nstazioni() { return stazioni.size(); }
    void set_aut(int m);
    void set_ciclo(int m);
    void gest(float dt);

    void draw(sf::RenderWindow &);  // <<<<<<<

    void drawInfo();
    bool    aut;        // man / aut(Semia|Ciclo)
    bool    ciclo;      // Ciclo Automatico in esecuzione
    bool    VaCoppie;   // Vasche operanti a coppie
    int     dxEngage;   // dx Aggancio: se 0 usa metodo a Pinzatura Verticale
    int     iProgr;     // Programma Ciclo Aut
    int     tSgocc;     // Tempo di sgocciolamento sulle vasche
    Telai   telai;
    Stazioni stazioni;
    Carro   carroSx, carroDx;
};



impianto.cpp:
Code: [Select]
#include <cmath>
#include <string>
#include <SFML/Graphics.hpp>
#include "impianto.h"
#include "globals.h"
#include "futy.h"
using namespace std;

Impianto::Impianto() //Impianto crea lui Telai e Stazioni e Carri
:telai()
,stazioni()
,carroSx( telai, stazioni )
,carroDx( telai, stazioni ) {
    aut      = true;
    ciclo    = true;
    iProgr   = 1;
    VaCoppie = false;
    tSgocc   = 2;
    dxEngage = 6; // dxAggancio Telaio
    int i;
    std::stringstream ss, ssLog, ssKey;
    // Define the stations
    float dxst = stazioni.dxStazioni;
    int ist = 0;
    //Stazione& st = stazioni[0];
    //st = stazioni[ist];
    Stazione st;
    st.set_tipo( Stazione::CARICO );
    st.set_tOn( 1 );
    st.set_termoSet( 0 );
    for ( i=0; i<stazioni.nCarScar; i++ ) { // Carico
        st.set_name( "St" + tostring(i) + "\n" + "Ca" );
        st.set_pos( rifx + ((i-7)*dxst)-27 );
        stazioni.push_back(st);
    }
    st.set_tipo( Stazione::VASCA );
    st.set_tOn( 60 );
    for ( i=0; i<stazioni.nVasche; i++ ) { // Vasche
        st.set_name( "St" + tostring(i) + "\n" + "V" + tostring(i+1) );
        st.set_pos( rifx + ((i-7)*dxst)-27 );
        st.set_termoSet( 90-i*6 );
        stazioni.push_back(st);
    }
    st.set_tipo( Stazione::FORNO );
    st.set_tOn( 120 );
    st.set_termoSet( 120 );
    for ( i=0; i<stazioni.nCarScar; i++ ) { // Forno
        st.set_name( "St" + tostring(i) + "\n" + "F" + tostring(i+1) );
        st.set_pos( rifx + ((i-7)*dxst)-27 );
        stazioni.push_back(st);
    }
    st.set_tipo( Stazione::SCARICO );
    st.set_tOn( 1 );
    st.set_termoSet( 0 );
    for ( i=0; i<stazioni.nCarScar; i++ ) { // Scarico
        st.set_name( "St" + tostring(i) + "\n" + "Sc" );
        st.set_pos( rifx + ((i-7)*dxst)-27 );
        stazioni.push_back(st);
    }
// Define Carri properties
//    for (i=0;i<mCarri;i++) Carro_Init( carro[i], i );
    return;
};
Impianto::~Impianto() {
    return;
};

void Impianto::set_aut(int a) {
    aut = a;
};

void Impianto::set_ciclo(int c) {
    ciclo = c;
};

//--

void Impianto::gest(float dt) {
};


void Impianto::draw(sf::RenderWindow & prwin) { //<<<<<<<<<<<<<<
sf::Color cBackground( 0,255,0 );
rwin.SetBackgroundColor( cBackground ); // GlobalVar dont run
prwin.SetBackgroundColor( cBackground ); // Par.Var run ok
sfs.SetX(110);
sfs.SetY(110);
sfs.SetText("******************************************\n");
rwin.Draw(sfs);   // GlobalVar dont run
prwin.Draw(sfs); // Par.Var run Ok
};




I can pass "sf::RenderWindow & prwin"
to all objects but I find a clear OOP code.

I need other different classes that need to Draw..
..some of this is collected in Vector class..
I prefer to not pass "sf::RenderWindow & prwin"
through many and many classes if possible:
Vector class is only a collector class.

I simply ask for OOP tutorial similar to "Missile" class.
I need to mantain separate class functions and graph?

If you want to see my project, objects (classes now)
 I have the complete exe of version 1 without any class. (1MB)

Thanks in advance for any help.
^_^=>Il calcolatore è straordinariamente veloce, accurato e stupido. Gli uomini sono incredibilmente lenti, imprecisi e creativi. L'insieme dei due costituisce una forza incalcolabile. (Albert Einstein)

Wizzard

  • Full Member
  • ***
  • Posts: 213
    • View Profile
Finding true Draw procedure/code for an OOP
« Reply #3 on: July 22, 2008, 01:29:25 am »
I am not 100% sure if this is what you wanted, but here is a simplified version of how I create objects in my demos:

Code: [Select]
#include <SFML/Graphics.hpp>


class Missile : public sf::Sprite
{
public :

    static bool Init(const std::string& image)
    {
        return m_Image.LoadFromFile(image);
    }

    Missile() :
            Sprite(m_Image)
    {

    }

private :

    static sf::Image m_Image;
};

sf::Image Missile::m_Image;


int main()
{
    if (!Missile::Init("images/missile.png"))
        return 1;

    sf::Event event;
    sf::RenderWindow window(sf::VideoMode(640, 480), "Tile",
                            sf::Style::Close,
                            sf::WindowSettings(0, 0));

    Missile missiles[3];
    missiles[1].SetPosition(50, 50);
    missiles[2].SetPosition(40, 10);

    for (;;)
    {
        while (window.GetEvent(event))
            if (event.Type == sf::Event::Closed) return 0;

        window.Draw(missiles[0]);
        window.Draw(missiles[1]);
        window.Draw(missiles[2]);
        window.Display();
    }
}


Of course, you could use a vector instead of an array to easily add and remove missiles to the list of things that need to be drawn.

I hope this is what you needed!

fixus971

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
    • http://www.fixweb.it
Finding true Draw procedure/code for an OOP
« Reply #4 on: July 22, 2008, 01:35:35 pm »
Thanks,

but I have a more complex scenario.
I have 4 "impianto class(sprite)"..
..each class have:
16 "stazione class(sprite)"
x "telaio class(sprite)"
2 "carro class(sprite)"

I try to make a good OOP application.


I ask if, for OOP, is better to

a) draw all from main application finding and drawing all that have to be draw

b) simply call from main: impianto1.draw that go to call in transparent mode:
  stazioni.draw -> stazione1.draw.. stazione2.draw.. stazione3.draw..
  telai.draw      -> telaio1.draw.. telaio2.draw.. telaio3.draw..
  carro1.draw
  carro2.draw

Is more right to have objects capable of draw
or is better a separated object that scan all, get sprite data and draw?

Other option is to create a list of pointers to sprites of objects and pass that to main.draw

I find any strategic idea for that.. for my application and in general OOP.

Thanks
^_^=>Il calcolatore è straordinariamente veloce, accurato e stupido. Gli uomini sono incredibilmente lenti, imprecisi e creativi. L'insieme dei due costituisce una forza incalcolabile. (Albert Einstein)

Wizzard

  • Full Member
  • ***
  • Posts: 213
    • View Profile
Finding true Draw procedure/code for an OOP
« Reply #5 on: July 22, 2008, 11:56:29 pm »
Quote from: "fixus971"
is better a separated object that scan all, get sprite data and draw?

I've seen a lot of applications that do this and it would be acceptable by most standards, but I for one do not like the way it feels. Objects are meant for things that are declared multiple times.

Quote from: "fixus971"
Other option is to create a list of pointers to sprites of objects and pass that to main.draw

This is what I do in my applications. However, I do it so that my list of pointers are global. That way I can add sprites to the list from anywhere in my application. I also made inline helper functions called Create() and Remove() to make my hands happy.

fixus971

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
    • http://www.fixweb.it
Finding true Draw procedure/code for an OOP
« Reply #6 on: July 23, 2008, 08:08:47 am »
Many thanks Wizzard.  :lol:
This is type of answer that I finding.

Now I have to Study how to implement that
because I'm not a genius of OOP:
strategy with a List of sprites is only an idea
 that I think writing previous post.

Consider that:
- I have some sprite precedence.
- I have to draw some sf:String too (as last layer).
What type of list can I use?
Is better to use 2 separate list for sprites/strings?

What happen if I remove/add a sprite..
..I have to use some type of ordered list with precedence parameter?
Or..
Is true to generate list in every cicle using .draw metod
 as posted above to get ordered list?

Is better implement List and helper Functions for that
 in other class or as pure global?

Can you give me a 2line of "sprite list" code
to see if I have to use pointers or other?

PS:
How can I menage my 10 text of
 to put all of them with same Font setup?
At the moment I use only one sf:String, setup it
 and then modify many times text,x,y and draw it.

1000 Thanks
^_^=>Il calcolatore è straordinariamente veloce, accurato e stupido. Gli uomini sono incredibilmente lenti, imprecisi e creativi. L'insieme dei due costituisce una forza incalcolabile. (Albert Einstein)

Wizzard

  • Full Member
  • ***
  • Posts: 213
    • View Profile
Finding true Draw procedure/code for an OOP
« Reply #7 on: July 23, 2008, 11:39:43 am »
The way I have it is so that my list of sprites is a std::vector<sf::Drawable*>. However, using this method would mean that all your classes that you want to be drawn would need to be derived from sf::Drawable (sf::PostFX, sf::Shape, sf::Sprite and sf::String are already derived from sf::Drawable). Consider the following code:

Code: [Select]
#include <SFML/Graphics.hpp>


class Missile : public sf::Sprite
{
public :

    static bool Init(const std::string& image)
    {
        return m_Image.LoadFromFile(image);
    }

    Missile(const sf::Vector2f& position = sf::Vector2f(0.f, 0.f),
            const sf::Vector2f& scale = sf::Vector2f(1.f, 1.f),
            const float& rotation = 0.f,
            const sf::Color& col = sf::Color::White) :
            Sprite(m_Image, position, scale, rotation, col)
    {

    }

private :

    static sf::Image m_Image;
};

sf::Image Missile::m_Image;


std::vector<sf::Drawable*> g_Drawables;

int main()
{
    freopen("console.log", "w", stderr);

    if (!Missile::Init("images/missile.png"))
        return 1;

    sf::Event event;
    sf::RenderWindow window(sf::VideoMode(640, 480), "Tile",
                            sf::Style::Close,
                            sf::WindowSettings(0, 0));

    g_Drawables.push_back(new sf::Shape(sf::Shape::Circle(window.GetWidth() / 2U,
                                        window.GetHeight() / 2U, 16.f,
                                        sf::Color::Red)));
    g_Drawables.push_back(new Missile(sf::Vector2f(window.GetWidth() / 2U - 8U,
                                      window.GetHeight() / 2U - 32U)));

    for (;;)
    {
        while (window.GetEvent(event))
            if (event.Type == sf::Event::Closed)
            {
                for (std::vector<sf::Drawable*>::iterator it = g_Drawables.begin();
                        it != g_Drawables.end(); ++it)
                    delete *it;

                return 0;
            }

        for (std::vector<sf::Drawable*>::iterator it = g_Drawables.begin();
                it != g_Drawables.end(); ++it)
            window.Draw(**it);

        window.Display();
    }
}

It's a bit complicated, but you'll find it's an easy way to deal with a constantly changing number of drawables. If you wish certain drawables to be drawn on top of others you can either make sure that the drawable you want drawn on top is put on the list before the other drawables or you can even create a whole new layer/list of drawables.


I hope this helps!



P.S.: The call to freopen is just so we can report errors, it's nothing special. :)

EDIT: I just realized I didn't show you how to remove drawables! You can figure that out for yourself I guess. I'll try and get back to you if you need anything more though.

fixus971

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
    • http://www.fixweb.it
Finding true Draw procedure/code for an OOP
« Reply #8 on: July 23, 2008, 12:51:52 pm »
1 000 000 :lol:  Thanks Wizzard for your quick and clear response.

Now I go to study and test all.
^_^=>Il calcolatore è straordinariamente veloce, accurato e stupido. Gli uomini sono incredibilmente lenti, imprecisi e creativi. L'insieme dei due costituisce una forza incalcolabile. (Albert Einstein)