SFML community forums
Help => General => Topic started by: Nexus on June 08, 2008, 07:30:02 pm
-
Hi,
Today I updated from SFML 1.2 to the new SVN version.
I see, there are many changes. Some new features are quite nice, for example the sf::Shape class. But some I can't really understand.
For example:
sf::Sprite::GetLeft(); // old
sf::Sprite::GetPosition().x; // new
sf::View::GetWidth(); // old
sf::View::GetSize().y; // new
The fact of typing more is not even the worst. The names of the functions seem to be quite random, sometimes there is still GetWidth(), and sometimes that GetSize().x. What's the point of making the names so inconsistent? Do you just want to have an own Getter for specific properties (position, rotation, size, scale)?
And the other thing is, everything has to be an own class now. For me, there's currently too much OOP in SFML. For example, you can't just write a normal sf::String constructor. Instead, the font has to be an own class (a string doesn't seem to be sufficient) which unfortunately doesn't own any specific constructors. The sf::WindowSettings struct is another example.
Up to now, I have been really impressed by SFML, but now I am a little bit deceived. Couldn't there be a possibility to at least add the old GetX() and GetWidth() again? And why did you change "Left" to "X" and "Top" to "Y"? Before it was much clearer.
-
The names are not random nor inconsistent, they perfectly reflect what the changes made to the functions. However, if you can spot an inconsistency in the new functions, I'll be glad to see it :)
I don't think there's too much OOP. The string and font stuff was a huge inconsistency : fonts had their own internal manager, whereas all other resources don't. Now all the resources (I mean, stuff which can be loaded from a file) behave exactly the same : images, fonts and sound buffers. Replacing the internal manager with a new class also adds much more flexibility, as sf::Font can now expose more parameters and be extended in the future if necessary.
Same for sf::WindowSettings, it justs gathers all the parameters which can be useful at creation time for the OpenGL context, instead of having creation functions which have hundreds of parameters. Much more powerful and maintainable.
Up to now, I have been really impressed by SFML, but now I am a little bit deceived
You shouldn't stop on such considerations, all the modifications made in version 1.3 are really meaningful and will make SFML more powerful and flexible. I always put special efforts in keeping a consistent and flexible public interface, trust me ;)
Couldn't there be a possibility to at least add the old GetX() and GetWidth() again?
GetX() wouldn't mean anything in the new version (see below), and GetWidth() is exactly the same as GetSize().x (if you don't mind writing 1 more character ;)).
One important addition for 1.3 is 2D and 3D vectors, to be able to pack attributes with X, Y and Z coordinates in one variable. This makes the code much cleaner (1 function per attribute instead of 2 or 3). Then I can't keep the old names (width and height becomes size).
And why did you change "Left" to "X" and "Top" to "Y"? Before it was much clearer.
Because the origin of a drawable is no longer at the top-left corner, you can now put it where you want (center, right-bottom corner, ...). It would be a non-sense to keep Left and Top.
-
Ah ok, from this point of view I didn't see it ;)
I couldn't reproduce some of the changes you've made, so I had doubts. You don't have to be scared, I won't stop using SFML, it's a very good library. :) Just some little thing don't please me too much, but I think I will get used to them...
And until now, I only experienced the (for me) bad part, but I believe that new improvements like vector classes and consistent resource system will help me in future, too ;)
And why did you change "Left" to "X" and "Top" to "Y"? Before it was much clearer.
Because the origin of a drawable is no longer at the top-left corner, you can now put it where you want (center, right-bottom corner, ...). It would be a non-sense to keep Left and Top.
Okay, but... what does "origin" in this context mean then? And you said that the function GetX() wouldn't mean anything in the new version, what do you exactly mean? Just to replace it by GetPosition().x? There is also a SetX(), will it soon be useless (only because of the X/Left discussion)?
And about the sf::Font... Could you make one specific constructor taking a std::string parameter for the file name? Or did you design this class to load a font file after construction?
-
You don't have to be scared, I won't stop using SFML, it's a very good library
I don't mind if someone doesn't like SFML, my goal is not to dominate the world with it ;) It would even be better for me, as there would be a discussion about bad points in SFML and how I could improve it :)
Okay, but... what does "origin" in this context mean then?
The center of translation, rotation and scaling.
And you said that the function GetX() wouldn't mean anything in the new version
Sorry, I wrote "GetX" but I actually had "GetLeft()" in mind :oops:
So forget what I said about it, it's just the same reason as GetWidth().
And about the sf::Font... Could you make one specific constructor taking a std::string parameter for the file name? Or did you design this class to load a font file after construction?
As I don't use exceptions, there's no way to notify an error on loading failure. That's why you have to use the LoadFromFile function, which returns a boolean. And yes, this is all on purpose ;)
-
Okay, but... what does "origin" in this context mean then?
The center of translation, rotation and scaling.
So by using SetX(), SetY() or SetPosition() I place this center and by GetPosition() I get its coordinates? Sorry, I just want to feel certain ;)
And about the sf::Font... Could you make one specific constructor taking a std::string parameter for the file name? Or did you design this class to load a font file after construction?
As I don't use exceptions, there's no way to notify an error on loading failure. That's why you have to use the LoadFromFile function, which returns a boolean. And yes, this is all on purpose ;)
Okay, then it's similar to the sf::Image class. I am just not used to classes without specific ctors :D
And, another question: Where is the log file where I can see what changed in SVN since 1.2? Or is there something like a doc for the newest functions?
-
So by using SetX(), SetY() or SetPosition() I place this center and by GetPosition() I get its coordinates? Sorry, I just want to feel certain
No ;)
To change the center you have to use the new function SetCenter (coordinates must be relative to the top-left corner, which is the default center). Then, when you use SetPosition you move this center (and of course the sprite which is around it :D).
Regarding rotation and scaling, the center is the point that won't move (the sprite will rotate / stretch around it).
Where is the log file where I can see what changed in SVN since 1.2?
You have the roadmap on the website for a summary, and the SVN log for more details (see with your SVN client -- "show log" with TortoiseSVN).
Or is there something like a doc for the newest functions?
From the next release on, the tutorials for SVN versions will be available online, as well as tutorials for old versions. Maybe the doxygen documentation too.
-
Hi,
maybe you could see the done category in roadmap page. For docs, Hiura on the french forum keep an up-to-date doc, here (http://hiura.123.fr/SFML/doc/).
-
While we are discussing the new font-class, I have a question.
I have a feeling I might be using it wrong. If I want to use the same font but with different font-sizes do I need to load the font multiple times? For example:
if(!FontSmall.LoadFromFile("./gamedata/gfx/FreeSansBold.ttf", 8))
exit(EXIT_FAILURE);
if(!FontMedium.LoadFromFile("./gamedata/gfx/FreeSansBold.ttf", 10))
exit(EXIT_FAILURE);
if(!FontBig.LoadFromFile("./gamedata/gfx/FreeSansBold.ttf", 12))
exit(EXIT_FAILURE);
Because if I don't use the same char-size and string-size the text is not drawn very nice, like below (not a complete code but you get the idea):
if(!Font.LoadFromFile("./gamedata/gfx/FreeSansBold.ttf", 10))
exit(EXIT_FAILURE);
sf::String Text;
Text.SetColor(sf::Color(0, 0, 0));
Text.SetFont(Font);
Text.SetSize(8.f);
Text.SetText("Hello World");
Text.SetSize(10.f);
Text.SetText("Hello World");
Text.SetSize(12.f);
Text.SetText("Hello World");
-
I have a feeling I might be using it wrong. If I want to use the same font but with different font-sizes do I need to load the font multiple times?
Yes you have to load it multiple times. This is because internally the font is rasterized and stored as an image. A different character size will produce a new image.
Because if I don't use the same char-size and string-size the text is not drawn very nice
You'll never be able to get a perfect display of text if you scale your string or your font, and I can't help much about that. Look at modern games (eg. Half-Life 2) : they have to use specific techniques using pixel shaders to get a perfect text rendering at any scale.
However, in most cases the text will be nice enough, you don't really have to load the font so many times.
-
Using the setup above (loading multiple times) the text is drawn nicely, I just wasn't sure I was using the font-class correctly.
-
As I don't use exceptions, there's no way to notify an error on loading failure. That's why you have to use the LoadFromFile function, which returns a boolean. And yes, this is all on purpose ;)
What are your reasons for not using exceptions?
Instead of writing (just to pick up the above code):
if(!FontSmall.LoadFromFile("./gamedata/gfx/FreeSansBold.ttf", 8))
exit(EXIT_FAILURE);
if(!FontMedium.LoadFromFile("./gamedata/gfx/FreeSansBold.ttf", 10))
exit(EXIT_FAILURE);
if(!FontBig.LoadFromFile("./gamedata/gfx/FreeSansBold.ttf", 12))
exit(EXIT_FAILURE);
You could write:
try
{
FontSmall.LoadFromFile("./gamedata/gfx/FreeSansBold.ttf", 8);
FontMedium.LoadFromFile("./gamedata/gfx/FreeSansBold.ttf", 10);
FontBig.LoadFromFile("./gamedata/gfx/FreeSansBold.ttf", 12);
}
catch (LoadingExeption& Ex)
{
Ex.WriteErrorToLog(Log);
return EXIT_FAILURE;
}
This way you could also provide constructors taking the filename (or something like sf::File, ever thought about that?) as a parameter directly.
It simplifies things a lot. (I was actually going to post this in feature requests.)
-
What are your reasons for not using exceptions?
Actually there's no strong reason not to use them, it's more a design choice.
The thing with an exception is that such an error is fatal and breaks the code flow. In SFML, I always try to treat errors as not fatal; instead, when an error happens I prefer leaving the objects in a valid but incorrect state (eg. a white sprite when loading an image failed), and throw a message on the standard error output. Moreover, I think this way of handling errors is much easier for beginners ; it's also more convenient when interfacing with C and other languages.
-
What are your reasons for not using exceptions?
Actually there's no strong reason not to use them, it's more a design choice.
The thing with an exception is that such an error is fatal and breaks the code flow. In SFML, I always try to treat errors as not fatal; instead, when an error happens I prefer leaving the objects in a valid but incorrect state (eg. a white sprite when loading an image failed), and throw a message on the standard error output. Moreover, I think this way of handling errors is much easier for beginners ; it's also more convenient when interfacing with C and other languages.
Agree.
-
Thanks for your reply.
I definitely agree on the last argument, it was just that I'm a big fan of exceptions :).
IMHO exceptions do not break the code flow, they however require other programming techniques.
-
You'll never be able to get a perfect display of text if you scale your string or your font, and I can't help much about that. Look at modern games (eg. Half-Life 2) : they have to use specific techniques using pixel shaders to get a perfect text rendering at any scale.
However, in most cases the text will be nice enough, you don't really have to load the font so many times.
There is one solution however when using TrueType font because there are internally stored as Bezier curves so using a predefined step to approximate them and storing the result in a display list allows to render characters at different scales without recreating them(given a small enougth approximation step). Of course this has the disadvante of being specific to TT fonts and to require more work at the loading times but the result is more beautiful(I believe). I don't know if it's more or less efficient than using textures.
-
...and throw a message on the standard error output.
And how to read that message e.x. in a windowed application under Windows or e.x. in a "daemonised" application under Linux, both having no obvious "stdout" or "stderr"? Or how to know the reason for an error when a function hidden deep in the inner workings of SFML just saying "uops, didn't work"?
To be honest it took me some serious amount of time at my initial steps with SFML to get things done correctly when something obviously didn't work and the error message had only been dumped to stdout. To actually have access to those error messages I wrote a pretty complex logging system which "bends" stdout over to some std::stream which then puts its input in a list of strings stored in a logging system singleton which then can output its content to several defined outputs, e.x. the GUI of my application or a log file or even back to console if I have one.
In addition some errors can get pretty much "spamming" in an application "doing something wrong every frame, 250 frames a second" :lol:
Anyway. Personally I work with exceptions since I like them but if you don't use exceptions that's perfectly fine, too. But simply outputting errors to stdout is far less than optimal in my opinion, due to the types of applications named above and due to beginners not being able to recognize errors which are not slapped directly into their face (and, yes, I was a beginner with SFML, too).
-
Outputing to the standard error stream is very flexible, it let users redirect it to wherever they need very easily, just as you do. I don't see the problem with that ?
Regarding spamming messages, I try to remove them as possible. If you still get some of them let me know :)
Anyway, this is purely for information and debugging, the true error reporting is the boolean return of functions which can fail. If you want to discuss error handling then it should be about this, and not about messages ;)
-
Outputing to the standard error stream is very flexible, it let users redirect it to wherever they need very easily, just as you do. I don't see the problem with that ?
It might be "flexible" but it is not "beginner friendly"; in my humble opinion.
On the other hand I found freopen() after a short Google search...
Regarding spamming messages, I try to remove them as possible. If you still get some of them let me know :)
Will do.
Anyway, this is purely for information and debugging, the true error reporting is the boolean return of functions which can fail. If you want to discuss error handling then it should be about this, and not about messages ;)
I remember that when I started SFML (a bit before version 1.2) I had an occasion where I called a function returning void or called a constructor which called several functions internally and finally outputted some error message to stdout - and there was no way to determine whether it went right or wrong based on return values. Unfortunately I can't remember which function or constructor that was, sorry.
At that time I didn't want to start a discussion about error handling since I was pretty new to SFML and feared I could not have the "big picture" yet.
Meanwhile I can't start that discussion, too, since my spare time is limited and when I code I do that mostly on the server part of my application, not the client part which uses SFML - and so I'm not sure what you changed lately. I'm currently using revision 651 from 4. Mai 2008 and I don't intend to update soon because that version simply does what I want and I have made my own changes to it (due to my sub pixel accuracy problem I posted here).
P.S.: sorry for going offtopic...
-
t might be "flexible" but it is not "beginner friendly"; in my humble opinion.
On the other hand I found freopen() after a short Google search...
It's even simpler with standard C++ streams :
std::cerr.rdbuf(TargetStream.rdbuf(());
Where TargetStream is any kind of standard stream : ofstream for a file, ostringstream for a string, custom ostream for whatever, ...
I remember that when I started SFML (a bit before version 1.2) I had an occasion where I called a function returning void or called a constructor which called several functions internally and finally outputted some error message to stdout - and there was no way to determine whether it went right or wrong based on return values. Unfortunately I can't remember which function or constructor that was, sorry.
All these functions should have been fixed now ;)
-
Concerning the inconsistences, I found some points:
sf::Sprite:
- the method to get the size on the screen is GetSize().
sf::String:
- the method to get the rectangle (and the size about it) is GetRect().
- but GetSize() returns the font size.
I think this is a little bit confusing. For me, both classes are quite similar, so why once using a Rectangle and once a 2D-Vector?
And another thing is the base class sf::Drawable. I think, there is no GetSize() method because of inherited sf::Shape and sf::PostFX, right? I don't use those 2 classes often, but don't they require a size? If yes, would make polymorphism easier (for example you don't have to overload specific functions for sf::Sprite and sf::String)...
And what I is also not really consistent, is GetSize() vs. GetWidth() or GetHeight() methods. For example Sprites use GetSize().x or GetSize().y, and the "greater" classes like sf::Image or sf::RenderWindow use GetWidth() or GetHeight(). And why did you implement sf::View::GetHalfSize()? Is that for people who don't want to write sf::View::GetRect()::GetWidth()/2? :) Or because of 2D-Vector (now there's again the question why a Rectangle with 2 specific size methods).
What's the reason for these things? They might follow a simple logic, but at the moment I don't really see it ;)
-
Cleaning all this stuff is my next task, actually ;)
-
Cleaning all this stuff is my next task, actually ;)
Oh, so there wasn't any intention behind those names? :P
-
No, I even agree 100% that these functions are confusing and everything but consistent :)
In fact, when I implemented each of them (at different times) it was just a local feature of each class, I didn't have in mind to get a generic behaviour for geometry testing and collision tests. Now I realize that I need to get a little more abstraction and consistency on this side.
-
Yes, I can completely understand that. I think it's quite normal to write working code first, and care about things like name consistency later.
I just didnt know, maybe there could have been a special reason for those identifiers. :)