Raveler

Members
  • Content count

    45
  • Joined

  • Last visited

Community Reputation

132 Neutral

About Raveler

  • Rank
    Member
  1. [quote name='SriLumpa' timestamp='1313652191' post='4850638'] [quote name='ooog' timestamp='1313622364' post='4850525'] For example, say I have a render component, which needs the coordinates from a position component to know where to render a sprite. When updating the render component would you just use the getComponent() method to get the position component? [/quote] I think in this case, the "position" components are sending "I just moved" messages to the render components, but I might be wrong (maybe it's too costly ?). [/quote] That is how it should be done. Sending messages is extremely efficient; it's almost as efficient as a direct function call. So you don't have to worry about it being too costly. If the position changed, the component should send a message, and the subscribed entity (in this case, the render component) will receive the message and process it. Another option is to do a requestComponent on all Position components in the Render component, and maintain a list of all Position components. You can then iterate over the list during each draw loop, and render everything.
  2. I released a new version! This version has all boost dependencies removed, instead using the std::tr1 variants. This makes Cistron completely stand-alone. You do need a pretty recent compiler though, visual studio 2008 express edition, for example, does not contain the tr1 unordered_map yet. As always you can download the new version from the project webpage: [url]http://code.google.com/p/cistron/[/url]
  3. Hello, I've made a tutorial guide for 2D collision detection with spheres. It might be of use for anyone who's currently making a 2D tile-based game and wants collision detection for free-moving game objects in the tile-based world. I wrote this guide because I couldn't find anything similar when I was looking for it. You can find the guide on my blog: [url="http://strawberrycowbear.blogspot.com/2011/06/simple-sphere-based-collision-detection.html"]http://strawberrycow...-detection.html[/url] All feedback is welcome!
  4. Vector flipping

    There are an infinite number of pairs of axes that form a orthogonal system with one vector. Imagine 2 perpendicular axes rotating around your vector. They're all orthogonal with each other. So you need a second vector, typically called the "up" vector, which determines which direction is actually up. Together with this up vector, you can determine the two other axes that form your orthogonal system. The up vector is typically taken as: (0,1,0) in OpenGL, ie high y values means the object is higher up in space. First start with normalizing your vector diff. Then calculate the cross product between diff and the up vector, to get your first axis: right = diff x up Now, finally, calculate the cross product with diff and right to get your up axis (which is different from the up vector, but will point as "up" as possible while still being orthogonal with the other two axes: nup = right x diff Now diff, right and nup form an orthogonal axis system which you can use for roll, pitch and yaw.
  5. Interesting. So pretty much everything I use is now available in the STL through TR1. How widely implemented and stable is this? I'll do some research. Either way, thanks for the heads up.
  6. [quote name='Dan_orbis' timestamp='1308838836' post='4826791'] Thanks, well I made a point of building the core library without external dependencies (other than STL). Boost in particular is a monster. The most important Boost ideas made their way into the STL and are widely available now, so it's possible to do away with it. Anyway a rewrite can't hurt, components and messages are quite complex, we've already taken very different approaches. [/quote] They are? I make heavy, heavy use of boost::bind, boost::any and boost::function. I also use boost:unordered_map because it is faster than the STL map implementation (it's a hash table). Boost is indeed a monster but I can't program C++ anymore without those libraries. Especially boost::bind.
  7. [quote name='Dan_orbis' timestamp='1308830026' post='4826732'] Interesting, looks like we're developing similar frameworks / engines. I'm also as excited as you are about this approach. I made this post in another thread about scene graphs: [/quote] I think what you're doing can actually be built upon Cistron. Cistron provides the basic component architecure and message-passing framework, and the rest can be built on top of it. I use similar structures in my games. For example, in my current project, I programmed a quad tree (which is a scene graph) on top of Cistron to handle efficient drawing. Your project seems a little more ambitious than a simple quad tree. Interesting application of the paradigm! Good luck with it! It's too bad we wrote, independent from each other, probably a large portion of code twice.
  8. I released a new version of Cistron, which takes care of some memory issues, and adds several useful functions to gain access to components of other objects. Since I've created this library, I've been using it in pretty much every project I've worked on in C++. It's so awesome that it's completely changed how I program games. If you haven't considered component-based game programming yet, I recommend giving it a look. Cistron might help you out if you're having one of the following problems: [list][*]You are working with lots of game objects in a deep inheritance hierarchy, and you end up having to put a LOT of functionality in the root object of the tree, because it's shared by so many different subclasses. [b]Cistron[/b] solves this issue by splitting objects up in components that each implement a particular functionality. Objects are composed of these components depending on the functionality they need.[*]You have trouble organizing communication between different game objects. Maybe you solved this by creating some sort of managing object that keeps a list of all the objects, and acts as a mediator between them. Or maybe you determined a hierarchy between different game object types, and the one higher up in the hierarchy leads the communication with the ones lower down. A typical case in which this problem often occurs is collision detection. [b]Cistron[/b] allows you to have neutral communication directly between objects, without a hierarchy and without another class linking the two objects together.[*]You have a "Game" class which contains a lot of lists, each for different object types, in order to keep track of which object should be drawn, which should be updated, which should receive mouse or keyboard input, and so on. [b]Cistron[/b] solves this issue by allowing components to subscribe to messages, which are then broadcast by the game object and automatically sent only to those components who are interested in them. Different components (different classes) can subscribe and receive the same message, and process it in different ways, without the need for a shared superclass interface.[/list] The newest version can still be found on: [url="http://code.google.com/p/cistron"]http://code.google.com/p/cistron[/url] All feedback welcome!
  9. List of free libraries

    Cistron: component-based framework http://code.google.com/p/cistron/
  10. I uploaded a new version. Changes: - ObjectManager Singleton removed. You now just create an instance of ObjectManager and add components to it. Multiple ObjectManager's possible now. - boost::any used for the payload instead of void*. - Message passed by const reference instead of value. - No pollution of the global namespace through #define's or anything else. - Some other minor changes and improvements to the interface and code. This should address most of the issues raised in this thread. The updated source code is also visible from the 'Source' tab on the website. Feedback still appreciated.
  11. Quote:Original post by nullsquared Why make something a singleton without reason? [wink] Well, the reason is that a singleton was comfortable in the game project I'm working on. I extracted this framework from my game project, which is why there are still some remnants in the code that originate from it being part of a larger game. This kind of feedback will hopefully help iron out these problems and make Cistron into a mature, stand-alone library. Quote:Originally by Tutorial/example GE in this case, because the message originated from a requestMessage call * - sender: A void pointer to the Component who sent the message. Typo, I'll fix it in the next release. Quote: True - but even if they were unsafe, you're still not checking for a NULL result as you're passing the result directly to boost::bind [wink] The library is designed for speed, so I ommitted any checks that would slow down the game. I expect some basic common sense and proper use of the user in several places. You can break the library easily if you do it on purpose, but so far I haven't encountered any places where I accidentally screwed it up, so I think it's safe enough. In this place, for example, it's really hard to screw up, since the sender is filled in automatically by the system; the only thing you can screw this code up with is by passing a member function of another class. Which is hard not to do on purpose. Besides, why so concerned with passing null? You're squaring it all the game. Might cause a segmentation fault here and there. :) Thanks!
  12. Quote:Original post by Ravyne So, first, the sample code was a little unclear (ie - doesn't seem to demonstrate) why this is a component-based system, vs. a message-passing system, but presumable one can associate an ObjectID with more than one component. Correct? Actually, the sample code does demonstrate multiple components per object: at one point, one object has a person component and 2 job components. It also demonstrates the ability of a component to add components of itself to his or other objects. Quote:Next, are there rules/documentation regarding the order in which components receive their messages? Is this under user-control? If worthwhile, and it may be, it seems you could add it by asigning each component a priority-level, and maintaining a sorted list, per object. This could also be extended to Messages, if they are not sent immediately. Messages are sent immediately and act as function calls. It's stored as a plain STL list, so the order in which components receive messages is defined by the order in which they request them. I agree that a nice improvement would be to change this to a priority list and sort them in some user-defined order. Quote:Finally, I noticed that your Message structure contains a payload member, which is defined as a void pointer (according to the comments) -- how is ownership of the data, and transfer there-of, defined. Does the message reciever assume ownership, and therefore, must also delete it when its done? If so, std::auto_ptr could greatly simplify these semantics, allowing the reciever to simply let the payload fall out of scope. Hrm, then again, perhaps the Message itself assumes ownership? Normally, you shouldn't really use the payload system that often. Because I wanted maximal flexibility, I added it as a last resort if you cannot use anything else. For example, the sender is passed along with the message, so normal use is to cast the sender to its original class, and use getters to obtain the desired information. However, in some cases, this may be impractical, so the payload pointer is added so that you can pass a struct or something else that contains the data that needs to be examined.
  13. Quote:Original post by nullsquared Why is that hack needed, anyway? I thought it was for VC6 compability, which no one uses anymore. You're right. It's old legacy code I originally got from Game Programming Gems 1. Quote:Second, what happens if I want two or more object managers? What if I spawn a minigame inside the real game and the minigame has its own (separate) objects? Point taken. I'm not sure. I guess it doesn't HAVE to be a singleton, it can perfectly work without the requirement. Quote:Third, if sender is a component, why void* instead of Component*? Sender is Component*, where do you see differently? Quote:Forth, why void* instead of boost::any for the user data? (or is "payload" something else?) I'm not familiar with boost::any. I'll look into it. Quote:Edit: Further observations: Why pass Message by value instead of const reference? Good point. Quote:Why have utility "register" functions that internally use a dynamic_cast (not a good idea, you might as well use a static_cast since you're not checking for NULL anyways)? Just let the user do the binding - no casting involved. The utility function is there to provide a smooth interface. I had to type requestMessage("Msg", boost::bind(&A::fun, _1)) so many times, that I wrote utility functions to hide the bind from the user, changing the statement into requestMessage("Msg", &A::fun). But since the utility functions are safe anyway, you're right that I can as well remove the dynamic cast.
  14. Quote:Original post by magic_man You forgot to mention you are also using boost. Doh, you're right. I took that as a given because it's so natural to use boost in a c++ project nowadays. I'll change it in the documentation tomorrow, because this is indeed a huge dependency. Quote: The first header I looked at has namespace using declarations at global scope which is a really bad idea. You mean the 'using' statements? Sure, I can put those in the namespace. Quote: You are also using a singleton (which I will not comment on its use) but it is not safe. Firstly you use a hack to get the offset. *** Source Snippet Removed *** Next the assert will only be hit in debug code and not release, in addition you do not define the copy constructor so it is auto generated meaning the class can be copied. These are the only two files I have looked at so far. Firstly, the hack is a hack, but is safe as far as I know. Secondly, asserts ARE only supposed to hit in debug mode and not in release mode. That's what they are for, so I fail to see your point. Thirdly, sure you can copy the class, it doesn't matter, the singleton is stored in a static member. Finally, I appreciate the feedback but you can also give it in a more constructive and less offensive manner. Thanks.
  15. All the source code is available on the website, so you can see for yourself in detail. Basically, I first map each string representing a particular message to a unique integer identifier. This identifier is then used to index into an STL vector (which is constant-time) containing a list of all the listeners. The magic is in the mapping to the intermediate id. Because you can do this mapping once, and then use the id directly instead of the string identifier for extremely fast message sending. If you use the identifier to send the message, there is only one function call overhead.