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

Author Topic: Class, loading static image, multiple instances  (Read 3519 times)

0 Members and 1 Guest are viewing this topic.

Valis

  • Newbie
  • *
  • Posts: 4
    • View Profile
Class, loading static image, multiple instances
« on: October 17, 2010, 10:54:59 pm »
Here is the code I have.  The code works and displays the image from the class just fine.  I was just wondering if anyone could look it over and make sure I'm doing it properly.

Basically I want to make sure if I create 100 bullets from the Bullet class, that bullet.png is only really loaded once, and that all 100 sprites are using the same image.

Bullet.h
Code: [Select]

#ifndef BULLET_H_INCLUDED
#define BULLET_H_INCLUDED

#include <SFML/Graphics.hpp>

class Bullet
{
    private:

        static sf::Image Image;
        sf::Sprite bulletSprite;

    public:

        Bullet();
        ~Bullet();
        void loadImage();
        void draw(sf::RenderWindow &App);
};

#endif // BULLET_H_INCLUDED


Bullet.cpp
Code: [Select]

#include "bullet.h"

Bullet::Bullet()
{

}

Bullet::~Bullet()
{

}

void Bullet::loadImage()
{
    static sf::Image Image;
    if (!Image.LoadFromFile("bullet.png"))
    {
    // My Error message...
    }

    bulletSprite.SetImage(Image);

    bulletSprite.SetColor(sf::Color(0, 255, 255, 128));
    bulletSprite.SetPosition(20.f, 20.f);
    bulletSprite.SetScale(2.f, 2.f);
    bulletSprite.SetCenter(0, 0);
}

void Bullet::draw(sf::RenderWindow &App)
{
    App.Draw(bulletSprite);
}



Main.cpp
Code: [Select]

#include <SFML/Graphics.hpp>
#include "bullet.h"

int main()
{
    sf::RenderWindow App(sf::VideoMode(800, 600, 32), "SFML Graphics");

    while (App.IsOpened())
    {
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            if (Event.Type == sf::Event::Closed)
                App.Close();
        }

        Bullet theBullet;
        theBullet.loadImage();

        App.Clear();
        theBullet.draw(App);
        App.Display();
    }

    return EXIT_SUCCESS;
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Class, loading static image, multiple instances
« Reply #1 on: October 17, 2010, 10:59:55 pm »
Nop, you're loading the image for every new bullet. And you're using a different sf::Image instance than the one you declare in your class.

Read the sprite tutorial again, it is well explained with source code ;)
Laurent Gomila - SFML developer

Valis

  • Newbie
  • *
  • Posts: 4
    • View Profile
Class, loading static image, multiple instances
« Reply #2 on: October 17, 2010, 11:23:51 pm »
Quote from: "Laurent"
Nop, you're loading the image for every new bullet. And you're using a different sf::Image instance than the one you declare in your class.

Read the sprite tutorial again, it is well explained with source code ;)


OK, guessing something more like this....

Though I have to add:
sf::Image Bullet::Image;
To the top of my Bullet class CPP.   What is that doing exactly?

Bullet.h
Code: [Select]

#ifndef BULLET_H_INCLUDED
#define BULLET_H_INCLUDED

#include <SFML/Graphics.hpp>

class Bullet
{
    private:

        static sf::Image Image;
        sf::Sprite bulletSprite;

    public:

        Bullet();
        ~Bullet();
        void draw(sf::RenderWindow &App);
        static bool Init(const std::string& ImageFile)
        {
            return Image.LoadFromFile(ImageFile);
        }
};

#endif // BULLET_H_INCLUDED


Bullet.cpp
Code: [Select]

#include "bullet.h"
sf::Image Bullet::Image;

Bullet::Bullet()
{
    Init("bullet.png");
    bulletSprite.SetImage(Image);
}

Bullet::~Bullet()
{

}

void Bullet::draw(sf::RenderWindow &App)
{
    App.Draw(bulletSprite);
}




Another question would be, is it a bad idea to make the RenderWindow global so I don't have to pass &App to every single bullet for example?  That's what I do in SDL, but maybe that is bad coding practice?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Class, loading static image, multiple instances
« Reply #3 on: October 17, 2010, 11:29:00 pm »
You're still doing it wrong, because you call Init every time a Bullet is created. You must call it only once.

Quote
Though I have to add:
sf::Image Bullet::Image;
To the top of my Bullet class CPP. What is that doing exactly?

It defines the variable (ie. it creates it in memory). What you write in the header only declares it (ie. it says "hey, there's such a variable defined somewhere"). C++ FAQs and tutorials can probably explain this better than me :)

Quote
Another question would be, is it a bad idea to make the RenderWindow global so I don't have to pass &App to every single bullet for example? That's what I do in SDL, but maybe that is bad coding practice?

Yes, it's a bad practice. Passing the render target to the drawing function is a much better design, why is it a problem? Usually you end up drawing all your entities with a single loop, so you there's only one line of code where you need to pass the window.
Laurent Gomila - SFML developer

Valis

  • Newbie
  • *
  • Posts: 4
    • View Profile
Class, loading static image, multiple instances
« Reply #4 on: October 17, 2010, 11:40:01 pm »
Quote from: "Laurent"
You're still doing it wrong, because you call Init every time a Bullet is created. You must call it only once.


Ok, I was wondering about that.  So I can just call it once from where I create Bullets, or I can figure out how to create a static bool and then check in the constructor if I called Init already?  Maybe you show me that?

Quote
It defines the variable (ie. it creates it in memory). What you write in the header only declares it (ie. it says "hey, there's such a variable defined somewhere"). C++ FAQs and tutorials can probably explain this better than me :)


That makes sense. I appreciate the explanation.

Quote
Yes, it's a bad practice. Passing the render target to the drawing function is a much better design, why is it a problem? Usually you end up drawing all your entities with a single loop, so you there's only one line of code where you need to pass the window.


Not a problem really, but I type a little less.  :)  Really, I just wondered if there was any speed difference.  It's just pointers being passed right, so as far a speed penalty it's probably basically nothing, right?

Valis

  • Newbie
  • *
  • Posts: 4
    • View Profile
I think this works.
« Reply #5 on: October 18, 2010, 02:14:11 am »
Hopefully this is correct.

Bullet.h
Code: [Select]

#ifndef BULLET_H_INCLUDED
#define BULLET_H_INCLUDED

#include <SFML/Graphics.hpp>

class Bullet
{
    private:
 
        static bool init_done;
        static sf::Image Image;
        sf::Sprite bulletSprite;

    public:

        Bullet();
        ~Bullet();
        void draw(sf::RenderWindow &App);
        static bool Init(const std::string& ImageFile)
        {
            init_done = true;
            return Image.LoadFromFile(ImageFile);
        }
};

#endif // BULLET_H_INCLUDED


Bullet.cpp
Code: [Select]

#include "bullet.h"
sf::Image Bullet::Image;
bool Bullet::init_done = false;

Bullet::Bullet()
{
    if(!init_done)      Init("bullet.png");
    bulletSprite.SetImage(Image);
}

Bullet::~Bullet()
{

}

void Bullet::draw(sf::RenderWindow &App)
{
    App.Draw(bulletSprite);
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Class, loading static image, multiple instances
« Reply #6 on: October 18, 2010, 08:08:52 am »
Quote
Hopefully this is correct.

Yes it is :)

Quote
Really, I just wondered if there was any speed difference. It's just pointers being passed right, so as far a speed penalty it's probably basically nothing, right?

Absolutely, don't even think about that.
Laurent Gomila - SFML developer