SFML Project help (or FML project... at the moment)

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
SamCam
Posts: 17
Joined: January 8th, 2020, 3:24 pm

SFML Project help (or FML project... at the moment)

Post by SamCam » June 7th, 2020, 9:46 pm

Hey guys, I'm looking for a little help with this project/demo I started building with SFML (sorry Chili engine)

The aim of this little project is to be able to type in some text to a screen from a remote network source, the text should appear 'live' so you can see the remote users train of thought, mistakes, backspaces etc.
To make the text centred and justified per line, I ended up splitting the string on the '\n' delimiter and pushing the split strings into a vector of strings. Then I push back some make_unique SFML Text objects into another and calculate the offsets and alignment of the text blocks - It's a bit clunky but displays the behaviour I like.

This was all working great when the code was in the main() method, but to help tidy up and keep the main method readable I wanted to split out the string handling into it's own class, now I'm hitting a big fatty of an exception when I get down to my Draw() call...

Any ideas in this specific problem would be appreciated, also any further ideas about development welcome!

The network code was just built simply from the SFML library, and is working pretty good, See the SFML_textsender project. But for testing I've just hard coded a string into the main() method.

https://github.com/SamuelLouisCampbell/SFMLdemo

albinopapa
Posts: 4170
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: SFML Project help (or FML project... at the moment)

Post by albinopapa » June 8th, 2020, 7:52 am

Well, I'm a bit ashamed to say I am not sure what change got it working, but here are the modified versions:

Stringhandling.h

Code: Select all

class Stringhandling
{
public:
	Stringhandling(
		std::string message_in,
		sf::RenderWindow& window,
		sf::Font const& font,
		float size );
	void Draw() const;

private:
	void makeVecStrings( const std::string& message_in );
	void makeVecText();
private:
	sf::RenderWindow& window;
	const sf::Font& font;
	const float size;
	std::string message; 
	std::vector<std::string> stringies;
	std::vector<sf::Text> vec;

};
Stringhandling.cpp

Code: Select all

#include "Stringhandling.h"



Stringhandling::Stringhandling(
	std::string message_in,
	sf::RenderWindow& window,
	sf::Font const& font,
	float size )
	:
	message( std::move( message_in ) ),
	window(window),
	size(size),
	font(font)
{
	makeVecStrings( message );
	makeVecText();
}

void Stringhandling::Draw() const 
{
	for (auto const& text : vec )
	{
		window.draw( text );
	}
}

void Stringhandling::makeVecStrings( const std::string& message )
{
	if( message.size() >= 1 )
	{
		size_t start = 0u;
		size_t stop = message.find( '\n' );
		while( stop != std::string::npos )
		{
			stringies.push_back( message.substr( start, stop ) );
			start = stop + 1;
			stop = message.find( '\n', start );
		}
		stringies.push_back( message.substr( start ) );
	}
}

void Stringhandling::makeVecText()
{
	vec.reserve( stringies.size() );
	for (int i = 0; i < stringies.size(); ++i)
	{
		auto& text = vec.emplace_back( );
		text.setFont( font );
		text.setCharacterSize(size);
		text.setFillColor(sf::Color::White);
		text.setPosition(window.getSize().x / 2, window.getSize().y / 2);
		text.setString(stringies[i]);

		//Centre current string
		if (text.getString().getSize() >= 1)
		{
			float offsetX = text.getLocalBounds().width;
			text.setPosition(
				( window.getSize().x / 2 ) - ( offsetX / 2 ),
				window.getSize().y / 2
			);
		}
	}
	float totalSize = -( size * vec.size() ) / 2.0f;
	for( auto& text : vec )
	{
		text.move( 0.f, totalSize );
		totalSize += size;
	}
}
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4170
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: SFML Project help (or FML project... at the moment)

Post by albinopapa » June 8th, 2020, 8:08 am

There are a few things here.

You store an sf::RenderWindow const&, then pass in a sf::RenderWindow& to Stringhandling::Draw. You probably either need to change the window stored to just a non-const reference, or not store the reference tot he window and just keep passing it to the Draw function.

You store an sf::Font const&, then pass in a const sf::Font which makes a copy then tries to store a constant reference to the temporary.

The functions Stringhandling::makeVecString and Stringhandling::makeVecText are private and therefore cannot be called outside the class. You are storing the vector<std::string> and std::vector<std::unique_ptr<sf::Text>> in same class, no need to pass them to private members.

I'm not sure the use of std::unique_ptr for sf::Text is necessary, so I just made the vector std::vector<sf::Text> and it seems to work.

Stringhandling::makeVecStrings takes in a const std::string&, but then you make a copy so that it can be modified. You could just pass the message string by value to get the copy or as I did, keep the const& and use the values returned by std::string::find as offsets into the next section to search.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

SamCam
Posts: 17
Joined: January 8th, 2020, 3:24 pm

Re: SFML Project help (or FML project... at the moment)

Post by SamCam » June 8th, 2020, 9:36 pm

Hey, thanks once again, I ran your changes, had a couple of issues but solved them.

I think I was probably overthinking things a bit which let to me using unique_ptr which is unnecessary as you say. From now on I'm just going to try and write classes to begin with and not end up with a load of stuff hanging out in main. That will help I think!

All working brilliantly now, time to move on to the many other things I had in mind.

albinopapa
Posts: 4170
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: SFML Project help (or FML project... at the moment)

Post by albinopapa » June 9th, 2020, 12:28 am

Awesome.

It's kind of funny. I usually had better luck starting off the same as you, then move everything to their own classes so I can see how everything is suppose to "get along".
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

SamCam
Posts: 17
Joined: January 8th, 2020, 3:24 pm

Re: SFML Project help (or FML project... at the moment)

Post by SamCam » June 9th, 2020, 11:16 pm

Haha, its a minefield there's probably no correct solution just what works well at the time.
I get excited when things are all moving forward but then it feels like a drag to have to move all of the code around and make it play together again. Probably a moderation of excitement and less wasting time is the way forward.

albinopapa
Posts: 4170
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: SFML Project help (or FML project... at the moment)

Post by albinopapa » June 10th, 2020, 3:03 am

Yeah, there is one more step in programming that I haven't yet ventured into, Test Driven Development.

In TDD, you write tests for each "feature" of your program and verify that they pass or fail as expected.

Say you have a class that takes an float.

Code: Select all

class Angle
{
public:
    Angle() = default;
    Angle( float value_ ) : value( value_ ){}
private:
    float value = 0.f;
};
Now, say you want this int to always be between -PI and +PI. In your own code, you might always remember that Angle::value should always be between -PI and +PI, but either you may forget or something like:
Angle a{ 42 }; // whoops forgot to convert degrees to radians
A b{ PI };
A c = a * b; // whoops angle is now 42 + PI

Now, you pass it to a function that requires the -PI,+PI range:

Code: Select all

void Mat3f::Rotate( A const& a ){
    const auto sine = std::sin( a.get_value() );
    const auto cosine = std::cos( a.get_value() );

    return{ cosine, -sine, 0.f, 
            sine, cosine, 0.f, 
            0.f, 0.f, 1.f };
}
So for TDD, you'd write tests that pass in various values into A::A( int ) and have a condition that is expected, including failures given that failures would probably lead to bugs.

It's tedious on the front end, but supposedly saves time on the back end where you don't have nearly as many bugs because you tested for various cases during TDD portion. This is how I understand TDD anyway.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

SamCam
Posts: 17
Joined: January 8th, 2020, 3:24 pm

Re: SFML Project help (or FML project... at the moment)

Post by SamCam » June 10th, 2020, 4:12 pm

That's cool, I've been doing a few of those little coding challenges they have on hackerrank, which seem to do just that. I can see how automated testing would be useful. As the man himself once said, if you can give the user a way to get their dick caught in a ceiling fan they'll do it.
I'm still a fair way off needing such things I guess, most of my own stupidity I could probably better handle with assertions.

I think I'm going to try and bring this project back into the DirectX chili realm for now too, I like SFML but it almost feels like cheating because it's so feature rich and when it goes awry I struggle with the debugger output as there is a lot of information in there. I know we're supposed to push ourselves as programmers but I still feel I have much more to learn and squeeze out of the chili framework.

To that end, did you ever find a good resource for understanding directwrite or a better/different library for font handling? I managed to get the MSDN example to build and run but didn't try and get much further.

Also also can you recommend any good resources for network integration? I have managed to code up and make some basic winsock examples work within the framework but always fall down with trying to make the sockets "non-blocking"

albinopapa
Posts: 4170
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: SFML Project help (or FML project... at the moment)

Post by albinopapa » June 10th, 2020, 5:47 pm

Definitely use those assertions. As stated, I haven't made it to doing TDD myself. I rely on assertions and the debugger. It's odd, I've been running across some posts around the web claiming you shouldn't rely on the debugger and instead do your own testing ( TDD ).

I still like using the chili framework myself. It's small enough to quickly download. It's pretty much just ready to go, just go to the Game class and start programming. I use it a lot when I want to do some 2D graphics and don't want to get SFML to work ( I seem to have troubles with vcpkg and lately have been having troubles with Nuget in getting SFML to work ). Also, the chili framework doesn't have any external dependencies, which is a huge plus. SFML uses 4-5 or so other libraries for sound, founds, image loading and others. The most difficult thing for me is CMAKE, but it seems VS has gotten a lot better and handling it, so those concerns are fading.

The only things I've been able to do with DirectWrite is load the IDWriteTextFormat and IDWriteTextLayout, and maybe get a collection of system fonts, so no I haven't gotten any further than what you can find on MSDN. The only other font rendering library I've heard of is FreeType. That's what SFML uses to render their sf::Font to screen.

There's a user on here that created a tutorial series on blocking and non-blocking sockets networking:
https://www.youtube.com/user/Jpres/videos
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply