Page 1 of 1

Little sfml platformer framework - game thing

Posted: June 16th, 2017, 1:05 pm
by Florian3321
Hi everyone!
I made a little "platformer-framework" around sfml. Really I just used sf::Texture, sf::Sprite and sf::Clock so if I know how to load and display sprites in the chilli framework (in some time when the tut is out ;)) I want to "port" it over to the Chilli Framework :)
For those who are interested, here is the github: https://github.com/florianPat/SFMLPlatformer
It would be very cool if some of you maybe look over it, write what could be improved and so on. You know ;)
I know that I should use more const-correctness but up until this point, I was to lazy to really do it, so...
I am not sure if I use the shared_ptr, unique_ptr really right or if I do a big mistake, so response on that would be also pretty cool.
Moreover, in Component, I have a circular dependencie. I do not know how to avoid that, but if someone comes up with an idea, I would be very likely to hear it!
Thanks for answers in advance (or how you call it ;))

Re: Little sfml platformer framework - game thing

Posted: June 16th, 2017, 3:27 pm
by chili
Looks like interesting stuff. It's already a pretty complex system, I can't really give a detailed analysis. But it seems like your use of shared_ptr isn't bad. You've got some weird code where you pass in an iterator as a parameter, that could probably be cleaned up. Also, I think you should add a garbage collection function to clear out all objects that don't have any external references. I'll see if I can build this later. Looking forward to seeing what you make of it bro :)

Re: Little sfml platformer framework - game thing

Posted: June 16th, 2017, 11:37 pm
by xu2201g
Hi,
looks like you already solved the circular dependency problem. If u cant avoid it by design you ve to use forward declarations afaik like u did with the Actor class in Component.h.

short explanation:
https://stackoverflow.com/questions/492 ... ation-in-c

how to use it properly:
https://stackoverflow.com/questions/553 ... eclaration

If u already know that stuff ignore it.

I reviewed some parts of your code.

like:

Code: Select all

template<typename T>
inline T* Actor::getComponent(int componentId)
{
...
return dynamic_cast<T*>(result->second.get()); //TODO: Do I really want to return a raw pointer?
}
I am not that familiar with smart pointers yet, but i would say its fine to get a rawpointer here.

In my sourcecode i handle resourcemanagement with smartpointers.
For example when i load a new texture from file and store it in a std::unordered_map like:

std::unordered_map<std::string, std::pair<std::unique_ptr<T>, unsigned int>> m_resources;
T can be for example a sf::texture, sf::font, sound etc.
(i know shared pointer would be a better way to solve that like you re already doing, but i was to lazy to adjust it yet)

When for example a sprite needs a texture you can use a raw pointer imho. Even if the ownership of the texture ll move the raw pointer adress should stay the same - i made a quick test before with std::unique_pointer

Code: Select all

	Foo f1(1);
	Foo f2(2);

	Foo* pRaw1;
	Foo* pRaw2;

	std::unique_ptr<Foo> p1(std::make_unique<Foo>(f1));	
	pRaw1 = p1.get();

	std::unique_ptr<Foo> p2 = std::move(p1);
	pRaw2 = p2.get();


	std::cout << "p1Raw1: " << pRaw1 << std::endl;
	std::cout << "p2Raw2: " << pRaw2 << std::endl;
Please correct me if anything is wrong.

Re: Little sfml platformer framework - game thing

Posted: June 17th, 2017, 3:58 am
by albinopapa
Use smart pointers for lifetime and ownership of resources. Use raw pointers to pass to functions when lifetime will outlive the function and ownership of the resource won't be transferred to the function or anything inside the function.

That's my rule of thumb.

The reason for smart pointers is to allocate when created, and deallocate when destroyed ( leaves scope ). It makes resources on the heap act more like resources allocated on the stack. When a resource allocated on the stack leaves scope, then the resource is freed. So when a smart pointer like std::unique_ptr leaves scope, the dynamically allocated memory is freed. This also reduces the amount of work the programmer has to do. Before std::unique_ptr, you would have to use operator new/new[] to allocate and either at the end of a function or in a class destructor, you'd have to call operator delete/delete[] ( new/delete for single elements new[]/delete[] for arrays of elements ).

std::shared_ptr is useful for shared ownership, and has it's benefits and drawbacks. Personally, I'd only use it in multithreaded situations because of the atomic reference counting. The way I would approach resource sharing in single threaded situations would be to store the unique_ptr some where, and pass around the raw pointer stored using unique_ptr::get(). I always know in my own code, raw pointers are not owned, while unique_ptrs are owned. Either way I don't have to delete my pointers because of the stance I take on how I use them.

Re: Little sfml platformer framework - game thing

Posted: June 17th, 2017, 4:03 am
by albinopapa
Forgot to mention about shared_ptr. Dealing with passing them around can get confusing because of the reference counting. If you pass them by value, the reference count goes up, so pass to a function, add 1, copied inside the function add 1, leave the function subtract 1 for the paramter, then maybe 1 for the copy depending on the lifetime of the copy. Pass by reference, no increment for the paramter, but there add one for the copy. Leave the function, no decrement for the parameter, but maybe for the copy again depending on the lifetime of the copy. Pass by const ref...reference counter can't be incremented for the parameter or the copy, so is it still a "shared" pointer?

Re: Little sfml platformer framework - game thing

Posted: June 17th, 2017, 4:12 pm
by chili
shared_ptr is excellent in both single-threaded and multi-threaded situations. If you have some shared resource and you have one object own it with a unique pointer and others reference it with normal pointers, when the owner dies all the others will have dangling references and that is a terrible situation.

If you have a situation of sharing between peers, use shared_ptr. If you have a situation where one object is guaranteed to have a lifetime that encompasses all the lifetimes of the objects which refer to the resource, you can have that object own the resource outright with a unique pointer and give out references. This situation is not what I would call sharing, and it does not require a shared pointer.