Jump to content
  • Advertisement

Saitei

Member
  • Content Count

    24
  • Joined

  • Last visited

Community Reputation

185 Neutral

About Saitei

  • Rank
    Member

Personal Information

  • Role
    Programmer
  • Interests
    Education
    Production
    Programming
  1. I'm using glm library. Transform class stores single glm::mat4 Fuction glm::decompose can give me all information I need, but... Why I need to extract everything if I need, for example, only position? Don't sure about interface of Transform tho
  2. Hello! I'm looking for C and C++ programmers who want to have a good time during thematic discussions Do you like C/C++? You are welcome! Do you like CG (OpenGL and etc.)? You are welcome! Do you develop your own game engine? YOU ARE WELCOME! I hope you enjoy our chat. Here is invite link https://discord.gg/7rRHRqN ( ͡° ͜ʖ ͡°)
  3. Uh... https://cmake.org/Wiki/CMake/Tutorials/Object_Library is useless, cause lib/glfw/CMakeLists.txt and lib/glew/build/cmake/CMakeLists.txt gives me only LIBRARIES, not OBJECTS.  Conversion LIBRARY -> OBJECT possible? Guys! Please help me(
  4. When I tried to create a VS2015 project with my library manully I noticed that dependencies is not linked.  Here is my CMakeLists: https://github.com/xSaiteix/SOGL/blob/master/CMakeLists.txt (Something going wrong at this line?) target_link_libraries(SOGL glew_s glfw ${OPENGL_LIBRARIES}) Help me please. And sorry that my english is bad, it is not my native language
  5. Im using this pathfinding method https://harablog.wordpress.com/2009/01/29/clearance-based-pathfinding/   The object sizes can be different. So, how can I smooth my path by curves without any artefacts? 
  6. How about pimpl? You can hide class GameWindow inside Engine implementation
  7.   How about void prepare()? system->prepare(); system->update(dt);
  8.   Really good idea! It's brilliant! Can you advise how I can name the buffer? And how to call a method that is called after update? My dictionary of English words is not very large, so I can not come up with a beautiful names
  9. #pragma once #include "ISystem.h" #include "Utils.h" namespace ecs { const uint32_t default_capacity = 64; template < class Component, uint32_t InitialCapacity = default_capacity > class System: public ISystem { struct ComponentWrapper { EntityId owner; Component data; }; public: System(): //preallocate some memory free_components(InitialCapacity), components(InitialCapacity), entity_map(InitialCapacity) {} virtual void update(float dt) override {} void for_each(Function<void(Component&)> func) { for(auto i : used_components) //Sequential update of components. Cache should be happy (here is some cache-misses due of Set, but it's okay) func(components[i].data); } void add_component(EntityId eid, const Component& c) //Best: O(4 + log(n)), Worst: O(3 + n + log(n)) { ComponentIndex cid; if(free_components.empty()) //O(1) { cid = components.size(); //O(1) components.push_back{eid, c}; //O(1) or O(n) } else { cid = free_components.back(); //O(1) free_components.pop_back(); //O(1) components[cid] = c; } used_components.emplace(cid); //O(log(n)) entity_map[eid] = cid; //O(1) } void remove_component(ComponentIndex cid) //Best: O(2 + log(n)), Worst: O(1 + n + log(n)) { entity_map.erase(components[cid].owner); //O(1) used_components.erase(cid); //O(log(n)) free_components.push_back(cid); //O(1) or O(n) } private: HashMap<EntityId, ComponentIndex> entity_map; Vector<ComponentIndex> free_components; Set<ComponentIndex> used_components; Vector<ComponentWrapper> components; }; }; ??What do you think about this code? Costs of Set justified?     And... Here is some important question.  What if someone want to remove component inside for_each? How to fix this bug?
  10. I can't use it. Because there is many find calls. Systems already can iterate by its components and answer the question "Is it used now? Can I update it" without using of find function. Very frequent searching exactly bad for performance...    System<T> can work something like this:  vector<T> components;  dynamic_bitset<T> alive_components; //actually there is no std::dynamic_bitset. Btw, std::vector<bool> storing bits, not bytes void for_each(std::function<void(T&)> f) {    for(size_t i = 0; i < alive_components.size() && i < components.size(); ++i)    {       if(alive_components[i]) { f(components[i]); }    } }
  11.   Thank you, good to hear :)   Entity is not pure id. It has some methods. phil_t understood me correctly:    I understand that perfectly     That's right. System<T> is not only logic. It's storage, too.  Sp, inside System<T> I can make something like unordered_map<Entity, uint32_t> components, where uint32_t - index of component in some container (for example, array) This dictionary is used in such cases: 1. Component creation 2. Component destroying 3. When I need get address of component for specific entity   My doubts: 1. unordered_map or some else HashMap is fast enough?  2. Search by value, not key, a bad thing? I must have some ability to get component's owner. Create another map?: unordered_map<uint32_t, Entity>?   Typically, the system will operate at the component level. So, using hash map is not bottleneck..?    Uhm, I see. But how fastly get this entities with this kind of components? Why I can't just create another Component with pointers to the desired components inside?  That's it: 1 System = 1 Component. Another thing - if the component by a reference now is invalid (somehow deleted). But it is logical issue that must be "debuged"      Very well. But... I am designing abstract ECS library that can be used everywhere.  I really do not understand how can I get entities with specific components without performance issue. If I add some "glue-components" like this: struct Position {   Position(float x = 0, float y = 0): x(x), y(y) {}   float x, y; }; struct Rotation {   Rotation(float angle = 0): angle(angle) {}   float angle; }; struct Size {   Size(float x = 1.0f, float y = 1.0f): x(x), y(y) {}   float x, y; }; struct Transform {   Transform(Position* position,             Rotation* rotation,             Size* size):             position(position),             rotation(rotation),             size(size) {}   Position* position;   Rotation* rotation;   Size* size; }; It becomes very easy.    Thank you. This is the third way of communication between the systems! :) 1. By the data (components) 2. By the messages  3. By the direct call (system can be passed to another system by constructor)   It is okay. I can make function update non-pure (virtual void update(float) {}), so method update not necessary to implement.   Another thing - all systems must inherit from my class. But it is a necessary sacrifice, because I'm developing a library rather than a specific application.   Yes... However, I realized not too many ideas. Perhaps the problem is in the language barrier. Method "some_system.update(dt)" called every time when I call world.update(dt). Or is the problem purely in the name of the method?    If it so, how about word "process"? :)     What is the difference between them?   Thank you for your comment. Yes, it is very important the order of message processing. Also bags is possible when I everytime send message A from function that handles messages with type A. while(true) =)
  12.   That's right.  I am now 20 years old and I started programming in 2009. Previously, the OOP approach seemed to me the cure for all ills.  I just did not know what approaches exist and what disadvantages there are in the OOP. I also did not know how CPU works and how to use the multithreading.   But now... More or less I understand.    ==First of all, multithreading.  Multithreading with 100500 mutex lock's... WHERE IS POWER OF MY THREADS?! Yes. In this case, the program will work very poorly. Even worse than the single-threaded program.  Also, here is cache issues... It all depends on the architecture, but typically processor cores provide its cache.  One core can easily invalidate cache of another core, so this core must reload cache from RAM (Yuck! Core cycles are idle).   So, there is cure: The smaller the number of locks - the greater the efficiency of multi-threading. Also it is necessary to intelligently share data for multi-threaded processing, so that the CPU cores did not fight each other.   If I know what components are processed by the system, and also know that there is practically no modification of components from other systems, it becomes possible to make multithreaded computations without blocking.   ==Cache-friendly code && OOP  For example, I have object "Tank" which is derived from Transform, Scriptable, Mesh, etc.  Suppose that it is necessary to update the position of all objects. And... Here is a issue. With transform component we also load to a cache a lot of "trash". If i need update only transforms, why I need load to the cache Mesh/Scriptable?    In ECS case: all transforms in one continuous memory area. So, cache store ONLY useful information and use it VERY WELL, because update goes sequentially. Cache is very hot :)    Also here is a very well reusability of components (if it designed very well). Yeah, in OOP with this all ok too. But... Here is some logical problems.    ==Only logic Basically, the system contains processing logic only. It enhances the beauty of the code and allows you to concentrate only on the logic.   ==Easy to rewrite Because logic placed in one place. The code is not scattered on different classes.   ==Easy to debug (It follows from the preceding paragraph)   ==vtable lookups  No vtable lookups inside method update. Vtables is not so terrible... But we can don't use them   ==OOP is evil? No. I love basic idea. It's really easy to understand. But sometimes it is hard to develop and debug, also performance issues is possible.  OOP - is not "MUST HAVE" concept. I think, it is better to mix OOP with many other concepts to make it stronger =)   P.S. I will respond to other posts a bit later. Some things difficult to translate into my native language
  13.   Because I'm developing generic ECS library.  Storage method we can specify by the template parameter. But first, I want to write a simple System<T>    Single responsibility principle. If other systems must be notificated - just send a message    Keep a little bit of data in the system is possible. But if there are a lot of data - there is problem in Data (Components) design   Because I developing ECS library. It is interface for custom systems. Implementation of it interface can add some more methods   It's okay. Just do not try to dissuade me, I really want to develop a ECS library: P
  • 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!