Friday, June 29, 2012

EPI #6: Classes

The brainstorming I did on Wednesday got me started on the right track as far as thinking about designing a game engine.  I didn't post yesterday because I spent the whole day hiking.  This blog is going to get a little bit more technical as my ideas crystallize further and I start writing code, so I apologize to those of you who are not hip to the Computer Science lingo.  However, don't get too disappointed, because there will still be a lot of work to do designing the actual game once the engine is ready.

I hinted on Wednesday that I will use an object-oriented approach to implementing my game engine.  I'm choosing this programming paradigm because it makes the most sense.  Games are broken up into multiple discrete functional units, and taking an object-oriented approach allows me to conceptualize and implement each of these different functional units separately.  This makes it easier both to translate my thoughts into code and to keep my project organized.  Honestly, keeping this whole thing organized is very likely going to be the hardest part of what I'm doing.

Some of you are probably curious about which programming language I'm going to use.  I have decided to use Python for the sole reason that I need to learn Python before I start my real job in July.  If I had other concerns, I might have made a different choice, e.g.:  C++ (if I were actually going to write a real game, as in one I could sell to people maybe); Java (if I were a masochist and/or concerned about portability); or PHP (if I wanted to use something I'm comfortable with).  For graphics, I'm probably going to use PyGTK, although I haven't really explored my options there.

I've blogged before about how nearly all of the action in a JRPG takes place on the world map, on a town or dungeon map, or in a battle.  It happens that, from a coding standpoint, there's no reason to separate world maps from town or dungeon maps.  In practice, the world, town, and dungeon maps will probably all be designed very differently from each other, but the engine needs to support the same set of features from all three.  So in practice I've reduced the number of locations in which action happens from three to effectively two.  Therefore, the first class I'm going to design will be the Map class:
  • Map
    • name: string
    • actors: MapEntity[]
    • tiles: MapTile[][]
    • move(Character, integer)
  • OrderedPair
    • x: integer
    • y: integer
  • MapTile
    • description: string
    • passability: integer
    • art_path: string
    • art_resolution: OrderedPair
    • specials: string[]
So then, the really important parts.  A Map will consist of a matrix of MapTiles and an array of MapEntitys.  Maps will also be responsible for moving their different actors around.  A MapTile, in turn, consists of the file system path to the corresponding art and an array of special event definitions.  MapTile "passability" will make sense when I talk about MapEntitys:
  • MapEntity
    • current_location: OrderedPair
    • last_location: OrderedPair
    • control: Intelligence
  • Party extends MapEntity
    • members: Character[]
    • travel_power: integer
  • Character
    • (statistics)
    • (equipment)
    • (abilities)
    • current_HP: integer
    • maximum_HP: integer
Above are classes that describe things that act on the map.  MapEntitys keep track of their present and immediate past locations, Partys are collections of Characters, and Characters are the bread-and-butter of RPGs.  Party travel_power is compared against MapTile passability to determine whether or not a Party can move to a particular tile.  If travel_power >= passability, the move is successful.  Intelligence will be an interface that prescribes methods by which MapEntitys will make decisions.  There will be several different implementations of this interface, representing AIs, humans, and maybe one day even networked players.  Class properties in parentheses are things I haven't yet completely thought out that need to exist.

When you're planning a software development project, there is always more planning you can do.  But what I've done and blogged about so far is probably enough for me to start writing code.  I haven't really been talking about it, but when I think about class design, I also think about how the classes will interact with each other and the main game engine execution thread.  So now I have a pretty clear idea of how these pieces will fit together to generate a map with a figure on it that moves around in response to input.

"But Zach!" you say, "You haven't talked about how designers will create content, or how that content will be interpreted by the game engine!  Surely you'll need some content to test your code as you write it?"  Yes. I will.  You've made an astute observation, dear reader.  And you've raised a question that will be answered in a later post.  In another later post, I'll get into the details of how these lovely classes interact with the main game engine execution thread.  Maybe I'll even abbreviate that MGEET in the future, since I can't think of anything better to call it.

No comments:

Post a Comment