views:

117

answers:

4

If i have a textgame that has a world object that has objects of type room which has objects of items and enemies and then a gamehelper object that has user objects for the actual player. (this game doesn't have wandering enemies since that would complicate my question to much for me :-))

How should I go about either killing an enemy or picking up an object? Or should I think some other way when structuring up my classes completely? I got the suggestion that I would need a manager that controls the world and mediates between users and objects but I can't figure out how that would look/work.

I would also implement interfaces of killable and pickable to separate objects from eachothers when necessary if thats of any relevance... And oh im learning Java so any example code that might be useful to understand could be written in that.

Ie:

        World
         |
    ____Rooms____ (could be like a 4x4 array or something with X and Y cords)
    |           |
  Objects     Enemies (Either killable / pickupable)

        Game
         |
        User (can walk around in rooms, kill monsters and take treasure)
+1  A: 

I don't see anything obviously wrong with your class structure unless your diagram is a diagram of it. :) Rooms, objects and enemies should certainly not inherit World. It looks like you're diagramming containment, though, which is fine.

How would you go about killing an enemy or picking up an object? Doesn't that depend on what those actions mean in your game? It sounds like, for picking up an object, an Object has an Environment that can be either a Room or a User; an Object whose Environment is a User is in that User's inventory. Picking up the Object changes its Environment from the Room to the User.

Possibly Objects can have Enemies as their Environment as well, so that killing an Enemy destructs the Enemy and moves Objects in its inventory into the Room that the Enemy was occupying. Or maybe you want a "dead Enemy" type of object? Really, it all depends on your game model.

chaos
Oh yeah it's a diagram of where they are not the class diagram :) But yes thats pretty much a good description of what im looking to accomplish. I can't wrap my head around how to actually control the game. Should like a control object have an while(true) loop that accepts commands and then if command is kill monsterone where should it start doing it's work? Look trough room for the monsterone object and then send a message kill() to the object or should it send a message to the user attack(monster)?
Patrik Björklund
I guess the first question there is whether the game is single-player or multiplayer, turn-based or realtime. If it's a single-player turn-based game, you don't need to poll for commands, you can just run them off of the input you're receiving. Otherwise, a polling loop is probably called for. What happens when a 'kill' command is processed again depends on your game model (does an ongoing combat start, or does the enemy just die?), but I would tend to go with the User::attack(monster) option.
chaos
Possibly you might want to look at how some similar, established codebases like http://dead-souls.net/ do this.
chaos
Would it be a good idea to use a GameHelper object that has the loop checking for input send all the messages to different objects? Like gamehelper calls users attack() with the argument being the monsterone object? Or if time is 05:00 send the sunrise() to the World object which sends like an echo that the sun rises to something (what would be a good idea to send that to btw?) Sorry for asking you so much but im just getting so many things to think about from this question :)
Patrik Björklund
It really depends how deep you want your game to be... These sorts of things can be incredibly complex, or mind blowing simplistic in their conception.
Matthew Scharley
The simplest way that will let me expand the game with minimal rewriting of the existing code/classes :-) There must be best practices or similar for these types of things (having a controller that thats "in charge", some way of interacting object to object depending on controllers actions, how to display output/manage data retrieval and such) Or do I think Java is to rigid and should just test my way forward to see what works and what doesnt?
Patrik Björklund
I think you should have a couple of different objects for those things. The object that turns user commands into function calls I would refer to as your Parser. I don't know that I would have it do the input-checking loop; that might be a job for a thread in the User object. For periodic events like the sun rising, I would make a Cron object of some kind. I imagine your 'sun rising' messages, and the rest of your game messages, would be sent to the User to be output.
chaos
You may want to check out the Flyweight-Singleton-Registry design pattern I talk about in this question: http://stackoverflow.com/questions/401720/brokered-definition-set-design-pattern-well-known-under-another-name; I find it's very helpful for many game purposes. For instance, with your command Parser, you may find it beneficial to have it manage a pool of 'command definitions', rather than having all the command code within itself. So your Parser object analyzes the command and then hands off to the Command.Kill object, which has the actual killing logic.
chaos
+1  A: 

Interfaces for attackable and pickupable items, perhaps:

interface IAttackable {
    void Attack();
    event Killed;
}
interface ILiftable {
    void Get(Container putHere);
}

Then you can do simple type checks to see if you can attack or pick things up.

Yes, a mediator object sounds like a good idea... For instance, it might subscribe to all the IAttackable.Killed events and send a signal to the User class when something dies in the same room as them. It might also be a go-between for organising how much damage each takes.

Personally, I'd have a Creature class, and have both enemies and users subclass from that, to simplify things a little (and potentially enable enemies to fight amungst themselves if the need should arise).

Matthew Scharley
Havent read anything about subscribing to events but it sure sounds like a good thing! Thinking forward with the subclass is also a good point. I elaborated on my question a bit in the previous answers comment, it's hard to define what your asking when your not really sure.
Patrik Björklund
Events work pretty simply: it's a way for class A to say "Let me know when something happens" and give class B a function to call when it does. Then class B can call the event like a function, and Java will be smart and call all the registered functions for the event, letting everyone know the event happened.
Matthew Scharley
"It's hard to define what your asking when your not really sure" Perhaps it's time to sit down with a pen and some paper and start nutting some of this out then. Brainstorm things you'd like to do, narrow the list to things you think you can do, add a few things that are a bit harder to push yourself, then do some research and figure out how to actually do it!
Matthew Scharley
I did that and ended up with some terrible code that worked but didn't have a clear logic and got harder and harder to work with the more i started to rewrite it. Guess it's probably a matter of experience and im trying to take shortcuts. :-)
Patrik Björklund
Possibly one of the most important things is a good class/interface structure... If you can design that well, and decouple your classes implementations from each other (ie. with events and dependancy injection) you can make these sorts of things happen less.
Matthew Scharley
A: 

A controller- or mediator-class are often used in applications, but this has a little "smell" to me. Such classes can fast become so-called "God-classes" which know everything, when all other classes are just data-containers.

This kind of design is warned against! There is a good book about OO-Design which includes this warning and other really good principles.

I can also recommend for OO-Design in general the articles of "Uncle Bob" Robert C. Martin. You should look in "Design Principles" and here specially the first articles.

Those are invaluable ressources to understand, how Classes should be designed -- I think also decoupling by eventing and other things is handled there.

With this armament, you will be much better prepared for the design.

Your design could also be started by thinking, what activities should be done by which objects. Objects which tent to collect all activities are smelling like God-classes -- avoid them! Objects which tent to have no activities at all are smelling as not needed at all -- the boxes "World" and "Game" are somewhat smelling in this direction unless they really carry some functionality that no other object can carry.

When you create some thoughts, how the world is working -- the design might be very easy. Such thinking like the "Environment" as an association can be made here. But also different modelling is possible. How about this (Just a guess!): Why must your rooms be objects alltogether? You could also have a World-Object that just contains a 2D-Array with slots for the objects contained in the room (including the user-object??). This could ease things up, when you have a big "World". But of course, rooms as objects have the advantage, that unlimited objects (Enemies, users, Items) can be contained in them easily.

So first, you might begin thinking about that, then if you have an Item class or a "Takeable" class ... and so on.

Hope this helps a little bit -- don't hesitate to ask.

Juergen
A: 

As noted in a comment, it's important to know whether the game is single-player or multiplayer, turn-based or realtime. Because the simple solution for single-player turn-based games does not work unmodified for multiplayer realtime games.

For single-player turn-based games, the following basic outline should give you one approach (Python-like pseudocode):

def main_loop():
    while not finished:
        command_text = ask_user_for_input()
        execute_player_command(command_text)
        update_world()
        send_output_to_player()

def execute_player_command(command_text):
    # look up the command object and work out what parameters to pass it
    command, parameters = parse(command_text)
    # ask the command to do its stuff
    command.execute(player, parameters)

def update_world():
    # obviously you can munge these together with an Updateable interface
    # or something similar
    for each creature in all_creatures:
        creature.update()
    for each object in all_objects:
        object.update()

If you're real-time rather than turn-based, your main loop will presumably change to poll for input, and you will probably want to run the update_world on some sort of timer instead of once per iteration. For periodic tasks such as round-by-round combat, they too can be done with such a timer. It's useful to be able to put future events onto a queue ordered by time, and then check the front of the queue each iteration for pending events.

Your command objects can perform the task of looking up all relevant parties and performing operations on them as required. They can be used by PCs or NPCs as you need, and pushed onto the future events queue if you want them to operate in the future. Obviously for command objects to be useful they need to be able to look things up in the world, eg. finding all characters in a room, all objects in an character's inventory, all objects in a room, etc. If you're cunning you can implement almost all of this with thin wrappers around one containment interface.

Kylotan