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

Author Topic: I have to keep calling --sprite--.SetImage(--image--) everytime I want to draw.  (Read 1961 times)

0 Members and 1 Guest are viewing this topic.

Plazmotech

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Hi! I have a class, within that class contains a Sprite and an Image and a ton of other irrelevant stuff. Anyway, I have an init function. This function is called to initiate all the good stuffs including setting the image for the sprite. I also have a function that is called to draw this sprite. The function takes a pointer to the Render Window and then uses it to draw the sprite (held within the class). Although, when I draw like this, it shows as a white box. In order to draw correctly, before I draw I must set the image once again. This is very very odd as I have yet another class that doesn't do this (I only have to set the image once) and another class that does ALSO do this. I have done lots of problem testing and found out its not an obvious fault in my code (as in it is indeed being called and indeed being drawn correctly).

Anyway, please help me with this, bros.

P.S. the classes dynamically change coordinates. But the class that doesn't do the resetting thing also changes coords. So that's also odd.

P.P.S. if it helps, the classes that do this are stored within a std::vector<--class-->.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10991
    • View Profile
    • development blog
    • Email
Cool story, but code.show(); would be much better... ;D

No seriously the description isn't bad, but it doesn't really help that much. If you want a good answer you need to provide a minimal and complete example that reproduces the problem.

I can now only give you some points:
.SetImage
I strongly advice you against the use of SFML 1.6, it's around 2.5 years old, thus outdated, has a lot of bugs and misses quite a few nice features.

I have a class, within that class contains a Sprite and an Image
Usually it's not such a good idea to pair Sprites and Images, because Images are heavy resource objects that shouldn't be copied around but could also get used multiple times.

Anyway, I have an init function. This function is called to initiate all the good stuffs including setting the image for the sprite.
Classes have constructors for a reason. The job of a constructor is to fully initialize the object and it's member variables, having a (public) init function often shows already a bad design.

The function takes a pointer to the Render Window and then uses it to draw the sprite (held within the class).
The overall design is not exactly clear here, but I'd say a pointer is unnecessary and a reference would do the trick too.

Although, when I draw like this, it shows as a white box. In order to draw correctly, before I draw I must set the image once again.
This sounds like the Image gets moved in memory between setting the Image to the Sprite and drawing the Sprite, thus the reference the Sprite holds is invalid. But without code it's impossible to tell.

I have done lots of problem testing and found out its not an obvious fault in my code (as in it is indeed being called and indeed being drawn correctly).
Well C++ is quite complex and one has to learn a lot, even after years of programming with it. But I guess the problem here, is just a not so nice code design plus a small lack of knowledge in C++ basics.

P.P.S. if it helps, the classes that do this are stored within a std::vector<--class-->.
Go on... (= show code). :D
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Plazmotech

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Cool story, but code.show(); would be much better... ;D

No seriously the description isn't bad, but it doesn't really help that much. If you want a good answer you need to provide a minimal and complete example that reproduces the problem.

I can now only give you some points:
.SetImage
I strongly advice you against the use of SFML 1.6, it's around 2.5 years old, thus outdated, has a lot of bugs and misses quite a few nice features.

I have a class, within that class contains a Sprite and an Image
Usually it's not such a good idea to pair Sprites and Images, because Images are heavy resource objects that shouldn't be copied around but could also get used multiple times.

Anyway, I have an init function. This function is called to initiate all the good stuffs including setting the image for the sprite.
Classes have constructors for a reason. The job of a constructor is to fully initialize the object and it's member variables, having a (public) init function often shows already a bad design.

The function takes a pointer to the Render Window and then uses it to draw the sprite (held within the class).
The overall design is not exactly clear here, but I'd say a pointer is unnecessary and a reference would do the trick too.

Although, when I draw like this, it shows as a white box. In order to draw correctly, before I draw I must set the image once again.
This sounds like the Image gets moved in memory between setting the Image to the Sprite and drawing the Sprite, thus the reference the Sprite holds is invalid. But without code it's impossible to tell.

I have done lots of problem testing and found out its not an obvious fault in my code (as in it is indeed being called and indeed being drawn correctly).
Well C++ is quite complex and one has to learn a lot, even after years of programming with it. But I guess the problem here, is just a not so nice code design plus a small lack of knowledge in C++ basics.

P.P.S. if it helps, the classes that do this are stored within a std::vector<--class-->.
Go on... (= show code). :D

1) That's interesting. When I went on SFML I clicked download current version. Does that happen to be 1.6? I shall update!

2) So shall I create an imageHolder (or something) class (or struct, which would be better?) that contains instances of all images?

3) Yes, but the init function takes arguments. I don't think constructors can take arguments. Is it a better idea to just use a ton of getter and setter functions?

4) Elaborate?

5) Ok, I shall provide code. I was avoiding doing that because i'd have to strip down a ton of unrelated stuff from the main.cpp and the enemy.h and enemy.cpp and stage.h and stage.cpp, which would take some time since they're all huge, and I wanted to avoid taking this much time if by any chance it wasn't necessary.

6) I meant, I'm logging when things happen, to make sure they happen, and it is indeed happening, therefore the function of drawing and setting image is being called at the very least. Also, forgive me, I'm a nooblet at C++, but I have quite a bit of Python experience which is much easier :P

7) Code below

http://pastebin.com/712QvpdA

If you need to see any other file please specify. Files are: enemy.h, enemy.cpp, bullethandler.h, bullethandler.cpp, bullet.h, bullet.cpp, stagestats.h, stagestats.cpp, stage.h, stage.cpp, player.h, player.cpp, main.cpp, inputhandler.h, inputhandler.cpp

If you need to know about the design please ask. I would greatly appreciate if you give tips on how I could improve this, and the design of the whole thing. Thanks!

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10991
    • View Profile
    • development blog
    • Email
1) That's interesting. When I went on SFML I clicked download current version. Does that happen to be 1.6? I shall update!
Yeah, it's unfortunately a miss communication (see here).

2) So shall I create an imageHolder (or something) class (or struct, which would be better?) that contains instances of all images?
Well it really depends on your project. In small projects where I didn't really needed to share the textures between states, I simply declared the textures as member variables of the state and used it directly. But if the project grows a bit then you might want to implement a resource manager. There are examples on the GitHub wiki or you can take a look at what Thor provides.

3) Yes, but the init function takes arguments. I don't think constructors can take arguments. Is it a better idea to just use a ton of getter and setter functions?
Ehrm, maybe you should go back again to a C++ book or similar. Of course constructor can take arguments! You can even overload them, etc... ::)

4) Elaborate?
This is better...
void foo(sf::RenderWindow& window)
{
    // ...
}
... than this ....
void foo(sf::RenderWindow* window)
{
    // ...
}

5) Ok, I shall provide code. I was avoiding doing that because i'd have to strip down a ton of unrelated stuff from the main.cpp and the enemy.h and enemy.cpp and stage.h and stage.cpp, which would take some time since they're all huge, and I wanted to avoid taking this much time if by any chance it wasn't necessary.
Everything has its cost... ;)
Also if they are that huge, then you should think about splitting them up/getting a better code design.

6) Also, forgive me, I'm a nooblet at C++, but I have quite a bit of Python experience which is much easier :P
Sure things, but also keep in mind that C++ can't  be learned by the trial-and-error principle, it's just too complex to go that approach. IMHO one just has to read a good book about C++ to really understand what one is doing... ;)

7) Code below

http://pastebin.com/712QvpdA
(Keep in mind that this is not really called 'minimal' code... ;) )

As I said, if the memory location of the sf::Image changes the references the sprites hold get invalid. This happens every so often when you push_back() enemies on the vector. A vector guarantees to have the memory laid out contiguous, which means that when the vector size grows it has to relocate all elements to a new place in memory to guarantee the contiguous of the elements layout.
The solution? As I said, don't pair sprites and images/textures. It's okay to copy around sprites but it's not just okay to copy around textures.
If you ever work with a vector of textures you should probably use std::vector<std::unique_ptr<sf::Texture>> or at least pre-allocate the number of elements you want to use.

I would greatly appreciate if you give tips on how I could improve this, and the design of the whole thing.
I won't write an essay on it, since it's a huge topic and needs often some intuition that can't just be taught... The best thing you could do, is look at already existing and open source projects to see how things where handled there... ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Plazmotech

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
1) Oh. Time to update SFML!
2) Huh that's interesting. My real name is Thor :P
3) Oh of course! I had that confused with that constructers can't return anything. Über fail.
4) Oh, ok, thanks.
5) Well, they're not thaat huge. I have them pretty well split up (IMO). It's just that it would take time.
6) I've been learning it with cplusplus.com
7) Oh! Awesome! Time to make an image management class I guess :P

Thanks so much for your help!