Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

151 Neutral

About Nohup

  • Rank
  1. Well, if I'm reading you correctly, it seems the issue you have is with event communication.   The "Event" that is occurring is a dice roll. Ignoring everything else,  the event taking place is a dice roll.   Now, from what you describe, there are a number of dice-roll types that can occur.  2-dice, 3-dice-subtract-lowest, 4-dice, etc. Those events must be communicated to all interested components.  The most generic way to do that is to broadcast the type of dice-roll, and then the dice.   Broadcast(4-DICE-ROLL_ENUM, 6,3,2,6)  //where the enum tells what kind of roll, and the 4 numbers tell what the rolls were.   You can package the message up in a million different ways, the important part is entities and/or their components need to hear about it, and react by changing their internal state, and/or sending out their own messages.  One of the entities/components may score that roll as a hit, and set it's internal state to dead, while sending out a "Died" broadcast message to all the other entities/components.   So, to directly answer your question, I guess you would say you "put the logic of the ability into the components".  Because they have to deal with these events as they see fit.
  2. I think there's an issue with the use of the word "alignment" in your post. That word has a slightly different meaning than what you're considering. It's more to do with the exact placement of something within the memory banks of a machine along certain boundaries (byte, word, page). If I read you right, then you don't really care about exactly where a thing is placed. You're more concerned that all the things you make are placed in an orderly manner, and tightly packed, to get better cache utilization. If that's the case, then you were going along the right path with your thoughts of using a vector to store your components. The problem with a vector is that all the types in a vector must be the same. And from your code-snippet, you were thinking more of using a common interface to a set of different derived classes (components). Your code snippet shows that you want to store pointers to various types of components. That's a pretty common method. But I'm afraid, that it is unlikely that those components will ever be near each other in memory (cache coherent). The best you're likely to get, is having all of your components of a certain type together in memory. For instance, the "Health" components can all be pre-allocated in a vector/array, and can be tightly packed together. Your entities will store pointers to those components (as in your boost:unordered data structure). Then, if you can structure your code to run all of the entitiy's "health" processing at the same time, your cache-utilization will be very good. Do this for every component type, and you should get most of what you're looking for. Now, managing a whole bunch of vectors for every component type might be a bit daunting. Every time an entity is destroyed, you will have to remove it's components from their storage vectors, or somehow mark them as free. That can be a bit of a pain, and could lead to a lot of bugs. My advice is to use a freelist or some pooling allocator to do the job for you. (Game Programming Gems 4 has a good article on freelists, and boost::pool has a nice implementation that you could use to help manage the lifetimes of the components Once you have all the components in their homogeneous vectors, you might start looking for a way to just iterate over all the components within those vectors, without even considering what entity they belong to. Like the health example, you could check all the healths to see if any are <0, and if so look up that health's entity ID, and create a message for that entity to "die". Lots of flexibility in this setup, it's a lot like what I've been toying around with for a while. good luck.
  3. Nohup

    Threading / Message Queue

    While I don't dispute that message queues are great ways of moving messages around, they are not at all efficient for communication within a single process. There are several orders of magnitude more overhead in using a message queue, than using an in-process mechanism like a producer/consumer queue or a lockless FIFO. Message queues are great when you want to move messages between different processes, and want to have certain guarantees about accepted messages being received by "someone." [/quote] All very true. Although, zeroMQ does have an "inproc" socket, which is really a thin wrapper around a lockless FIFO. It should surely be fast enough to move packets between the game and network threads. It sounded like the OP was looking for a quick, easy, off-the-shelf way to move data between threads. I use this to do work-queuing on a project now, it's so dead-simple to use, I just had to mention it.
  4. Nohup

    Threading / Message Queue

    It seems like you're main question revolves around a good (efficient/safe/whatever) way to move data between two threads. There are many ways to do this, some are easier, some are faster, no way is really wrong as long as it works. Something that's working well for me right now to do a similar thing is a library called Zero Message Queue. (or ZMQ, or 0MQ) It's another API to learn, but it's simple. It's fast enough for everything I use if for. It's free, and extensible, so if you ever want to break this out into two processes, or two computers, instead of two threads, the API is nearly the same for both. It's something to look at, I've been pretty happy with it so far for a similar application. I wish someone would have pointed it out to me sooner. Good luck with your project.
  5. Nohup

    Events and entity communication

    "I think this would work well, but the issue is for a lot of things, everything gets everything. I could sort it, but then it would be a lot of manual setting and registering of types." The way I'm dealing with that particular part of the entity-system problem is to have components which act as filters for messages. I read a lot about the actor model while dreaming up my system. The way it's handled in that model is for an actor to filter and forward messages to other actors. I liked the flexibility of that, and came up with an idea like this. 1) Player causes explosion at (x,y,z) 2) EXPLODE(x,y,z) goes out to every entity who is registered, _BUT_, the only one who's registered is a "localizer" entity, who knows where all entities are located. His job is to forward a message to all the entities who are close to (x,y,z) in the form of NEARBY_EXPLOSION(x,y,z) Those entities can deal with the NEARBY_EXPLOSION message in any way they wish. I should mention, that my component/entity system is 100% for fun, experimental pie-in-the-sky, and will probably be too slow to ever be used in production code. It's sometimes been called a "Flurry of Messages" system. Just wanted to disclose that in case you try to do something similar.
  6. Quote:Original post by reptor Hello, it's fine if you want to make your own, but I just want to let you know, in case you don't yet, that there is a threadpool library, which uses boost.threads: http://threadpool.sourceforge.net/ If you decide to go this route, you should know boost.threadpool has been renamed to boost.task . It's in the boost vault, and if I'm not mistaken, is scheduled to be included in the boost libraries soon. I'm using it for a few things, and it seem to be a very nice piece of software.
  7. Scott Meyers books are a must-have for any programmer. After you've got those, I'd go for the Game Programming Gems books. (5 and 6 were my favorite). They're expensive, but very fun books. I keep them on my desk and have people borrowing them all the time.
  8. A quick question for those who have/will be implementing this sort of system. I'm curious about the "messages" which are passed between the components and subsystems. Are these messages serialized chunks or data? Which can be buffered, and passed around in a conventional manner? Or are we talking about a signal-slot, or a callback/functor type of system? I imagine that both methods would be possible, but the choice would impact the performance and extensibility of the system. It would be great to know how people have implemented this, and how it worked.
  9. Nohup

    select without a linear search?

    Boost has the "asio" library. It wraps the epoll/iocp calls into a single interface. Works the same on linux and windows. It's not perfect, but it's portable, and event driven (no select search to do). www.boost.org
  10. Nohup

    Spatial Partitioning for Entities

    Quick description of my understanding of a spatial hash... An object is at (X, Y) (we'll just consider a mostly flat 2D world) Lets put 2 objects in the game, their locations are (100,200) and (300,400) To "hash" thier spatial positions, I would divide their coordinates by, say 100, and drop the remainder. That puts the 2 objects into the boxes (1,2) and (3,4) That's just the hashing part. So, a 3'rd object at (123, 234) will "hash" into (1,2) as well, right alongside the (100,200) object. Now, the actual data structure you would use to hold these items is a 2D array of set<object> or linked list, or vector<object>, or whatever data struct suits your purposes. Then, whenever an object moves, say goes from (199, 250) to (200,250), you will remove the object from the set<object> at (1,2), and move it into (2,2) When you want to see if another object is close, you would search through the set<object> which holds the querying object, and other nearby sets to find neighbors. You should never have to "rebuild" this sort of a system, just update it whenever something moves. The positives to this system are very fast insertion, deletion, and updating. It's memory requirements are small, and it is very easy to make the "boxes" bigger and smaller (by adjusting your hashing number), to optimize the performance. The downside, is that this system works best with points. When an object is located at (199,299), if probably overlaps into another "box". Sometimes, this isn't a problem, but sometimes it is. It depends on what you're doing with it. Loose quadtrees would probably be better to use if your AI system has to take the "size" of objects into account. Another downside, is that a sparsely populated array of linked lists, will probably not provide the most optimal performance. You'll be looking through quite a few lists that don't have any objects in them. This could be helped with a "empty" flag for empty boxes, but I doubt that would help too much. It's all about trade-offs. Try to think of the best/worst/general case, and keep things generic, so you can switch out a different data structure if you need to. "Game Programming Gems 6, section 1.4" has an excellent article on this sort of thing called "Geographic Grid Registration of Game Ojbects" It focuses more on objects that have a "size", and register themselves with all the grids they occupy. It's not quite the same thing, but the same basic idea. keep googling, and good luck.
  11. Nohup

    Spatial Partitioning for Entities

    Have you considered a spatial hash? Or something like a grid of linked lists, where entities can be quickly added and removed when they enter/leave a square on the grid. I use something like this when my "entities" are points without a bounding area. Queries can be performed on the grid boxes, If a grid box falls completely within the query area, you know all the entities in the linked list are within the query. It sounds like you have a lot of static entities. I suppose you could put 2 linked lists (or another data structure) in every box, one for dynamic entities, and 1 for the static world stuff that doesn't move.
  12. Nohup

    CBaseEntity Help!!!

    A couple pointers for an intrusive double linked list.
  13. Nohup

    Must-have Game Programming Books.

    Game Programming Gems series. They're all great, but 5 and 3 seem to be the ones I'm always re-reading. Lots of great stuff there. Buy the whole series, you won't regret it. Design patterns is good, but I think google can give better info about a particular pattern. Still a must-have reference. A good reference on STL can be helpful, but again, google can tell you anything you need to know. The Scott Meyers books, Effective C++ and More Effective C++ are very good to have, and are relatively cheap. That's my list. I program both at work, and at home, and I'm always carting these books back and forth.
  14. Only have a quick second, but a small "trick" for fast deleting from an unsorted array/vector is to swap the element you want to delete, with the last element in the array, and decrement the "count" of elements by one. I know, it's simple, but something that you may have overlooked. Also, it may be possible to use an intrusive list of your elements. An intrusive double linked list would let you iterate through your insert/delete vectors and quickly set-up the links for your list. It wouldn't be sorted, but you may be able to work around that. Boost just added a nice intrusive list implementation to thier tree.
  15. There's basically 2 ways to implement this sort of architecture. 1) All components inherit from a base class which gives a basic interface for storing the components. Something like a couple pointers for a linked list node. Then, your Entity class will contain this linked list of components. This is a very easily-to-grasp method of managing your components. They're just stored in the entity that they comprise. The downside of doing it this way is that it isn't very easy to "find" a particular component. When you need to send a message to a component, you end up iterating through many entities, even if they don't contain a component of the type that accepts the message. It's still a viable way to keep track of your components. And if your entities are all very similar, this may be the best way to go. 2) The Database approach. (no, not kind of database) This is the way it was done in the Game Programming Gems 5 example. And it's the method I prefer. Basically, components are stored in a series of datastructures which are focused much more around the Components, not the entities. I don't have my GPG5 book here, so I can't detail all the datastructures they hold the component pointers in. But they are mostly things like a std::map of std::list, so you can search the map for components of a certain type, and then iterate through the list sending messages to all the components which can receive that message. All components have an "Entity ID" member variable, but that's the extent of thier association with a particular entity. The cool thing about this approach, is that there _is_no_entity_ entities are nothing more than ID numbers stored in various components. This method seems better to me, but I can see some of the benefits of the entity-centric approach. The good thing is, if I decide that I need to hold on to an entity for some reason, I can always make one, and just add that as a new data-structure in the database object. I'm sure this has been very confusing, especially the method #2 explaination. If you can get your hands on the GPG5 source-code or book, it does a MUCH better job of explaining the architecture than I ever could.
  • 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!