Our new Indie Games subforum is now open for business in G&T. Go and check it out, you might land a code for a free game. If you're developing an indie game and want to post about it, follow these directions. If you don't, he'll break your legs! Hahaha! Seriously though.
Our rules have been updated and given their own forum. Go and look at them! They are nice, and there may be new ones that you didn't know about! Hooray for rules! Hooray for The System! Hooray for Conforming!

Game Development Omni-thread [Unity, XNA, UDK, etc]

DelzhandDelzhand motivatedbattle programmerRegistered User regular
edited August 2012 in Games and Technology
Welcome to the Game Development Omni-thread, formerly the XNA thread! Any discussion of game programming, development, or (within reason) asset creation can go here. Up until page 55, you'll pretty much just see XNA discussion, so if you want to talk about something else, don't feel compelled to read the entire thread.

Original OP is in the spoiler.
Spoiler:

Delzhand on
9KKPPQw.png
«13456776

Posts

  • Dodge AspenDodge Aspen Registered User regular
    edited April 2010
    What's up with all these Old Spice games showing up this week?

    /=S=/
    Animal Crossing: New Leaf
    3DS - 3797-6074-8327

  • templewulftemplewulf Registered User regular
    edited April 2010
    What's up with all these Old Spice games showing up this week?

    Because this game is the game you wish your game could smell like.

    Friend me: Twitter | Google+
    Invite me: XBox Live | PS3 | Steam
    Link to me: Number Sorter | Achievement Generator
  • savooipeerdsavooipeerd Registered User
    edited April 2010
    What's up with all these Old Spice games showing up this week?

    Microsoft has a contest for XNA games called Dream Build Play, and the last iteration of it had an additional contest sponsored by Old Spice. Now that the results are in the people that didn't win are submitting their games to XBLIG because hey, why not?

    [SIGPIC][/SIGPIC]
  • DelzhandDelzhand motivated battle programmerRegistered User regular
    edited April 2010
    templewulf wrote: »
    What's up with all these Old Spice games showing up this week?

    Because this game is the game you wish your game could smell like.

    Look at your game. Now look at mine. Look at yours, back to mine. Your game couldn't be mine. But it could smell like mine.

    I'm on a horse

    9KKPPQw.png
  • templewulftemplewulf Registered User regular
    edited April 2010
    Delzhand wrote: »
    templewulf wrote: »
    Good OP! Also, "psych" != "sike".

    I'm in the middle of a sad, graphicless platformer right now, but I've been thinking of making a TRPG for about 10 years as well! How did you deal with displaying the tiles? Are they each a discrete unit, or did you just overlay a grid on top of a piece of terrain?

    I have a terrain class that has width, height, scale, and a list of tile objects. Each tile object has four variables for corner heights, a bool for whether the tile is walkable (which may be expanded to an enum of ground types like grass/carpet/water/inaccessible), and a bool that determines which way the triangle hypotenuses go through the square when drawn. This is all stored in XML. When the gameplay screen load, it converts each tile to a set of vertices (including automatically building vertical walls, which I will probably avoid since I don't know how to texture them), indices, and texture coordinates. When there is a range of selectable tiles, those tiles in the list are used to create another set of vertex data and drawn after the terrain with an vertical offset of .5f.
    That's about what I'm doing except for a.) the bolded portion; why would that be important? and b.) I have no textures for my tiles. Do you just index into an old-schooly spritemap for your tile texture? Do you just slice up larger-than-one-tile items into multiple textures?

    Friend me: Twitter | Google+
    Invite me: XBox Live | PS3 | Steam
    Link to me: Number Sorter | Achievement Generator
  • ImperfectImperfect Registered User regular
    edited April 2010
    I really want to get back into playing around with XNA - Christ, it's what I bought Windows 7 FOR.

    I'm still a little flummoxed though by how to properly organize things. When I get home (if I remember), I'll dig up my sources and see if I can identify some specific questions I had to pose to all you more practiced programmers.

  • StargliderStarglider Registered User regular
    edited April 2010
    templewulf wrote: »
    Delzhand wrote: »
    a bool that determines which way the triangle hypotenuses go through the square when drawn.
    That's about what I'm doing except for a.) the bolded portion; why would that be important?

    Changing the orientation of the diagonal based on the vertex heights can produce smoother looking terrain. Personally I use a grid of equilateral triangles instead of squares, because this further reduces visual artefacts. Neither of these are really necessary for an RPG style game that isn't going for graphical realism.

  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    So...is this only for XNA games? Or can I talk about my awesome indie game I'm making using the OGRE 3D engine?

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • ImperfectImperfect Registered User regular
    edited April 2010
    GnomeTank wrote: »
    So...is this only for XNA games? Or can I talk about my awesome indie game I'm making using the OGRE 3D engine?

    GET OUT SCUM

    But srsly, we all love games here. While OGRE 3D may be off-topic a bit, I don't think anyone will flame you so long as you do not completely derail the thread in a non-fun, non-intuitive way.

    My own plan is to maybe make something using XNA, then build Steamworks into it and put it up on Steam. Steam generally seems to be the better distribution portal, offering neat promotions, even for indie titles.

  • DelzhandDelzhand motivated battle programmerRegistered User regular
    edited April 2010
    Starglider wrote: »
    templewulf wrote: »
    Delzhand wrote: »
    a bool that determines which way the triangle hypotenuses go through the square when drawn.
    That's about what I'm doing except for a.) the bolded portion; why would that be important?

    Changing the orientation of the diagonal based on the vertex heights can produce smoother looking terrain. Personally I use a grid of equilateral triangles instead of squares, because this further reduces visual artefacts. Neither of these are really necessary for an RPG style game that isn't going for graphical realism.

    Close - it's not about smoothness, but uniformity. Imagine a square laying flat on the ground. If you raise a single corner, one of two things will happen - if the corner touches the shared hypotenuse of the triangles that make up the square, you'll have a downward facing "fold". Otherwise, you'll have an upwards facing "fold" (in this case, you still have a whole triangle flat on the ground.

    Is that clear at all?

    Edit:
    tiles.jpg

    9KKPPQw.png
  • tastydonutstastydonuts Registered User regular
    edited April 2010
    What's up with all these Old Spice games showing up this week?

    Microsoft has a contest for XNA games called Dream Build Play, and the last iteration of it had an additional contest sponsored by Old Spice. Now that the results are in the people that didn't win are submitting their games to XBLIG because hey, why not?

    ah. that makes sense.

    I'm thinking about scrapping my project (again) because of how much I seem to be developing a genuine hatred of 3d animation, and the horrible cycle of the only way you can get better at it is to keep doing it to get better at it but it's just evil. I imagine I will repeat this cycle again a few more times before I get to the point of putting a game out there, or just go "screw it" and charge forward, horrible animations and all.

    "a good leader can make an okay group great..."
  • IzzimachIzzimach Storm-Wizard Registered User regular
    edited April 2010
    I imagine I will repeat this cycle again a few more times before I get to the point of putting a game out there, or just go "screw it" and charge forward, horrible animations and all.

    Just go "screw it" dude. Have you seen some of the available games? Some of them are terrible, terrible abominations, even for 80 points. Plus, rough animation and graphics isn't a death sentence; games like Johnny Platform's Biscuit Romp are still pretty good even if they look like they're done with MS Paint.

  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    Nice spam bot.

    Anyway, one of my big complaints with using C# for game development (and mind you, I love, love, love C#), is the lack of multiple inheritance, which makes doing a truly component based game architecture difficult, without jumping through some odd hips. This is one of those edge cases where true multiple inheritance is a god send.

    This is one of the primary reasons I've shied away from XNA. If you look at my C++ engine that uses OGRE, my game objects are built as composites from many smaller, specialized, working parts.

    So every object in the game sub-classes from Object, which provides some basic things all objects need (tags, id's, etc). But beyond Object, the game objects composite themselves. For instance, my Actor class is a sub-class of Object, but also mixes in (via multiple inheritance) the MeshRenderable and Scriptable components. What they do is pretty self evident by their names.

    You could do this in C# using interfaces and some hackney eyed default-implementation scheme. You could also try and do it with a single inheritance tree, but you'd end up with a ton of bases classes that were only base classes because you needed that particular combination of mixin components in the inheritance chain.

    How are you guys handling this in your XNA engines? Or are you not even trying to architect your game engines at that level? I write commercial software for a living, so I don't tend to "hack" anything together, I tend to design things right "the first time" and leave myself a maintainable, extensible, code base for later.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • NamrokNamrok Herndon, VARegistered User regular
    edited April 2010
    GnomeTank wrote: »
    Multiple Inheritance rant

    Honestly, I've never run into a situation where I felt I needed multiple inheritance. Most of the examples I've seen appeared contrived to me. Then again, I haven't used C++ in a while and have completely internalized the design perspective of C#. A friend of mine who codes mostly in C/C++ also seemed troubled that C# didn't have multiple inheritance, and seemed to dislike how if you attempt the same thing using interfaces, you end up with a lot of code duplication. But in actual use, I don't think it's come up.

    I can only compare it to when I switch from Java to C# and vice versa. When I'm writing Java, it goes just fine. But Java does not support passing by reference, where as C# does. So what I find happening is that I will do lots of it in C#, but the thought never even occurs to me in Java. It's only when I try to translate one codebase to another that I even realized the difference in my coding habits with respect to the language I'm in.

  • ImperfectImperfect Registered User regular
    edited April 2010
    Ugh, you described largely my problem with XNA, actually. Previous to this, I was working on a Dwarf-Fortress-alike But With Zombies, and the lack of really extensible classes was driving me crazy. Plus, try to work out how to do really dynamic object instantiation in C# without losing your cheese.

    I kind of dread going back there. I could do that shit in, say, PHP (not an especially concise language) in one line. In C#, it's like, four functions spread out amongst three classes and WTF I AM JUST TRYING TO LOAD A TREE BASED ON AN INI FILE.

  • DelzhandDelzhand motivated battle programmerRegistered User regular
    edited April 2010
    What? I'm almost certain C# allows multiple inheritance. I know you can inherit from a class and several interfaces, at the very least.

    9KKPPQw.png
  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    Namrok wrote: »
    GnomeTank wrote: »
    Multiple Inheritance rant

    Honestly, I've never run into a situation where I felt I needed multiple inheritance. Most of the examples I've seen appeared contrived to me. Then again, I haven't used C++ in a while and have completely internalized the design perspective of C#. A friend of mine who codes mostly in C/C++ also seemed troubled that C# didn't have multiple inheritance, and seemed to dislike how if you attempt the same thing using interfaces, you end up with a lot of code duplication. But in actual use, I don't think it's come up.

    I can only compare it to when I switch from Java to C# and vice versa. When I'm writing Java, it goes just fine. But Java does not support passing by reference, where as C# does. So what I find happening is that I will do lots of it in C#, but the thought never even occurs to me in Java. It's only when I try to translate one codebase to another that I even realized the difference in my coding habits with respect to the language I'm in.

    What I wrote wasn't a 'rant', and my example is not contrived at all. Notice how I am building object in a composite fashion. This is hard to do without multiple inheritance. I also noted that it's an edge case, and in many cases multiple inheritance isn't needed (I don't find myself ever wanting it at work, where I write C# for a living).

    But, this isn't a programming zealotry thread. I was simply asking how people were architecting their game engines with XNA, using how I use multiple inheritance in C++ as a backdrop for the discussion.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    Delzhand wrote: »
    What? I'm almost certain C# allows multiple inheritance. I know you can inherit from a class and several interfaces, at the very least.

    Nein sir. It supports multiple interface implementation, it does not support true multiple implementation inheritance.

    A C# class can implement multiple interfaces, but cannot inherit multiple classes.

    e: Bah.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • NamrokNamrok Herndon, VARegistered User regular
    edited April 2010
    GnomeTank wrote: »
    Namrok wrote: »
    GnomeTank wrote: »
    Multiple Inheritance rant

    Honestly, I've never run into a situation where I felt I needed multiple inheritance. Most of the examples I've seen appeared contrived to me. Then again, I haven't used C++ in a while and have completely internalized the design perspective of C#. A friend of mine who codes mostly in C/C++ also seemed troubled that C# didn't have multiple inheritance, and seemed to dislike how if you attempt the same thing using interfaces, you end up with a lot of code duplication. But in actual use, I don't think it's come up.

    I can only compare it to when I switch from Java to C# and vice versa. When I'm writing Java, it goes just fine. But Java does not support passing by reference, where as C# does. So what I find happening is that I will do lots of it in C#, but the thought never even occurs to me in Java. It's only when I try to translate one codebase to another that I even realized the difference in my coding habits with respect to the language I'm in.

    What I wrote wasn't a 'rant', and my example is not contrived at all. Notice how I am building object in a composite fashion. This is hard to do without multiple inheritance. I also noted that it's an edge case, and in many cases multiple inheritance isn't needed (I don't find myself ever wanting it at work, where I write C# for a living).

    But, this isn't a programming zealotry thread. I was simply asking how people were architecting their game engines with XNA, using how I use multiple inheritance in C++ as a backdrop for the discussion.

    Sorry, I didn't mean to insult by calling it a rant, I just didn't want to quote a large post.

    Mostly I just don't think in terms of class heirarchies which converge instead of branch. It not being an option, I haven't even thought of what to do instead, because I never do that in the first place.

    I do know that I have multiple subsystems in my game class library already. Anything that collides with something else needs to support ICollidable so my collision event service can do what it needs to do. Anything that accepts user input needs to support IControllable so that my control hub knows how to route controls around. My model animation system has IMeshAnimation interfaces and so on (since I have keyframe animation systems and procedural animation systems).

    In theory, I could make all those interfaces classes, and then multiple inheritance things together when a class needs all of them. But frankly, almost every time I implement one of those classes, I do it in a radically different way, save for getting and setter functions on my various ICamera implementation (Ortho, Perspective, etc). And if a class needs them all, I've done something wrong. Because once upon a time, I did that, and it was a horrible debugging clusterfuck of a disaster.

    Seriously, it was horrible, and the reason my first game never got close to finished.

  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    If you're in a situation where you're writing "vastly different implementations" per-object, you may be designing something wrong to begin with, or your original base was not general enough.

    I don't have the code here, so I can't post the header for any of my components, but basically if you look at Scriptable it contains all the pieces you need to wire up scripting for an object: storage for the script context, script context initialization, generic methods to call script functions, generic ways to load a script in to the context. These are operations that should, if things are designed correctly, be absolutely 100% the same for everyone object. If you do need to overload the default behavior, everything is marked virtual (except getters and setters, makes them too slow).

    The inheriting component object can then use those generic facilities to wire up scripting in an object specific way.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • IzzimachIzzimach Storm-Wizard Registered User regular
    edited April 2010
    Well, I just use interfaces and aggregation; I don't even have a "base class" which all game objects inherit from. I only have about six interfaces and I don't need every combination of them, so the combinatorial explosion isn't a problem in practice. If I used inheritance I would just be overriding methods, so my game wouldn't gain much from it I think.

    I'm curious as to what tutorials/samples people have folded into their game. I know I have the Skinned animation sample, particles sample, and deferred shading tutorial (from Catalin Zima). What other stuff? I think I saw the "safe area" component being used in someone's video (Delzhand's?).

  • NamrokNamrok Herndon, VARegistered User regular
    edited April 2010
    GnomeTank wrote: »
    If you're in a situation where you're writing "vastly different implementations" per-object, you may be designing something wrong to begin with, or your original base was not general enough.

    I don't have the code here, so I can't post the header for any of my components, but basically if you look at Scriptable it contains all the pieces you need to wire up scripting for an object: storage for the script context, script context initialization, generic methods to call script functions, generic ways to load a script in to the context. These are operations that should, if things are designed correctly, be absolutely 100% the same for everyone object. If you do need to overload the default behavior, everything is marked virtual (except getters and setters, makes them too slow).

    The inheriting component object can then use those generic facilities to wire up scripting in an object specific way.

    Well, the reason I'm using interfaces instead of inheritance is because they are vastly different implementations. There is zero commonality between how a keyframe animation system calculates its animation matrix and how a procedural one does.

  • gjaustingjaustin Registered User regular
    edited April 2010
    GnomeTank wrote: »
    If you're in a situation where you're writing "vastly different implementations" per-object, you may be designing something wrong to begin with, or your original base was not general enough.

    I don't have the code here, so I can't post the header for any of my components, but basically if you look at Scriptable it contains all the pieces you need to wire up scripting for an object: storage for the script context, script context initialization, generic methods to call script functions, generic ways to load a script in to the context. These are operations that should, if things are designed correctly, be absolutely 100% the same for everyone object. If you do need to overload the default behavior, everything is marked virtual (except getters and setters, makes them too slow).

    The inheriting component object can then use those generic facilities to wire up scripting in an object specific way.

    I think in all my years of programming I've run into a situation where I needed multiple inheritance once. And it only came up because I had to create an extension to an existing class hierarchy that I couldn't change.

    It sounds like you're designing much more monolithic classes than would work in C# and XNA. My design is split into more interchangeable parts.

    I make heavy use of utility classes and methods. So while your class might look like:
    public class Entity : Object, Scriptable
    {
       public void RunScript()
      {
          this.ExecuteScriptAction();
      }
    }
    

    Mine looks like:
    public class Entity : Object implements IScriptable
    {
       public void RunScript()
       {
           this.ScriptAction.Execute();
       }
    }
    


    So they work fundamentally the same way, but mine is less tied to a specific implementation of scripting, since I could always just instantiate a different class.

    Edit: To be fair, yours has the advantage of saving a few lines of code in the Deserialization method.

    Your belief is not required
  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    gjaustin wrote: »
    GnomeTank wrote: »
    If you're in a situation where you're writing "vastly different implementations" per-object, you may be designing something wrong to begin with, or your original base was not general enough.

    I don't have the code here, so I can't post the header for any of my components, but basically if you look at Scriptable it contains all the pieces you need to wire up scripting for an object: storage for the script context, script context initialization, generic methods to call script functions, generic ways to load a script in to the context. These are operations that should, if things are designed correctly, be absolutely 100% the same for everyone object. If you do need to overload the default behavior, everything is marked virtual (except getters and setters, makes them too slow).

    The inheriting component object can then use those generic facilities to wire up scripting in an object specific way.

    I think in all my years of programming I've run into a situation where I needed multiple inheritance once. And it only came up because I had to create an extension to an existing class hierarchy that I couldn't change.

    It sounds like you're designing much more monolithic classes than would work in C# and XNA. My design is split into more interchangeable parts.

    I make heavy use of utility classes and methods. So while your class might look like:
    public class Entity : Object, Scriptable
    {
       public void RunScript()
      {
          this.ExecuteScriptAction();
      }
    }
    

    Mine looks like:
    public class Entity : Object implements IScriptable
    {
       public void RunScript()
       {
           this.ScriptAction.Execute();
       }
    }
    


    So they work fundamentally the same way, but mine is less tied to a specific implementation of scripting, since I could always just instantiate a different class.

    Edit: To be fair, yours has the advantage of saving a few lines of code in the Deserialization method.

    The problem here is that you have to re-implement IScriptable every time you want to create a scriptable object. You don't get any advantages of having the most mundane, completely generic, parts of scripting be drop-and-drop mixable.

    I have several places this makes a lot of sense to me. For instance, my Actor class is Scriptable, so is my CombatEngine class. They share no other similarities, except they both need a place to store a scripting context, and both need a way to call methods inside that context. My Static class and my Actor class are both Scriptable, and both game Objects, but one is a AnimatedRenderable, the other is a MeshRenderable...because static object's don't need to render an animated mesh. Yes, I could have had an IAnimatedRenderable and an IMeshRenderable, but again, I would be stuck reimplementing the same interface twice on two separate objects.

    I could have an IScriptable interface, but then Actor and CombatEngine would both need to implement IScriptable (or would need to aggregate an object that does, which is by no means any cleaner). I need to do neither, I just need to publically inherit Scriptable. The illusion that using interface implementation and aggregation gives you the magic bullet so that you can easily change scripting engines is just that, an illusion. It's no easier, or more difficult, than for me to simply change the Scriptable base class implementation.

    Object composites are that edge case where multiple inheritance clearly outshines interface implementation and aggregation. This is why there are several C# engines out there trying to provide object composites that don't look horrible in the framework of interface implementation and aggregation.

    e: Also, by the very definition of my system, my classes are not monolithic even in the slightest. Scriptable does scripting, that's it. It does it very well, and in a completely sub-class agnostic way. I can hang Scriptable off of anything, not just game objects sub-classing from Object. And I do, given by my CombatEngine v. Actor example. Both are Scriptable, but share zero similarities beyond that. That's is the exact definition of extensible and reusable (aka not monolithic).

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • SeolSeol Registered User regular
    edited April 2010
    You keep talking about object composites. So... why not use composition, instead of inheritance? It sounds like you're creating things like scripting contexts as standalone conceptual entities: so make them member objects, not base classes?

    edit: Yes, this is a bit more of a pain in the neck to implement: you need a scripting context getter, and interfaces to support accessing contexts, and it makes it more awkward if you want to access two conceptual entities at the same time. On the other hand, it protects you from the reasons why multiple inheritance was considered dangerous in the first place: if you do something in ScriptContext which conflicts with AnimationContext - give two fields the same name, for example - then that's not a problem, because they're entirely separate entities.

  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    Seol wrote: »
    You keep talking about object composites. So... why not use composition, instead of inheritance? It sounds like you're creating things like scripting contexts as standalone conceptual entities: so make them member objects, not base classes?

    edit: Yes, this is a bit more of a pain in the neck to implement: you need a scripting context getter, and interfaces to support accessing contexts, and it makes it more awkward if you want to access two conceptual entities at the same time. On the other hand, it protects you from the reasons why multiple inheritance was considered dangerous in the first place: if you do something in ScriptContext which conflicts with AnimationContext - give two fields the same name, for example - then that's not a problem, because they're entirely separate entities.

    You answered your own question in your edit. If I was doing this in C#, I would have no choice but to do what you suggest (which is composition through aggregation, btw). The "danger" of multiple inheritance is not lessened in C#. I can still have two interface that have a conflicting method, or property, signatures. I just have to implement one of the interfaces explicitly (IInterface.ConflictingMethod), rather than implicitly. In some ways, this is more dangerous than the multiple inheritance case. At least one tells me at compile time I have an ambiguous symbol, the other lets me work around it and then basically hide the conflicting method, rather than correctly design my interfaces.

    Also, if you keep your fields 'private' in C++ (which you should be doing, sub-classes don't need to access fields, they should have protected/public getters/setters if they need access), then you can have 15 base classes all with the private field '_name' and not conflict.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • NamrokNamrok Herndon, VARegistered User regular
    edited April 2010
    GnomeTank, I think you have a very specific way you like to code that works for you.

    But this is devolving into a "No, MY coding practices are the best" type argument.

    XNA and C# is a poor fit for you. Thats ok. You asked how things can be done in XNA, you've been told, and you've said quite profoundly "BUT I DON'T WANNA!".

    Moving on, I'm hoping to steal away some time this weekend to work on my game stuff. Lazy sunday hopefully.

  • gjaustingjaustin Registered User regular
    edited April 2010
    GnomeTank wrote: »
    gjaustin wrote: »
    GnomeTank wrote: »
    If you're in a situation where you're writing "vastly different implementations" per-object, you may be designing something wrong to begin with, or your original base was not general enough.

    I don't have the code here, so I can't post the header for any of my components, but basically if you look at Scriptable it contains all the pieces you need to wire up scripting for an object: storage for the script context, script context initialization, generic methods to call script functions, generic ways to load a script in to the context. These are operations that should, if things are designed correctly, be absolutely 100% the same for everyone object. If you do need to overload the default behavior, everything is marked virtual (except getters and setters, makes them too slow).

    The inheriting component object can then use those generic facilities to wire up scripting in an object specific way.

    I think in all my years of programming I've run into a situation where I needed multiple inheritance once. And it only came up because I had to create an extension to an existing class hierarchy that I couldn't change.

    It sounds like you're designing much more monolithic classes than would work in C# and XNA. My design is split into more interchangeable parts.

    I make heavy use of utility classes and methods. So while your class might look like:
    public class Entity : Object, Scriptable
    {
       public void RunScript()
      {
          this.ExecuteScriptAction();
      }
    }
    

    Mine looks like:
    public class Entity : Object implements IScriptable
    {
       public void RunScript()
       {
           this.ScriptAction.Execute();
       }
    }
    


    So they work fundamentally the same way, but mine is less tied to a specific implementation of scripting, since I could always just instantiate a different class.

    Edit: To be fair, yours has the advantage of saving a few lines of code in the Deserialization method.

    The problem here is that you have to re-implement IScriptable every time you want to create a scriptable object. You don't get any advantages of having the most mundane, completely generic, parts of scripting be drop-and-drop mixable.

    I have several places this makes a lot of sense to me. For instance, my Actor class is Scriptable, so is my CombatEngine class. They share no other similarities, except they both need a place to store a scripting context, and both need a way to call methods inside that context. My Static class and my Actor class are both Scriptable, and both game Objects, but one is a AnimatedRenderable, the other is a MeshRenderable...because static object's don't need to render an animated mesh. Yes, I could have had an IAnimatedRenderable and an IMeshRenderable, but again, I would be stuck reimplementing the same interface twice on two separate objects.

    I could have an IScriptable interface, but then Actor and CombatEngine would both need to implement IScriptable (or would need to aggregate an object that does, which is by no means any cleaner). I need to do neither, I just need to publically inherit Scriptable. The illusion that using interface implementation and aggregation gives you the magic bullet so that you can easily change scripting engines is just that, an illusion. It's no easier, or more difficult, than for me to simply change the Scriptable base class implementation.

    Object composites are that edge case where multiple inheritance clearly outshines interface implementation and aggregation. This is why there are several C# engines out there trying to provide object composites that don't look horrible in the framework of interface implementation and aggregation.

    e: Also, by the very definition of my system, my classes are not monolithic even in the slightest. Scriptable does scripting, that's it. It does it very well, and in a completely sub-class agnostic way. I can hang Scriptable off of anything, not just game objects sub-classing from Object. And I do, given by my CombatEngine v. Actor example. Both are Scriptable, but share zero similarities beyond that. That's is the exact definition of extensible and reusable (aka not monolithic).

    Object -> Scriptable -> CombatEngine
    Object -> Scriptable -> Renderable -> AnimatedRenderable -> Actor
    Object -> Scriptable -> Rendarable -> MeshRenderable -> Actor

    Why aren't all your meshes inheriting from Scriptable? Alternatively, if they need a Script Context, why don't you have a ScriptContext object?

    And the definition of a monolithic class I've always heard is a class that tries to do too much on its own. You're pasting all these objects together into something enormous, when you could be creating other objects to handle their own tasks.

    Your belief is not required
  • SeolSeol Registered User regular
    edited April 2010
    GnomeTank wrote: »
    Seol wrote: »
    You keep talking about object composites. So... why not use composition, instead of inheritance? It sounds like you're creating things like scripting contexts as standalone conceptual entities: so make them member objects, not base classes?

    edit: Yes, this is a bit more of a pain in the neck to implement: you need a scripting context getter, and interfaces to support accessing contexts, and it makes it more awkward if you want to access two conceptual entities at the same time. On the other hand, it protects you from the reasons why multiple inheritance was considered dangerous in the first place: if you do something in ScriptContext which conflicts with AnimationContext - give two fields the same name, for example - then that's not a problem, because they're entirely separate entities.

    You answered your own question in your edit. If I was doing this in C#, I would have no choice but to do what you suggest (which is composition through aggregation, btw). The "danger" of multiple inheritance is not lessened in C#. I can still have two interface that have a conflicting method, or property, signatures. I just have to implement one of the interfaces explicitly (IInterface.ConflictingMethod), rather than implicitly.
    That's if you have two separate interfaces with methods with the same signature that are intended to invoke different behaviour, and that's only if you specifically go out of your way to make it happen.

    I'm relatively new to C#, from a Java background, and I'm unconvinced about the usefulness of that device, and at my current level of experience with the language I'd agree that explicit interface implementation seems unnecessary and a crutch for poor interface design: I'll freely admit I may be missing contexts where it's particularly useful.

    And yes, by properly designing the code from day 1 you can avoid the dangers of multiple inheritance: it's much more of an issue in larger projects where different people are maintaining and extending other people's classes, where work on one class could break other classes that extend it due to unexpected interactions. Y'know, the sort of projects C# was designed for.

    So the argument against composition by aggregation is: it's a little more verbose to implement, right?

  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    Seol wrote: »

    So the argument against composition by aggregation is: it's a little more verbose to implement, right?

    That's the main argument yes, it can be way, way more verbose to implement as your interfaces grow in size. It can also lead to a lot of cut-and-paste boiler plate code, rather than sticking very cleanly to DRY.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    gjaustin wrote: »

    Object -> Scriptable -> CombatEngine
    Object -> Scriptable -> Renderable -> AnimatedRenderable -> Actor
    Object -> Scriptable -> Rendarable -> MeshRenderable -> Actor

    Why aren't all your meshes inheriting from Scriptable? Alternatively, if they need a Script Context, why don't you have a ScriptContext object?

    And the definition of a monolithic class I've always heard is a class that tries to do too much on its own. You're pasting all these objects together into something enormous, when you could be creating other objects to handle their own tasks.

    Because CombatEngine doesn't need to be an Object, it needs to be a Scriptable. Yes, I could create one gigantic single inheritance tree to get what I wanted. It would be a mess. Not every Renderable needs to be Scriptable, not every Scriptable needs to be an Object. Not every Object needs to be Scriptable. So I would end up with wacky base classes like "ScriptableRenderableObject", just to enforce the proper inheritance chain.

    And your definition of a monolithic class is very wrong. A monolithic class would be if I tried to implement the ideas behind Scriptable, MeshRenderable and Object as one gigantic class. A monolithic class is not one that is composed of smaller, non monolithic components, to create one larger logic object. That's good OO design. Classes should do one thing, and do them very well. That doesn't preclude that class from needing do the exact things it's composite bases provide. If I tried to rig up Actor, CombatEngine and Trigger all to be Scriptable, without a common base (or at the very least an aggregate interface implementation), that would be monolithic. Having those three classes all inherit Scriptable, which does it for them, is not monolithic. It's extensible, reusable and follows DRY.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • DelzhandDelzhand motivated battle programmerRegistered User regular
    edited April 2010
    I admit most of this goes right over my head. The most complex hierarchy I've ever had was Object>Entity>PhysicsObject>Actor>Player.

    Hell, in my SRPG, it's even simpler. Unit is extended by UnitPC and UnitAI.

    9KKPPQw.png
  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    Namrok wrote: »
    GnomeTank, I think you have a very specific way you like to code that works for you.

    But this is devolving into a "No, MY coding practices are the best" type argument.

    XNA and C# is a poor fit for you. Thats ok. You asked how things can be done in XNA, you've been told, and you've said quite profoundly "BUT I DON'T WANNA!".

    Moving on, I'm hoping to steal away some time this weekend to work on my game stuff. Lazy sunday hopefully.

    Uhh, actually, it's just an interesting discussion about game engine design, in a thread that prior to me asking the question had almost no movement or discussion. I know how to achieve what I am doing in C++ reasonably well in C#, I write C# for a living after all, and have been using it since .NET 1.0 beta.

    I was simply starting a discussion about game engine design, and how the language your using (in my case C++, yours C#) changes (sometimes fundamentally) how you design your engine.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    Delzhand wrote: »
    I admit most of this goes right over my head. The most complex hierarchy I've ever had was Object>Entity>PhysicsObject>Actor>Player.

    Hell, in my SRPG, it's even simpler. Unit is extended by UnitPC and UnitAI.

    Hehe, it's okay man. Frankly, my engine is probably a tad over designed in places, but god damn if the code doesn't look gorgeous. And that's what matters, right? RIGHT GUYS?!

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • SeolSeol Registered User regular
    edited April 2010
    GnomeTank wrote: »
    That's the main argument yes, it can be way, way more verbose to implement as your interfaces grow in size. It can also lead to a lot of cut-and-paste boiler plate code, rather than sticking very cleanly to DRY.
    Well, that depends on how you implement it. If you have the IScriptable interface as having all the scripting methods, that could get very verbose. If you have the IScriptable interface as having nothing but a getScriptContext() method, which returns the script context which you then act on, then each interface only needs one method.

  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    Seol wrote: »
    Well, that depends on how you implement it. If you have the IScriptable interface as having all the scripting methods, that could get very verbose. If you have the IScriptable interface as having nothing but a getScriptContext() method, which returns the script context which you then act on, then each interface only needs one method.

    Which leads to problem #2: Repeating a lot of boiler plate code cut and paste style, because there will end up being a common set of operations you can distill out of those disparate IScriptable implementations.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • DelzhandDelzhand motivated battle programmerRegistered User regular
    edited April 2010
    What kind of game are you making, GT?
    GnomeTank wrote: »
    Uhh, actually, it's just an interesting discussion about game engine design, in a thread that prior to me asking the question had almost no movement or discussion.

    It's less than a day old, mang. The last XNA thread only managed 100 pages in a year+ of discussion. It tends to be a long-haul thread.

    9KKPPQw.png
  • SeolSeol Registered User regular
    edited April 2010
    GnomeTank wrote: »
    Seol wrote: »
    Well, that depends on how you implement it. If you have the IScriptable interface as having all the scripting methods, that could get very verbose. If you have the IScriptable interface as having nothing but a getScriptContext() method, which returns the script context which you then act on, then each interface only needs one method.
    Which leads to problem #2: Repeating a lot of boiler plate code cut and paste style, because there will end up being a common set of operations you can distill out of those disparate IScriptable implementations.
    Yes, but it's all basic getter code. DRY is important for two reasons: firstly, repeating yourself is often wasted effort, but FAR more importantly, if you have a critical piece of code duplicated in different places, you end up with a maintenance nightmare. Fixing a bug in it once won't fix it everywhere: so, don't copy/paste logic.

    getScriptContext() doesn't contain any logic. It just returns a field. Which means, really, only argument 1 - that it's a bit more work - applies, and in a case where you don't have multiple inheritance at your disposal, you're looking at approaches which will require more effort, and this isn't much more effort for a very similar effect.

    Hell, I'd say this is a case of DRY. Maybe not quite so direct as multiple inheritance, but the sort of situations you're describing sound to me like a natural fit for composition by aggregation.

  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    Delzhand wrote: »
    What kind of game are you making, GT?
    GnomeTank wrote: »
    Uhh, actually, it's just an interesting discussion about game engine design, in a thread that prior to me asking the question had almost no movement or discussion.

    It's less than a day old, mang. The last XNA thread only managed 100 pages in a year+ of discussion. It tends to be a long-haul thread.

    Not dissin the thread mang, just pointing out, I was just starting a discussion, and it's gotten the thread hoppin', I might add.

    Anyway, I am making an 'evil' comedy action RPG. Basically everything is reversed. You live in the evil cave, the evil wizards are your beer buddies, and it's your job to go slaughter the inhabitants of every town, temple and castle you find. I'm working the loot angle in to the story, where the constant pursuit of "phat lewt" actually has a story reason, inside your evil brotherhood.

    The classes available will be an offering of evil: Demon Lord, Warlock, Succubus and Despotic Warlord.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
  • GnomeTankGnomeTank Registered User regular
    edited April 2010
    Seol wrote: »
    Hell, I'd say this is a case of DRY. Maybe not quite so direct as multiple inheritance, but the sort of situations you're describing sound to me like a natural fit for composition by aggregation.

    If the tools you are working with have no multiple inheritance available, then absolutely, composition by aggregation is exactly how you would achieve what I am doing. It would be the only (smart) way to do it.

    In the presence of multiple inheritance, that obviously becomes the preferred way to achieve object compositing. Why would I do composition by aggregation in C++ when I can do the less verbose composition by inheritance? :)

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, D3: Brainling#1998, NintendoID: Brainling
«13456776
Sign In or Register to comment.