Game Architecture

Discussion in 'Game Development (Technical)' started by Jay_Kyburz, Aug 15, 2007.

  1. Jay_Kyburz

    Original Member

    Joined:
    Nov 21, 2004
    Messages:
    180
    Likes Received:
    0
    I was working on my new game today, little tower defense game in python.

    I'm working everything up from scratch because it's grid based and needs a pathfinder, a real AI and is quite different to all the projects I have done before.

    Anyhow, I've got a first pass of a class hierarchy with a level class that contains a map class that responsible for generating paths; I've got a base gameobject class, and an AI class, and projectile classes etc etc . It's all animating and looking good.

    Then this afternoon I decided I needed to start generating paths for the AI's. An AI instance knows when it needs a path, but how does it communicate with the map instance that generates paths?

    Well my first response was to create an event / message system. The AI generates an event which is processed at the top levels of the game and is passed down to the map instance which generates the path and hands it to the AI.

    So I make a event manager class, and an event class, and then have other classes start registering interest in certain types of events and blar blar balr..when all of the sudden I ask myself...

    How is knowing what message to call any different to knowing what global function to call to return a path?

    Seriously, how is a global function that assumes the existence of my map instance any worse than a complicated event system. It's a lot better in many ways because I don't need to search around looking for where the event might be handled, don't need the overhead and extra paperwork generating new message classes etc etc..

    Here I am trying to bootstrap a game and I'm doing a bunch of leg work to give the system more structure and more abstraction than I imagine I'll ever need. Nobody is going to read this code but me.

    I've been seriously thinking lately of dropping the whole "object-orented" thing. I mean, what's it actually getting me? :)

    I few years ago I made a fairly complex game in blitz 3d. (before blitz max). It doesn't even have object oriented features like classes and inheritance. It was strange at first but it was a nice change. Lots of lists of data structures you just call functions on.

    Any of you guys thinking like this as well? Am I going crazy?
     
    #1 Jay_Kyburz, Aug 15, 2007
    Last edited: Aug 15, 2007
  2. ZeHa

    Original Member

    Joined:
    Nov 19, 2006
    Messages:
    426
    Likes Received:
    0
    I had the same thinking. But just believe me - you only keep saying this until you've once really understood how OOP works. Of course, you might now say "but I already know how it works!", but I also thought that back then. The fact is: If you ever develop a really complex OOP thing, you'll start to focus on different things and do things some completely other way. And only if that got completed, you might have really understood OOP. And even then, it can be that you still don't understand some certain aspects.

    When I started to do OOP, I really did everything like before, only with additional use of the "class" keyword - if I may exaggerate a little.

    I also feared that I may lose all those nice global variable features and stuff, but that was just because my thinking was still procedural. Once you REALLY understand OOP (and I don't claim that I'm the one who understands it fully), you'll notice that you'll take completely different approaches and that global variables are really NOT necessary. I didn't believe it either.

    Some little example: When I first heard that "GOTO" is a bad thing, I couldn't believe it. I just couldn't imagine how I should program anything good without using "GOTO". Then, when I really understood how to do it the correct way, I also realized it's really possible to develop software without the use of one single "GOTO" statement. I didn't believe that before. It's the same with using functions, you first apply it because you think you have to do it, but it takes some time until you REALLY use the advantages of it, and really do it the right way. In the beginning, you just use it in some particular cases, where you think it's better. But only after coding very much and learning and learning, you'll notice that there are so many cases where a function is better than inlined code. Why parameters and return values are a good thing. Etc, etc, etc...



    EDIT: Sorry for not answering your direct question :D
    Well, for your problem, first think of a strict hierarchy that makes sense. Draw it and think over it again, there might be some things that have to change. Then, when you're sure that everything works, you'll probably need some "Listeners", or callbacks. That way you can perfectly communicate "backwards" in the hierarchy. You can also use other signal or event systems, and I know, it might seem unnecessary at first, but - well just read my posting ;)
    In the end, you might understand why your approach is much more cleaner. Everyone only talks to those he's supposed to, and there's just no need for everyone to have everything under control. Think in basic and atomic actions, think how they fit together and how they need to be chained. In a big corporation, it's also hierarchical and has some event systems like mail or telephones, but it's not like everyone can go everywhere and read everything that he wants.
     
  3. Nikos Beck

    Nikos Beck New Member

    Joined:
    Jun 14, 2007
    Messages:
    321
    Likes Received:
    0
    Are you starting with the AI? Do you have a map in place yet?

    I develop in OO but I'm very cautious how I build things. I never add a class until I need it and only add functions as needed. I want to see how exactly the classes are interacting before I start giving them all sorts of structure.

    In terms of using "goto", I use it in only one case: jumping to the end of nested loops. If I have two loops and I'm done I just goto the end of the outer-most loop. Using breaks and a general "done-all-loops" variable is overkill.
     
  4. HairyTroll

    Original Member

    Joined:
    Jul 29, 2004
    Messages:
    582
    Likes Received:
    0
    I would make the Map object a Singleton and then call it directly from the AI class.
     
  5. MrPhil

    Original Member

    Joined:
    Aug 4, 2004
    Messages:
    671
    Likes Received:
    0
    I think you'll find Patterns helpful in getting a better handled on OOP:
    http://en.wikipedia.org/wiki/Design_pattern_(computer_science)

    I find the Composite pattern very useful for the game object:
    http://en.wikipedia.org/wiki/Composite_pattern

    In your case, path finding would be a class that is added at creation time to the game objects that need it. You could even have different version of path finding to make behavior different. The trick is that game framework runs the parts a game object is made up of, a sort of behavior injection.

    I also have found that my code is way better when I follow the Test Driven Development (TDD) methodology:
    http://en.wikipedia.org/wiki/Test-driven_development
     
  6. zoombapup

    Moderator Original Member

    Joined:
    Nov 25, 2004
    Messages:
    2,890
    Likes Received:
    0
    Well, the clear reason for using an event vs a function call, is that any code that calls the function call must be bound to the function. You could use a function pointer to allow indirection, but then you'd be essentially doing an OOP virtual method by another route.

    The main reason I like event based architectures, is that I can call an event on the AI object to send out a "create me a path between X and Y please" message, then return until the path manager object says "hey object ID, here's your path" event back. Remembering that the path manager might be handling many hundreds of these queries etc. The path manager can then do its thing over multiple frames rather than using a single frame.

    The indirection of events is a double edge sword, but my preference is on the side of events. Plus it makes compile times much faster as you naturally decouple event senders and recievers and can replace whole systems without upsetting the rest.

    But hey, if you feel happy with tons of globals, go for it!
     
  7. HairyTroll

    Original Member

    Joined:
    Jul 29, 2004
    Messages:
    582
    Likes Received:
    0
    If the path generation depends on the unit type then the event mechanism would have to encode the event type in the message; "Hey, I'm a goat and I want to get from A to B", or "Hey, I'm a Tiger Moth and I want to get from C to D."

    That works too.
     
  8. HairyTroll

    Original Member

    Joined:
    Jul 29, 2004
    Messages:
    582
    Likes Received:
    0
    Nothing wrong with global variables in an OO design.
     
  9. Jay_Kyburz

    Original Member

    Joined:
    Nov 21, 2004
    Messages:
    180
    Likes Received:
    0
    Yeah, but thats my point, the code that calls for the change is just as bound to creating the event as it is the function. The event is in fact a really indirect way to call the function. Its a very passive way of doing things.

    I do like the idea that an object such as my AI doesn't have to understand the structure of the rest of the program. i.e. My AI should not know that a Map singleton has a method to generate paths.

    I think what I'm going to experiment with are static lists in each of my classes with high level managers querying the lists and performing actions rather than processing a single message que. So for example, when my AI decides it needs a path, it puts itself in the "needs a path" list, rather than sending a "needs a path" message. Then the Level object, who owns the map and the AI will examine the message lists as hook up the two objects.

    Its not as efficient. My management object will need to query the lists every update whether it has AI in it or not. The question is whether the design is cleaner, more direct, with less code and easier to maintain.


    Thanks to everybody reading my rant and the interesting comments.
     
    #9 Jay_Kyburz, Aug 16, 2007
    Last edited: Aug 16, 2007
  10. HairyTroll

    Original Member

    Joined:
    Jul 29, 2004
    Messages:
    582
    Likes Received:
    0
    If each unit requires a different pathfinding behaviour (e.g. a car and an aeroplane), then should the pathfinding algorithm be encapsulated in the Map or the Unit class?

    What if the pathfinding behaviour depends on both the Map type as well as the Unit type?

    You don't really want your Units to be coupled to a Map, or a Map to be coupled to your Units. So you could encapsulate the pathfinding behaviour into a FindPath class; passing the map object and unit object to FindPath for generating the path. The Command Pattern may be useful here.

    Of course the FindPath class becomes complicated if the path depends on both the type of map as well as the type of unit. For example, from Practical Common Lisp:

    Ah, the joys of software development.
     

Share This Page

  • About Indie Gamer

    When the original Dexterity Forums closed in 2004, Indie Gamer was born and a diverse community has grown out of a passion for creating great games. Here you will find over 10 years of in-depth discussion on game design, the business of game development, and marketing/sales. Indie Gamer also provides a friendly place to meet up with other Developers, Artists, Composers and Writers.
  • Buy us a beer!

    Indie Gamer is delicately held together by a single poor bastard who thankfully gets help from various community volunteers. If you frequent this site or have found value in something you've learned here, help keep the site running by donating a few dollars (for beer of course)!

    Sure, I'll Buy You a Beer