Jump to content
  • Advertisement

rozz666

Member
  • Content Count

    387
  • Joined

  • Last visited

Everything posted by rozz666

  1. rozz666

    Casting Problem

      If you need to cast, then you should review your design. The point of an abstraction not to depend on concrete types. E.g. your GraphicsFactory::init accepts and interface, but inside you assume it's a specific class. What if I derive another class from IInitiationSettings? init will probably crash, even though init declaration told me I can pass anything that's an IInitiationSettings.   Of course, IInitiationSettings should be a data object, but this has already been address in other posts.
  2.   While this is true for operator<, std::less for pointer guarantees correct ordering (source: http://en.cppreference.com/w/cpp/utility/functional/less).
  3. rozz666

    Using old array or stl

    Yes, I agree with fastcall22.
  4.   Python reference are C++ pointers (they are also garbage collected, of course).
  5. Have a look at Boost.MPL: http://www.boost.org/doc/libs/1_55_0/libs/mpl/doc/refmanual.html It provides among other things containers and algorithms for types.
  6. rozz666

    Always running into a circular dependency

    Why does an Entity has to know about the Scene?
  7. rozz666

    Unit Testing ftw?

    In my experience when I started using Unit TDD and Accepance TDD, I've never had to step through every line. That's what my tests are doing.   I'm also surprised that no one mentioned that writing unit tests improves the design of the application. It enforces separation of concerns, single responsibility principle, dependency inversion, etc., because it becomes difficult to unit test classes if they violate these principles. This, in turn, improves maintainability.
  8. Very good article. Good emphasis on the importance of naming things correctly instead of commenting them.
  9. If I understood correctly, you have a shadow function that depends on time (let's call it s(t)) and you want to describe this function. For this, you want to make is a smooth step function (_/---) so you just need to store the coefficients. Keep in mind though, that you need more than 2 values. s(t) looks more like this (sunrise ___/--day--\___ sunset), so you need at least 4 values. Still, it should be pretty easy to implement. This, of course, assumes fixed relation between the ground and the sun.
  10. I would split the algorithm into the smallest pieces that are reasonable and unit test every possible scenario. Then the only bugs that could occur would be integration errors, which I would cover with module tests.
  11. rozz666

    The Lua Tutorial

    I disagree. This is a tutorial meant for beginners and suggesting bad coding practices in the examples can be harmful.
  12. rozz666

    The Lua Tutorial

    Please, drop the Hungarian notation.
  13. rozz666

    How to handle endianness?

    Using the union solution also causes undefined behaviour. You are only allowed to read the last assigned member (with few exceptions, not applicable here).
  14.   Then it should be mentioned in the article that the code is not C++ compliant and will only work with given compilers that support such extensions.
  15. This: union { float f; unsigned char b[4]; } dat1, dat2; dat1.f = f; dat2.b[0] = dat1.b[3]; dat2.b[1] = dat1.b[2]; dat2.b[2] = dat1.b[1]; dat2.b[3] = dat1.b[0]; return dat2.f; is undefined behaviour in C++. You are allowed to read only from the union member that has been assigned last (with few exceptions not applicable here). This pointer cast: byte SwapTest[2] = { 1, 0 }; if( *(short *) SwapTest == 1 ) is also undefined behaviour. Additionally, it also assumes sizeof(short) == 2 and that it uses 2's complementary encoding which is not guaranteed.   What you could do is use std::memcpy: float f1, f2; std::array<char, sizeof(float)> buf; std::memcpy(buf.data(), &f1, sizeof(f1)); std::reverse(buf.begin(), buf.end()); std::memcpy(&f2, buf.data(), sizeof(f2));  However, it seems awkward that you would keep "reversed" floats around. This should be handled by your deserialization layer, so you should never end up with a need to swap bytes in primitive types.
  16. If reference counting is needed, you can use boost::shared_ptr and boost::weak_ptr. E.g. template <typename Resource, typename Id> boost::shared_ptr<Resource> CachedResourceLoader::load(const Id& id) { if (boost::shared_ptr<Resource> res = cache->get(id)) return res; boost::shared_ptr<Resource> res = loader->load(id, boost::bind(&Cache::notifyRelease, cache, id))); cache->put(res, id); return res; } template <typename Resource, typename Id> boost::shared_ptr<Resource> UsedResourcesCache::get(const Id& id) { Elements::iterator it = elements.find(id); // elements: boost::unordered_map<Id, boost::weak_ptr<Resource> >; if (it == elements.end()) return boost::shared_ptr<Resource>(); return elements->lock(); } template <typename Resource, typename Id> void PermanentCache::notifyDestroyed(const Id& id) { elements.erase(id); } boost::shared_ptr<Image> ImageLoader::load(const std::string& filename, boost::function<void()> onDestroy) { return boost::shared_ptr<Image>(new Image(filename), boost::bind(&ImageLoader::imageDeleter, onDestroy, _1)); } /*static*/ void ImageLoader::imageDeleter(boost::function<void()> onDestroy, Image *img) { delete img; onDestroy(); } When last reference to a resource dies, imageDeleter will be called, which will notify the cache to remove an empty weak_ptr. This will also work with std version of shared_ptr, function, etc. if your compiler supports it.
  17. This is a very common misunderstanding. When using DI correctly you pass Configuration only to the objects that need it and as you mentioned, there will be few of them. Using a singleton would cause coupling. Using DI (and preferably an interface) you don't have coupling. Have a look here: http://misko.hevery.com/2008/10/21/dependency-injection-myth-reference-passing/
  18. It doesn't. Why not just create one instance? Dependency Injection would be a much better solution here.I'm not sure what language you think this is written for but it is C++ which doesn't have a reasonable solution for injections. Even with that, it would still be a singleton, there is only a single instance of the DB required for the program, anymore than that and it would cause problems. class Something { public: Something(boost::shared_ptr<Configuration> configuration); private: boost::shared_ptr<Configuration> configuration; };It's good enough. And it's DI. And I want to create more than one instance of Configuration: in unit tests I want to create a new instance for each test. Same for module tests. I also want to test classes that use Configuration, so I will either: a) create an instance of Configuration and pass it to the class under test; or b) create a mock object (e.g. using Google Mock) to pass it to the class under test I don't gain anything by making Configuration a singleton. On the contrary, I only get problems. EDIT: code formatting
  19. It doesn't. Why not just create one instance? Dependency Injection would be a much better solution here.
  20. I see several problem with the Player class: 1) The class is too big. It has 29 members including arrays! It has too many responsibilities: mouse speed, camera, physics, sound, etc. 2) Manual memory management. std::unique_ptr (or boost::scoped_ptr) would be a lot better. 3) It creates its own dependencies instead of using Dependency Injection. It creates coupling an block the possibility of unit testing the class. 4) The meaning of the last parameter of entity->SetPosition is not clear. 5) Not all members are initialized in the constructor. 6) Constructor is not exception safe (assuming ::Create can throw std::bad_alloc).   Such code smells in an article can teach people really bad habbits.
  21. rozz666

    C++: Custom memory allocation

      Starting functions, etc with an underscore is generally frowned upon, but it is not forbidden.  Most compilers reserve the prefix underscore. Starting with an underscore and a lower case letter is permitted, but an underscore followed by a capital letter is reserved for the compiler implementation.   both "_Capital" and "__whatever" are reserved. more often though, "_Capital" is used for the language-standards to add more keywords, where it is more "__whatever" being used by the compilers (for example: "_Complex" or "_Generic" vs "__declspec" or "__attribute__"). Agreed.
  22. rozz666

    C++: Custom memory allocation

      Starting functions, etc with an underscore is generally frowned upon, but it is not forbidden.  Most compilers reserve the prefix underscore. Starting with an underscore and a lower case letter is permitted, but an underscore followed by a capital letter is reserved for the compiler implementation.
  23. rozz666

    C++: Custom memory allocation

      If the derived classes do not update these variables, maybe that's because they provide their own leak detection system? That's why the base class shouldn't assume anything about leak detection.
  24. rozz666

    C++: Custom memory allocation

    It is forbidden to start identifier names with an underscore followed by a capital letter (e.g. _UsedMemory, _NumAllocations). Also, leak detection (ASSERT(_NumAllocations == 0 && _UsedMemory == 0);) should be delegated to derived classes, since there is no guarantee that a derived class would update these variables.
  25. It's hard to decide how to split the responsibilities of your classes. Try making a domain model (http://en.wikipedia.org/wiki/Domain_model) to define your dictionary and find relation between your abstractions, and post it.
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!