Servant of the Lord

Members
  • Content count

    7244
  • Joined

  • Last visited

Community Reputation

33715 Excellent

About Servant of the Lord

  • Rank
    C++ programmer

Personal Information

Social

  • Twitter
    JaminGrey
  1. Will we ever see an adoption of something other than C and C++?

    While not used too much for game development, Python has been strong for awhile, and over the past few years has grown dramatically for some industries. My armchair amateur opinion is that C and C++ are likely becoming the optimized ""assembly"" behind the scenes (which is what C was originally designed for anyway) for those (fewer and fewer) situations that need it, and that other languages like Python and Javascript will increasingly be used for higher level code. Right now Python and Javascript don't seem to be the dominant gamedev high level language (though they are used on occasion), but it's possible their dominance in multiple other industries will spill over to gamedev and make them defacto industry-wide for high level code.
  2. Any gun enthusiasts here?

    You're thinking in terms of videogame tradeoffs ("If it's more powerful, it must travel a shorter distance"). But it's more often just a real-life money tradeoff ("Just doing target practice? Don't waste the expensive bullets."). This can also have interesting gameplay ramifications - if different types of bullets cost more in-game, players might want to reserve their more powerful ones. Or, if players find ammo instead of buying it, provide less of the more powerful ammo, so players conserve those more. That reminds me of the gameplay of the N64 Turok game, where you got shotgun shells and explosive shotgun shells. Explosive shotgun shells were always better, you just didn't find them as often and so had to conserve them more. At some point though - varying per game - reality needs to take a backseat to gameplay. If you want different bullets to have genuine tradeoffs unrelated to cost, that's so common in games that I doubt it'll break immersion, even for gun experts.
  3. Status Effects (Buffs Debuffs) in an ECS Architecture

    There is no standard "ECS" architecture - they vary wildly, and some are decent, others are terrible. There's a pitfall in thinking that everything needs to fit into that one ECS system - for example, GUIs are usually not a good choice to fit into the ECS, but should exist outside of it. Even within an ECS, there are multiple sub-systems, and those systems usually aren't ECS's themselves - they aren't an ECS within an ECS. So back to your question; what kind of buffs/debuffs are you talking about? How are you currently storing the variables that you want those buffs to interact with?
  4. C++ Need some help with the Entity Component System

    The end-generated code isn't different, but the code itself is significantly different. As you know, in programming there are many different ways to get the same result. But different ways of coding can have different pros and cons they tradeoff (and it's not zero-sum either - some are genuinely better, others genuinely worse) - the code design affects their execution speed, memory usage, development time, compile time, convenience vs amount of boilerplate required, ease of debugging, ease of expanding, ease of learning/understanding, ease of reasoning about after having learned it, and so on, even when the final output is the same. <opinion> My issue isn't that the end-result is different (it's not), but rather that one method actually has more cons than I can justify to myself, without any real gains, and makes it a little harder to expand the architecture in certain ways, as development continues. In the thread I linked, someone asked a similar question and I gave some concrete examples, but to summarize a two key points: Forcing a consistent interface on unrelated classes puts unnecessary constraints on how the individual interfaces are designed and used. Hodgeman gave one example, and I gave the Uncharted 2 example. For me personally, when I am putting constraints on an interface via inheritance, I find it hard to notice when the class isn't a suitable fit, because I've already made the assumption that it should be inherited - so it's hard to catch myself at it, hence my pro-active defense against it - i.e. I better justify it to myself in advance, because if I assume it is justifiable without cause, I have trouble remembering to question the justifications afterward. Manually calling the systems makes their execution order clear and explicit. It's slightly easier to debug and optimize (including easier to parallelize). And being more straightforward, it's much easier to comprehend and reason about, helping other coders - or yourself in the future - understand what's going on. It's also less code. You don't gain anything of real substance from making them inherit, but you do lose some real benefits. Others absolutely disagree with me. I had a link to a thread somewhere giving an alternative view, though I can't place my hand on the link. I should also clarify that there are absolutely use-cases for components and component systems where it *does* make sense for the components to inherit from a base class. But at the level of abstraction we are talking about here, where the ECS is containing things as unrelated as Graphics and Physics, I've never been convinced that the actual benefits sacrificed on that particular altar of abstraction gain any benefit worth the cost. =) </opinion> Yeah, I'd put them in separate containers. Entities would likely be in a vector, possibly with an unordered_map to redirect EntityID's to the vector's elements, if required. For blocks, I'd start off with a 3D array of chunks with each chunk being a 3D array of blocks, and only do something cleverer if needed. For example, subdividing the world into 16x16x16 chunks of blocks, to cull or stream them quicker. By "3D array", I actually mean a regular 1D array (std::vector or std::array) to you index into as if it were 3D: arraySize = (width * height * depth); arrayIndex = (x) + (y * width) + (z * height * width); //Usually tossed into a convience function.
  5. Trackbar problem

    If absolute pos is the pos within the trackbar, e.g. 15 pixels out of 100 pixels wide, then if you do (AbsolutePos/Width), that'd be 15/100 which is 0.15f (meaning 15% of the way through). float RelativePos = (AbsolutePos/Width); I'm not sure what MaxVal is supposed to be doing though, so I may have misunderstood your question.
  6. C++ Need some help with the Entity Component System

    There are many different architectures people call "ECS", because it's very hyped and popular right now, few people know why they need it, and many implementations of it are terrible. It's not one design pattern, but a buzzword that acts as an umbrella for one or two designs that I personally think are nice, and a dozen more designs that are just terrible. Some really intelligent developers go a step further and say all ECS architectures are terrible. =) As TheChubu mentioned, in some ECS architectures, components *only* hold data, and Systems contain the logic that transforms that data. Other ECS systems, that I wouldn't even call "ECS", put the logic in the components and lose half the reason why ECS exists in the first place. Yes, that sounds terrible. I don't even want components of different type put in an array together - it doesn't seem worth it to me without a compelling reason (here's me explaining why I dislike it). I wouldn't want actions like 'IAttack' to be components either, nor would I have 'Player' responsible for drawing the GUI (depending on what you mean by GUI - if it's a name or healthbar over his head, I would - but if it's a HUD or menu widgets, I wouldn't). I probably wouldn't make Blocks into entities - the blocks need to be highly optimized since you'll have huge numbers of them, and it'd be better to implement something special just for them. In Minecraft-like games, there's really only a few different types of objects: Blocks - As mentioned, special care needs to be given to these because of how many there are. Special "blocks": Wall switches (activated manually) Floor switches (activated on-touch) Doors Arrow trap, spike floor trap, spike floor, etc... Moving platforms / elevators Monsters Players Projectiles (arrows, fireballs, etc...) Items in the world (separate concept from the items in your inventory). Essentially, I'd make two different classes: Block (for all regular blocks - it'd probably cover 99% of all your objects) Entity 'Entity' would handle all the other cases: special blocks, in-world items, projectiles (unless there are alot of projectiles - inwhich case, handle it specially), and monsters and players. They all share more in common than they don't: Solid: Monsters, players, most special blocks (any that aren't solid, just have a "bool solid = false" or a empty bounding box) Does stuff on touch: Monsters, projectiles, floor switches, items in world. Does stuff on hit: Monsters, projectiles, wall switches, special blocks, etc... Visible: All (any that aren't, just have a "bool invisible" or an empty 3D model) Has health: All? (indestructible entities, if any could just be given a bajillion health). I don't think components are needed here. Instead I'd change their behavior mostly by passing in parameters, including functors. Or if really needed, derive from a base class - or just implement specific behavior as abstract classes, contained by Entity. Sure, this will all work perfectly fine in a component system (Solid, Visible, Touchable, Hitable), but component systems cost alot more code complexity, so if I was to pay for that complexity, I'd want to be sure it is actually worth the cost of a full ECS architecture.
  7. 100 tiny games, ideas needed

    This recent thread may interest you. Especially JBAdam's link, which is a good source of ideas.
  8. Just to clarify, since I kinda glossed over that earlier - in my mindset, components are almost pure data (albeit sometimes with minor functions), and *data* doesn't have dependencies, *code* does. A system can have dependency on more than one component. (I count functors/function-pointers and scripts as pure data until executed - the components can store those for systems to execute) If a *system* requires more than one component, you can pass them both in to that system. For example, let's say you had a Transform component, containing position/rotation/etc... And you had a Collision component, containing a bounding box relative to Transform, and a Animation component that is drawn at Transform's position. There is no "Transform" system**. But PhysicsSystem can be handed the Collision comp and Transform comp, and GraphicSystem can be handed the Animation comp and the Transform comp. **Depending on the needs of your game, there might be a transform system, especially if there are parent-child relative transforms. Though that might be done by a simple function, e.g. "ResolveFinalTransforms(&transformComponents);", and not need an entire "system" class. In the ECS mindset I subscribe to, Entity is just a concept, identified by an EntityID, systems operate on components en-bulk, and so you'd pass in entire arrays of components to the systems that need that type of component. It'd look roughly something like this: //Systems that only need to read a specific component type (e.g. GraphicSystem's need of Transform), can take a const reference to that array. //This is benenficial for debugging, ofcourse, but also for paralization, if actually needed. //Some systems may have private internal arrays of components mapped to IDs, for bookkeeping and optimizations and such. PhysicsSystem physicsSystem(&transformComponents, &collisionComponents, staticWorldGeometry /* or whatever other components or non-component stuff this system needs */); GraphicSystem graphicSystem(&transformComponents, &animationComponents, &particleComponents, &textureCache, &shaders, &etc...); This seems like a very different architecture then what you are doing, and is alot of boilerplate for benefits most games don't need. Simple entities and composition (and possibly inheritance) is much superior in most cases.
  9. Some googling turned up the pragmas "push_macro"/"pop_macro", which is compatible with Visual Studio, GCC, and Clang. This means you can do this: //=========================================== #define new static_assert(false, "'new' is not available"); #pragma push_macro("new") #undef new template<typename Type, typename ...Args> void priv_PlacementNew(Type *ptr, Args&& ...args) { new (ptr) Type(std::forward<Args>(args)...); } #pragma pop_macro("new") //=========================================== Here's the Ideone test, which works how I think you are asking. (or you can push_macro/undef/pop_macro manually each time you want to use placement new) In practice, you'll want to define 'new' via a compiler parameter, or it won't cover your entire project. Ofcourse, in real true practice, there's a limit to how far you should go to bubblewrap things to prevent programmers from shooting themselves, and I personally think this crosses that limit.
  10. Yea, I definitely misread it. I thought he was asking for a way to disable new for most of the code, but still make it available for his internal classes, so I was suggesting disabling and reimplementing under a new name. However, he was asking for a way to disable new, but keep *placement* new.
  11. [Edit:] Oops, I misread your original statement about needing *placement* new, so this post doesn't actually help you. new and delete have pretty simple implementations (based off of malloc() and free(), but with constructor/destructor calls and a few other niceties). You could grab an implementation off the web, maybe even your own compiler's copy if the licensing permits, and give them different function names (e.g. "MyDeleteFunc()"). I just tossed this together and it compiled and ran fine, though I may have made a mistake somewhere: (feel free to take it as your own, though at your own risk =P) Usage: MyClass *myClass = Memory::Allocate<MyClass>("Hello", 357); Memory::Deallocate(myClass); Here's where I tested it. When some people reimplement new(), they also add things like leak detection and other features.
  12. That's one of the popular ways to do components that everyone seems to do, but no one has sufficiently justified why - at least to my arbitrary standard. =) (the only time I like the general idea of getting components from an entity is when scripting, and in that situation, I'd use a proxy class to act as an interface to the concept of "entity", since in the DOD-styles of ECS that I prefer, entities are a concept, not a class, existing mostly just as an ID) It's often over-abstraction, IMO. First, one has to ask, who should own components? If the entity does, I suggest you are (likely) just doing composition disguised as ECS, not really ECS (though the term isn't standardized enough to say definitively what is ""true"" ECS). Composition is perfectly fine and often preferable! Imagine you had something like this: struct Entity { //Variables common to all entities: int ID; std::string name; var whatever; //"Components" that not all entities have - nullptr if this instance doesn't have that component. MoveComp *move = nullptr; VisualComp *visual = nullptr; CollisionComp *move = nullptr; }; //Check if a component exists, and then use that component. if(myEntity.move) myEntity.move->FollowPath(); If your more complex code doesn't give you anything beneficial over this much simpler method, why use the more complex version? Even that above example is move convoluted than needed, as you can just give all entities a visual component, and set a bool to "invisible", and similar for many other components. I question how many times people's *actual* game needs require invisible entities anyway. Not theoretical "maybe in the future it'd be cool to have ghost enemies" (which you'd probably want to still be visible, just translucent anyway!). In my post above, I've linked to two posts I've written describing some of the habits I think are signs of potentially bad design - what some programmers call a "code smell" - i.e. it smells like something is likely bad, so your guard should be up. When it comes to ECS, because I've seen it abused so much, entity.GetComponent<Move>() is one of those smells to me. I don't like my Systems or Components to be polymorphic or suffer from CRTP-itis. =) (sometimes there are justifiable reasons for doing so - most cases I've seen just add abstraction for abstraction's sake, and not for actual benefit. Likewise, CRTP is useful in some cases, but is abused more often than not in ECS architectures) A Graphic system isn't a physics system, nor should they be forced into the same interface. A graphic component and a physics component have virtually nothing in common other than the fact that they're both components. They don't need to be stored the same way, nor should they be mandated to have the same interface, unless the project genuinely requires it. Unless your goal is to build **an ECS architecture**, you should probably just use composition in this case, and derive from Entity if the game requires it. I'm a *fan* of ECS architectures, but my current projects don't use them because not every architecture fits every project, and in many cases they are the wrong tool for the job. If you still want to make an ECS architecture (instead of actually making games =P), then I'd suggest writing out what *benefits* you hope to get out of it, because ECS adds complexity (not difficulty, just code-bloat complexity) in trade for specific benefits that likely don't line up with what you and your project actually require. What I'm saying is, different architectures have costs (code bloat, debug costs, development time, bad abstraction can increase mental reasoning costs, etc...), and offer something in trade for those costs, and what they offer in trade may not benefit your project.
  13. What am I not understanding about programming?

    I fully get that. Function-level code design, class-level code-design, system-level code-design, and whole-project code-design, are different fields of knowledge. The higher up you go in scope (function -> class -> system -> project), the fewer *quality* resources I've found explaining good practices clearly. Essentially, for lack of good resources, you have to just learn by doing. I've read a couple books and multiple internet tutorials on "building a complete game engine", that just break down the individual pieces and then never tell you how they are all connected together. The books just skipped it, and the tutorials never get finished. =P The only solution I've found is, well, writing more code, completing projects, learning from my mistakes, and asking questions. But it's even hard to ask questions, because it's hard to frame the questions clearly when you get to larger scopes, and it's not like people have the time to go through hundreds of thousands of lines of code understanding my project's architecture to tell me how I should improve the architecture. I think the difficulty is in communicating/articulating abstract concepts at that level, perhaps from a lack of terminology. For example, at the class level we can talk using Design Patterns, and system levels are small enough that we can use our classes as building blocks for discussion, and a few Design Patterns describe things at that level as well (ECS, MVC, and a few other patterns), but the project-level code doesn't seem to be as standardized in terminology and design. But anyway, just wanted to let you know it's certainly not your logic skills, but a lack of code architecture experience and a lack of community-pooled knowledge targeting this area.
  14. These are slightly off-topic from what you are currently reasoning over, but I've written some of my thoughts on common ECS design pitfalls here and here, and you may find them worth a read. I haven't mentally resolved every aspect of how I would design an ECS, but I've come to a few conclusions about how I wouldn't design them, basically by observing what I think others do wrong. Again, I should stress that I'm no expert, I just play one on TV.
  15. I'd default to making as few things components as possible, and prefer passing parameters to the components. Think of it like this - what does a visual system need from its component to function properly? If nearly every visible entity requires an animation, then the entities that have that visual component should have the animation passed into that component. (I'm using "visual" as a concept, not a system name). Anything that can be parameterized probably should be, though I'm sure I could think of exceptions. Most programmers recognize that Composition is more often preferred over Inheritance. I think when it comes to Entity Component Systems (ECS), composition and parameterization of components is more often preferred over more components. Don't forget that you can make some components depend on the existence and data of other components - pass in a reference or ID as a parameter. Why, for example, are Position and Velocity part of two different components? It's like separating every variable of a class into its own component - but for what benefit? Even walls can have velocities - just set the velocity to (0,0). And what about size and collision rects? I'd have them as part of the same component. If an object doesn't collide, for example, I'd just set a bool or set the collision rect to (0,0,0,0). Think of components as structs, not solo variables. They are bundles of variables needed for the System to do its thing. Sometimes a system needs the data separated in more than one component, but they shouldn't be unless actual concrete benefit is gained by their separation (and theoretical future benefit doesn't cut it). I'm not familiar with your particular code, but another thing that seems odd is that there is a Graphics system and an Animation system. What does the Animation system do? Disclaimer: I've read buttloads about ECS systems, but don't have any practice/experience with them, as none of my projects have needed them yet. I intend to move to ECS when I move to 3D games, but don't find them necessary for any of the 2D projects I've worked on.