Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

  • Days Won


Oberon_Command last won the day on June 21

Oberon_Command had the most liked content!

Community Reputation

6266 Excellent

1 Follower

About Oberon_Command

Personal Information

  • Role
  • Interests

Recent Profile Visitors

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

  1. Oberon_Command

    OOP is dead, long live OOP

    I can think of at least a couple of arguments in favour of that attitude. Typically we want individual commits to source control to represent one bugfix or feature. The more stuff you put in a commit or changelist, the higher the likelyhood that your commit will break something and need to be reverted and, if that happens, the more work will be potentially unavailable to the client when your change is reverted. There's also that if you find two problems in the code while you're looking at a bug, and you fix both at the same moment, it becomes harder looking back through the code's version history to see what the actual problem was that caused the bug. When you're fixing a bug, I find it really helps to have a stable (even if flawed) codebase to test your fixes against. If you change one thing at a time, you get a better sense of what your change did than if you change a whole bunch of things all at once. Fixing stuff as you see it is all well and good, but if it isn't pathologically difficult to test and submit individual bugfixes, then bugfixes should be as separate from one another as possible. Easy branching in source control systems like git make this a lot nicer, but not everyone is using git. Structuring your code well can certainly help in all cases.
  2. You have the general idea, but no. Think about what memset does: The count parameter is already in bytes. 8bpp commonly means "8 bits per pixel", so that would be 1 byte per pixel. But what we're asking is for you to verify (or have your code deduce) the actual number of bytes per pixel on your texture. D3D itself should be able to tell you this somehow, if I'm not mistaken.
  3. Oberon_Command

    OOP is dead, long live OOP

    Well, in C++ in particular you'd want to avoid static functions in classes, as well, unless those functions needed access to the private fields of the class. There are a couple of reasons for that: Minimizing compile times. Having a free function doesn't inherently lead to better compile times, but it does give you the option of moving that function out into a different header from the class with a forward declaration of that class, which allows code that uses the functions to avoid including the class header. That means that when you change the class definition, fewer translation units will need to be recompiled. Promoting encapsulation. The more functionality is in free functions that use the public interface of a class, the less code you need to change when the class's private implementation does, at least in theory. In a lot of cases you can get it so that code depends on the free functions instead of the class itself. This also encourages one to focus a class's public interface on its state invariants, rather than putting significant amounts of behaviour in the class itself.
  4. Is D3D allowed to ignore that if the driver doesn't support 8-bit textures?
  5. Because it probably isn't. The pitch is not the width in pixels! It might be, if the hardware surface is one byte per pixel and there's no extra padding added to the end of each row of pixels. But that seems unlikely to me, given that you're getting this crash. What is the width of the texture, in pixels? Is it 64, or 128?
  6. What is the actual size of the texture? How many bits per pixel? And how do you know?
  7. Oberon_Command

    OOP is dead, long live OOP

    Ah, I can empathize there. I don't think that's Hodgman's intent, at all - it seems to me that he's more claiming that the "OOP" Aras was referring to is a strawman, not saying that SOLID-C is the one true way to code. Hmmm, I've been using both of those words differently. To me a principle is a kind of "normative axiom", not something that has a truth value. The SRP isn't a thing that's "true" so much as it's an idea that we choose to follow because we believe it will yield better software; more generally, principles are norms that we follow in order to promote our values. I will happily ignore a principle if I find I'm in a case where the principle doesn't apply or doesn't advance my values. If I find that a principle ceases to advance my values in most cases- or never did so in the first place - then I tend to discard it. To me what makes a principle "dogma" is how it is applied, not an inherent characteristic of the principle. "Dogma" refers to principles that are applied unquestioningly and universally, oftentimes without really understanding why one applies them in a particular circumstance. I think that covers the case where an "authority" impose a principle on someone who doesn't understand the principle, too. SOLID-C can certainly be applied dogmatically - because any principle can be.
  8. Oberon_Command

    OOP is dead, long live OOP

    I think the term you're looking for is "leaky abstraction." And I would point out that even if abstractions are ultimately leaky in some way, that doesn't mean we shouldn't have them. They're useful. I am of the opinion that the search for advice to apply unquestioningly is fundamentally misguided; we shouldn't do anything in software unquestioningly, so I struggle to follow your point here. There's a reason we call them principles and not laws or dogma. Design principles are not cudgels to bash over the heads of the unfaithful, they're guidelines that suggest what a good course of action might be when trying to solve a problem. Frankly, I struggle to imagine any kind of design advice that works always, without exceptions, and provably so, because there's always an outlier case where the best course of action is something really weird. Even a singleton, as icky as singletons are, is sometimes the right choice to solve a problem where things are un-fixably un-ideal. That doesn't mean we shouldn't have principles for the common case.
  9. Oberon_Command

    OOP is dead, long live OOP

    It sounds to me like we're largely in agreement here. Sort your data according to its behaviour! You can even use separate pools for the same "object" (as the user would see it) that's in a different state. Eg. from the same project as the snippet I posted earlier, instead of having a variable on my weapon class that indicates whether it is lying on the ground, being held by a character, or has just been dropped, and instead of representing that with a set of "weapon state" classes with virtual update functions, my "weapon pool" stores three vectors of weapons: std::vector<WeaponDatum> FreeWeapons; std::vector<WeaponDatum> BoundWeapons; std::vector<WeaponDatum> DroppedWeapons; Then it applies different logic to each one; free weapons just idle and wait for something to pick them up, bound weapons mimic their owner's animations, and dropped weapons start playing the idle animation, then enter the free state. Switching states means moving a weapon from one "sub-pool" to another one. I haven't yet, but there are some further optimization opportunities here - the "free" (ie. not being held or dropped) weapons don't need to store a reference to the character that owns them, for instance.
  10. Oberon_Command

    OOP is dead, long live OOP

    That's the other thing - notice that in my sample I'm passing the services/pools that each method needs directly to each method. The dependencies are injected to the method that actually needs them; the individual services and pools don't store them! This makes dependency reasoning really straightforward at the expense of having bigger function signatures (which, oddly enough, has been encouraging me to write updaters that have fewer dependencies). Sometimes I wish the mainstream engines gave me control over their main loops so I could do stuff like this.
  11. Oberon_Command

    OOP is dead, long live OOP

    In my mind, if you're going to have a bunch of pools of distinctly-behaving objects, anyway, there's not a whole lot of point to making that Update method virtual, nor much point in calling it "Update." Just name it according to what it does - "MoveBullets" - and put a call to pool.MoveBullets at the appropriate place in the main loop. That way you can see in the code what each pool is doing when. Here's a few lines illustrating the principle from a side project I'm working on: combat.resolve_attacks(collision, status); hazards.apply_status_effects(status); characters.update_sprite_data(sprites); sprites.update_animations(dt); particles.update_all_particles(dt); projectiles.update_all_projectiles(dt); projectiles.resolve_collision(status, collision); Look how simple this is! I can control the order in which each of the steps happen. No PreUpdate or PostUpdate or deferred update queues. All I need to do to work out when something happens is look at my main loop code to see where it happens. If I had a "virtual void Update" thing going on this code snippet would be a bit shorter (and this is not the complete function!), but tracing execution flow and debugging would be a lot harder. The compiler could probably inline some of these shorter updates, too. Sometimes simple declarative-looking logic is nicer than a 6 line loop.
  12. Attach the debugger and put a breakpoint at the line with the memset. What are the contents of sRect?
  13. Oberon_Command

    OOP is dead, long live OOP

    Depends on your definition of "reusable." As a gameplay programmer, I find the important kind of reusability is being reusable in multiple situations in the same program, not reusable across projects. Concerns like rendering, audio, and animation (ie. "engine code") are a different story. The reusable parts in the examples we're talking about would be the "components," in any case, not the entities. This would be true regardless of whether the composition was compile-time or run-time, or whether we were reusing them across parts of a game or across different games. I would not expect games that aren't sequels, reskins, or mods to share a whole lot of gameplay code. Certainly not enough that reusing entity archetypes across projects would be of much interest to me, never mind a driving requirement of my gameplay architecture. Different gameplay begets different code.
  14. Oberon_Command

    OOP is dead, long live OOP

    You're presupposing that it shouldn't be. I would say that having runtime composability as a default is overengineering as long as you're writing a game (not an engine). If you need runtime composability for something, you can introduce it in small, controlled amounts where it is appropriate to solve the problems at hand, and you can do it in better ways than "entities with pointers to components". An approach I've found works fairly well is to divide entities up into types based on which components I know they'll have at compile time, then use separate "services" (in ECS terminology, "component arrays" coupled with "systems") to decorate instances of those specific entity types with extra state they need at runtime. If taken to extremes, this can result in something that looks like ECS, but was designed with a different approach than "throw all the components for all the entities ever in their own arrays."
  15. Oberon_Command

    OOP is dead, long live OOP

    Maybe we just need a snappy new name. Natural languages being what they are, the meanings of words tend to evolve; if enough people agree that OO refers to what we're all calling "bad OO" in this thread, then that's what "OO" means, regardless of what we think of the matter.
  • Advertisement

Important Information

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

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!