Jump to content
  • Advertisement

SeanMiddleditch

Member
  • Content count

    1498
  • Joined

  • Last visited

Community Reputation

17569 Excellent

About SeanMiddleditch

  • Rank
    Crossbones+

Personal Information

Social

  • Twitter
    stmiddleditch
  • Github
    seanmiddleditch

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. SeanMiddleditch

    SpeedTree 8 for Lumberyard Now Available

    SpeedTree. Lumberyard. Heh.
  2. SeanMiddleditch

    Game Engine Containers - handle_map

        You don't need them for constant-time insertions or removals.   I 100% promise you that you can do everything you're trying to do, with less code, less complexity, and less memory usage, keeping only a single level of indirection for lookup. I highly suggest you read the article I linked; it's pretty close to what we use. :)   One vector to store the objects, one vector for indirections, embedding generation data in the indirection entry, and also embedding the free-list into the empty indirection slots with no space overhead.
  3. SeanMiddleditch

    Game Engine Containers - handle_map

    This design is a good deal more complicated than really necessary. This is mostly owning to the metadata concept. It should be done away with, IMO. For instance, you mention the type id to offer an "element of type safety" which is something you can get far better by using _actual types_, e.g. a strong enum:   enum class PlayerId : HandleMapId {}; enum class TextureId : HandleMapId {};   PlayerId player; TextureId texture; player = texture; // COMPILE ERROR   If you're concerned with supporting older versions of C++, the same is trivially accomplishable with tag types:   template <typename Tag> struct Id { ... };   struct PlayerIdTag; typedef Id<PlayerIdTag> PlayerId;   struct TextureIdTag; typedef Id<TextureIdTag> TextureId;   This resolves concerns with memory usage, too. You only need two arrays at most (and that includes the id free list), and those you can also allocate in a fused block if you must (though for many uses, using distinct block allocators is likely to be faster both for allocation and runtime usage).   It's a good article, but I don't think you've decently justified why your more complex version is better than the industry standard approaches (which are also decently well-documented, e.g. [url]http://bitsquid.blogspot.com/2011/09/managing-decoupling-part-4-id-lookup.html[/url]).
  4. SeanMiddleditch

    Static, zero-overhead (probably) PIMPL in C++

    Yeah, I'm not a fan of this. This is the kind of code that programmers write thinking that they're being clever but are really just writing obtuse, error-prone code. If your big performance bottleneck worth solving is dynamic allocation of Pimpl classes, then either you're _massively_ overusing Pimpl, you're imagining performance bottlenecks without profiling first and are rushing off to find clever solutions to phantom problems, or you have written the most wonderfully efficient engine the world has ever seen so you're just out of more important issues to address. I confidently assume this case is one of the first two. Use your C++ prowess to solve real problems. :)
  5. SeanMiddleditch

    Action Lists: Simple, Flexible, Extendable AI

    Sounds like maybe your dog possibly read some of my old [url=https://docs.google.com/presentation/d/1kzxp8jfO3GvQsfWo3JHW2b44l9rC9g0jEDJzmU5I_No/edit?usp=sharing]Action! List[/url] slides... I like your dog. :)
  6. Please, no. You should _not_ be using so-called "smart" pointers 99% of the time. Smart pointers manage ownership and lifetimes. If you're not managing lifetimes, you should be using a good ol' raw pointer. Reference are also not just replacements for raw pointers, though certainly a lot of uses of raw pointers in old C-style code are better served by references. We're actually going through a round of replacing smart pointers with raw pointers in a lot of our engine code right now (the engine was originally written back when Boost smart pointers were the new hot thing, so far as I can tell, and it suffers for it). Smart pointer overuse is an anti-pattern. That said, I agree with most of the rest of what you said. I think this article (based on this sample) needs a thorough round of professional editing and code refinement before it's something I'd recommend for free, much less for money. My recommendation to start would be to avoid littering the article with actual code samples. First explain the concepts and reasonings, with pseudo-code where needed to illustrate points, and then provide a separate well-commented sample app to download and dissect. The people who need raw code want a complete sample, and the people who need to understand the "why" here don't need 50% of the space dedicated to boilerplate code, and the article as it stands serves neither demographic well. Krohm's points about layering are especially important, too. Yes, there's a reason to simplify abstractions for educational purposes, but I feel this article goes too far in that direction. It also doesn't really exemplify the important bits of structure of a good networking engine. The article's code needs at least a little more abstraction; that bloats the samples a bit, yes, but that feeds back into the need for separating the article's important content from the sample code. There's also a misdesign present in the idea that you'll have a "packet" for placing a building or whatnot at the game level. That's a high-level message; multiple messages should be communicated per packet. There's too much overhead per-packet to send one for each game-level message. Even things like keep-alive and whatnot should not be whole separate packets; just send a packet with no messages in it if all you want is to let the other side know that you're still there. You want to packet as much data into a single UDP packet as you can (and that's far less than 64k, btw, because of MTU sizes. Most UDP packets that are actually 64k in size will be dropped, even though that is technically a legal IP packet size. Transmission logic really should work hard to keep packets smaller. Of course, there's a trade-off in packet size between packet fragmentation with resulting packet loss and the the overhead in dispatching many packets vs fewer packets. Also rememeber that bandwidth is not free. For client-server games, bandwidth alone can cost a company hundreds of thousand of dollars per month if it's poorly utilized. Gameplay code doesn't want to have to deal with those complexities, though, so the low-level networking layer needs to intelligently deal with those complexities while abstracting them from the gameplay programmers.
  7. SeanMiddleditch

    Cache And How To Work For It

    Your compiler will never optimize the given example because it's illegal to do so. C mandates that compilers not move aggregate members around and also requires that the implementation provide consistent rules about padding and alignment and then always apply those (sans any non-standard extensions like #pragma pack). C++ does allow a limited form of aggregate member reordering only for members in different member access sections. No compiler I've ever seen takes advantage of this, though.
  8. Hello. Saw the name and just thought I'd say "hi". Caught a few of your talk from DigiPen on the Game Engine Architecture Club Channel on YouTube. Not to be mean to your classmates, public speaking isn't for everyone. You're really the only one I watched up there who pulled of a good presentation...not that their info was bad.
    1. SeanMiddleditch

      SeanMiddleditch

      Hi, Trevor. Thanks for the compliment; the speaking takes practice, and lots of it. Part of why I founded that club was to help people (like me!) get practice at giving talks.
  9. SeanMiddleditch

    Learn from Irrlicht the API mapping between OpenGL and Direct3D

    There's also the question of forward-compatibility. Which versions of OpenGL does Irrlicht support? Does it support GLES? Is it ready for D3D12/Mantle/Metal?
  10. SeanMiddleditch

    Implementing a Meta System in C++

    His code is following common idioms for C++-based reflection/binding libraries. I wouldn't change it like that. I might change it to take a signature instead of a varying argument list, though, e.g. OVERLOAD(lol, Test, float(float, float));
  11. SeanMiddleditch

    Pre-Visualization Is Important!

    Just to be clear, since I can interpret this article a couple ways: are you using "class" to mean literal, individual C++/Java class definitions, or are you meaning it in the context of broader modules or systems? I hope it's the latter.
  12. SeanMiddleditch

    The Pros and Cons of Going to College for Game Development/Design

    This is super important. It also illustrates a huge important aspect of choosing a school should you choose to go to one. There's a very real and huge benefit to a game school like DigiPen vs other more highly-advertise game education programs: location. DigiPen has advantages in being right next to Microsoft, Nintendo, Valve, Zombie, Wargaming, Epic, Uber, Z2, Pop Cap, 343, Bungie, Turn 10, 5th Cell, Monolith/WB, Runic, Sucker Punch/Sony, and many many others. I'm not saying "go to DigiPen" (I can easily make a very strong argument not to) but it's something to consider if you're looking at a game-oriented education; the relative worth of most other game-centric educations suffer greatly not because of the education quality itself (some are quite good) but because of the networking handicap they operate under by not being situated in a major area saturated with game companies.
  13. SeanMiddleditch

    How to Record High Quality Video of Your Game using a Slow Computer

    Jarmo's solution isn't flawed; it's just based on different trade offs. Recording state instead of input does have advantages. For one, it's resilient to minor changes in gameplay behavior. e.g, if you just record input but then a designer tweaks the player movement speed to be a meter/second faster then replaying the recorded input will produce a different result and likely a broken replay. Recording the states of the objects will ignore that kind of change. You can still get input-recording to be resilient (also record pertinent object configuration data; keep two copies of the data; etc.) but it's much harder and more fragile. Ultimately it comes down to what you want to do with replays. If the in-engine replay data is meant to be short-lived because your long-term replay data is a movie, input recording is IMO superior. If this is a replay system that you expect to support in-game playback a long time after the recording, a more stateful approach makes sense. One way to make state-based recording work better would be to ensure that you can also record events and replay any of their effects that does not modify object state. e.g., the PlaySound event. This way you get the robustness of state-based replays and all the information necessary to generate sounds, VFX, and so on. I don't believe that there's a good reason to need that kind of stability, though. For long-term replay storage, upload a movie to Twitch or the like. If you then only need short-term use of in-engine replays you can use input recording and get the other advantages it offers like its use for system tests and bug reports.
  • Advertisement
×

Important Information

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

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!