Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

In a roguelike I'm developing in Ruby, I started with a traditional object hierarchy where all game logic relevant to creatures were contained in the Creature class. Movement logic, for example:

Creature.instance_methods(false)    # => [ :move ]

In my design, the map and creatures are decoupled: the map has no idea what's on a tile and the creature has no idea which kind of tile it is on. What brings them together are coordinates.

Movement logic requires information about where on the map the creature is, so the creature would need access to the map. The map belonged to the game, so I just added a game attribute to every creature as a quick solution. I didn't really want to pass a map instance every time the creature needed to move around because the map the creature is on isn't likely to change.

In the end, I removed the game logic from the Creature class, and separated them into modules:

Game::Logic::Movement.singleton_methods(false)    # => [ :move ]

The way I understand it, these logic modules integrate multiple game parts which depend on each other in a way not easily expressed hierarchically. The methods are just algorithms that operate on the given information. For example, the implementation of the move method:

def self.move(creature, map, dx, dy)
  coordinates = Map::Coordinates[dx + creature.x, dy + creature.y]
  tile = map[coordinates]
  creature.coordinates = coordinates if tile and tile.passable? # Teleport!
end

These methods are called directly from the game loop:

def handle(input)
  case input
    when :up then Logic::Movement.move character, map, 0, 1
    # ...
  end
end

This is how the game is currently organized. Movement is the only game logic I've added as of now, so I think it would be wise if I revised the architecture while it is still small. So, what do you think of it? What are the problems, and what can I do to improve it?

I'm also interested in how it compares to component-based game architecture. I've read a lot about it during my research, and it seems to be the most maintainable and reusable way to write game code. I think it would fit naturally in the Ruby world, due to its dynamic nature and message-based method invocation. The thing is, I really never understood how different components interact with each other, and I'm looking for something I can make sense of.

share|improve this question
2  
Game development is seriously profiling-centric. Profile your game and figure out where the hotspots are first; improve those as much as you can. Too much architecture will kill performance (in most cases). –  Jonathan Dickinson Dec 1 '11 at 23:09
    
@Jonathan, I totally agree! However, at least in this case, I think speed isn't a priority since roguelike games are turn-based and text-based, and are thus not required to draw at 30~60 frames per second. That is one of the reasons I chose an expressive, high-level language such as Ruby to develop in, even though I love C. :) –  Matheus Moreira Dec 2 '11 at 1:28
add comment

2 Answers

One thing to note is that if you are going to have a lot of creatures/monsters, you should probably make them flyweights. You would have a Creature class with individual-specific information like current hit points, and a CreatureType class with information that is common to all instances of that particular type of creature (things like max hit points). All creatures of a particular type contain a reference to a single, shared CreatureType object. You will only have a few instances of CreatureType in your entire game (one for each type of creature), so the more information you can place in that object as opposed to hundreds or thousands of Creature objects, the better your memory savings will be.

In my game I also place the movement logic in the CreatureType class, since all creatures of a particular type use the same movement AI.

share|improve this answer
add comment

There's not really much to speak of yet. You could shift the logic around as much as you like but that movement function would still look pretty much identical. It's too early to judge whether this is going to work for you or not. You need to come up with a few more use cases, specifically complex stuff, and see how it fits into the system. You'll quickly see where the problems lie.

I'm also interested in how it compares to component-based game architecture. I've read a lot about it during my research, and it seems to be the most maintainable and reusable way to write game code

Reusable? Sure. Maintainable? Nope. I think components make games harder to maintain because the number of possible interactions between components grows exponentially as you add new ones. They have pros and cons.

share|improve this answer
    
I didn't realize this before, but it seems that components interact through levels of indirection. Is this how their complexity grows exponentially? Do truly independent components have such impact on complexity? The differences I've noticed between components and my model is that the object gets to keep all its data, which is defined by the class hierarchy, and that the level of indirection is handled by the Game::Logic modules. Can the rise of complexity be reduced in my model? –  Matheus Moreira Dec 2 '11 at 1:14
1  
@Matheus: There is no rise in complexity, if used correctly. Components should be separable and low in interactions. If many of your components have tight dependencies and interactions, something is wrong with your design. Just like you can use OOP in good ways and bad ways, you can use components in good ways and bad ways. The good way will reduce weird interactions between separate modules while increasing maintainability. The whole point of components is to decouple things that have no business or reason to be merged together into one uber-class in the first place. –  Sean Middleditch Dec 2 '11 at 6:49
    
Personally I don't think (or find in practice) that game entity components can ever be as decoupled as people would like. There are always interactions between them if you need any non-trivial behaviour and tracking and managing those interactions is more complex when spread across multiple objects. –  Kylotan Dec 2 '11 at 13:40
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.