Question

I'm currently creating a simple console-based game in which the player can move between different rooms, pick up and use items, and eat food. In the game's current state that's about it.

What I need help with is:

Creating a good "Event" class for my game. The way I'd like it to work is that every item and room should be able to be associated with an Event.

As I'm new to this I'd appreciate any reading material related to this kind of procedure, or suggestions as to how it would be best to set up my class(es) considering the points below, or simply how to attack this kind of problem (that is having trouble deciding how to set up classes).

I want to be able to create different kinds of events, for example:

  • Output some text, and then ask the player a question. If the player gives the correct answer, do something.

  • Output some text, then remove an item from the player's inventory, and then move the player to another room.

What I'm trying to avoid:

  • The entire point of the game is to practice good class design, so things such as responsibility-driven design, cohesion and coupling are important aspects. Thus I want it to be as simple, reusable and independent as possible.

  • Having to hard-code every event so that an item or room simply calls a specific method in the Event class.

What I'm thinking at the moment:

Creating a few sub-classes so that I could for example create new events (and associate them) using: itemObject.setEvent(new Event(new Question("introText", "outroText", "correctAnswer")));

Please let me know if more info is needed! Thanks!

Was it helpful?

Solution

The Game Programming Gems books are great... though a bit pricey.

You can probably find a relevant article or two over on GameDev's Article list, and there's probably some good stuff buried in their forums

As for an Event class, you almost certainly want a base class with some number of subclasses (MoveEvent, InventoryEvent, etc). And if you really want to avoid hardcoding things, you should define your game in data files. Rooms, items, and events... plus anything else you tack on later. The format you use to define things is entirely up to you. I recommend something that will give you practical experience as this is a learning exercise: an XML parser you haven't used for example. Not the most efficient format to parse, but this is a console game, so that's not such an issue.

One suggestion I have for an Event subclass would be one that can chain other events together. The interface doesn't change, and it allows you to do things like "add this to the player's inventory, take that away, AND move them over here".

OTHER TIPS

One thing I would consider is separating the parsing of input text and generation of output text from the underlying domain model. Your question appears to mix the two together whereas I would consider the text portion of the problem as the presentation layer.

For example, your domain could consist of the following interfaces:

public enum Action { HIT, TALK_TO, EAT, USE };

public interface GameEntity {
  /**
   * Performs the specified action on this GameEntity, passing in zero or
   * more other GameEntity instances as parameters.
   */
  void applyAction(Action action, GameEntity... params);    
}

public interface Item extends GameEntity { }
public interface Person extends GameEntity { }

In addition you could define a TextParser class that would process the input string and make resulting calls to the domain layer or else return a default response: "I do no understand.". For example, the input phrase "use key on door" would result in the method call:

key.applyAction(Action.USE, door);

When speaking of events the observer pattern comes to mind. You can think of your game to be internally presented by several state machines (you can look this up at Wikipedia, too, I can't add 2nd link myself due to being new to SO). Each transition from one stage to another is an event that can be communicated to registered oberservers of that event.

At example:

USE KEY ON LOCK: triggers removal of key and opening of door; implictly "cascading" to next event without additonal user interaction (opening of door): triggers room having additional exit etc.

I've recently implemented something similar to what you're describing. I began by creating an EventManager class that has a "Publish" and "Subscribe" method. When the system starts up, it scans all the loaded assemblies (libraries) for classes that implement the IEventListener interface:

/// <summary>
/// A class that intends to listen for specific events to be published by an
/// event manager.
/// <see cref="EventManager"/>
/// </summary>
public interface IEventListener
{
    /// <summary>
    /// Subscribes to the event types that this listener wishes to listen for.
    /// </summary>
    /// <param name="eventManager"></param>
    void RegisterSubscriptions(EventManager eventManager);
}

... and calls the RegisterSubscriptions method on each of them. (There is only one instance of the EventManager that gets used everywhere; I use dependency injection to bind it as a singleton instance.)

RegisterSubscriptions will simply call the Subscribe method for each event type and handler that the given class is intended to handle. (I'm using .NET, so events and handlers are a little easier to work with, but you can do the same thing in Java using anonymous subclasses.)

A typical event might be something like RoomEntered, and the arguments associated with this event would include the room ID and maybe some other properties about the room. The game engine publishes this event when the user enters a room, providing the appropriate event arguments for that room, and the EventManager class is then responsible for invoking each handler that has subscribed to that event type. One handler for this event might be "HandleEnterRoomWithMonsters", which checks to see whether the room has monsters, and performs an action accordingly.

Does this make sense overall? Do you have any questions about this approach?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top