8
\$\begingroup\$

I am just getting started learning to make games. I have created a simple text-based game where the user can walk around between rooms and interact with the objects in each room. However, I feel like my approach has led to a pile of bad spaghetti code. I'm not sure what a good way to structure a game like this would be.

My approach was to have one class with a method for each room and all the objects and interactions that could be done in that room. For example, this is the method for the study:

public static void Study() 
{
    bool studyexited = false;

    while (!studyexited) {
        string usercommand = Console.ReadLine ();
        usercommand.ToLower ();

        switch (usercommand) {
        case "turn left":
            GameEventText.StudyLeft ();
            break;
        case "turn right":
            GameEventText.StudyRight ();
            break;
        case "go forward":
            Notes firstsetofclues = new Notes ("First Note");
            GameEventText.StudyFront ();
            string firststudycommand = Console.ReadLine ();
            firststudycommand.ToLower ();

            if (firststudycommand == "read note") {
                firstsetofclues.Firstnotereading ();
            }

            Console.WriteLine ("Picking up this note would prove valuable");
            string secondstudycommand = Console.ReadLine ();
            secondstudycommand.ToLower ();

            if (secondstudycommand == "pick up note") {
                if (MainClass.PlayerInventory.AddItem (firstsetofclues)) 
                {
                    Console.WriteLine ("The note has been added to your inventory");
                } else {
                    Console.WriteLine ("Your inventory is full");
                }

                MainClass.PlayerInventory.Inventorydisplay ();
            }
        }
    }
}

I don't feel like this is an approach that will scale; that is, I can't really write functions like this for every room. I believe that using files in some way would be a good strategy to avoid the "hard coding" that I'm currently doing. But I am not sure how I can achieve that?

\$\endgroup\$
  • \$\begingroup\$ This is really more of a general programming topic, except maybe the bits about game loops and such (which is very broad). It's hard to say, though, because your question is very unclear as written. \$\endgroup\$ – user1430 Jan 18 '14 at 16:31
  • \$\begingroup\$ i don't understand how it's not clear as i tried my best to explain. perhaps you could assist me? \$\endgroup\$ – Mohamed Serry Jan 18 '14 at 16:33
  • \$\begingroup\$ A lot of it has to so with the lack of punctuation, capitalization and spacing between paragraphs. Fundamentally it sounds like you are asking how to avoid having to hard code a single class per room in your game. Is that correct? If so I can help edit your question. \$\endgroup\$ – user1430 Jan 18 '14 at 17:56
  • \$\begingroup\$ to some extent yes. i want to avoid hard coding all the game play basically. \$\endgroup\$ – Mohamed Serry Jan 18 '14 at 19:55
  • 1
    \$\begingroup\$ Possible duplicates: gamedev.stackexchange.com/questions/27004/… or gamedev.stackexchange.com/questions/20158/… ? \$\endgroup\$ – Trevor Powell Jan 19 '14 at 1:07
10
\$\begingroup\$

You are on the right track with your notion of using files to help alleviate the amount of hard-coded behavior you have. You want to make your game data driven as much as possible: it isn't a complicated concept, it is exactly what it sounds like. Drive the game behavior via data rather than directly via code.

A good mindset to take when determing how to drive some system via data is to look for the generalities. What things are in common between all instances of these systems? The commonalities become properties of the system, and the values of those properties are the data. Rooms, for example, usually all have a description and a list of exits. They may also have an "inventory," a list of items that are in the room.

One option you can persue is to use plain text or XML files (both of which are fairly straightforward to parse in C#) to store room data and contents.

Consider an XML structured file like this:

<room name="Study">
  <description>
  You enter a well-furnished study. A heavy wooden desk sits in one corner, an ugly lamp illuminating its surface.
  </description>
  <exits>
    <exit command="north">Hallway</exit>
  </exits>
  <items>
    <item name="Pen">
  </items>
</room>

This simple structure defines exactly what I listed above. A cooresponding Room class would have properties for the Description, a List<T> of exits (which are references to other rooms and the "go" command used to get there, in the above example going north would take the player to the hallway). There's also a List<T> of items.

Rather than put a while loop in a function for each room (which you can't do now since you only have a single Room class anyhow), you make a more generalized main loop:

while(!done) {
  Console.WriteLine(currentRoom.Description);
  var command = Command.Parse(Console.ReadLine());
  switch(command.Verb) {
    case "go":
      nextRoom = allRooms[currentRoom.GetExitForDirection(command.Object)];
      if (nextRoom == null) {
        Console.WriteLine("You cannot go that way.");
      }
      else {
        currentRoom = nextRoom;
      }
      break;
    ...
  }
}

Note that the Command.Parse function is left as an excersize for you, but should basically parse user input and return some kind of "verb/object" pair or similar (see this question for a kickstart on doing so, it's a bit beyond the scope of your question). In the above example, the verb would be "go" and the object may be "north" or "south" or whatever.

But beyond that, what this loop is doing is presenting the rooms in a generalized fashion; every time through, you print the room description, wait for user input. If the user input is "go to some other room," you find the exit of the current room coresponding to the direction the user entered. If there is no exit in that direction, say so, otherwise set the current room to that new room. Then repeat.

You can continue to refine this approach (for example, the above prints the room description after every command; can you see how to make it print the description only the first time you enter the room? How about that plus when you type a "look" command?). You can also scale it out to include handling of items in a similar fashion.

\$\endgroup\$
  • \$\begingroup\$ Thank you dearly for your support josh. i will attempt this and try to develop progress as much as i can \$\endgroup\$ – Mohamed Serry Jan 19 '14 at 19:33
1
\$\begingroup\$

If you know html, you can think of the rooms as webpages, the exits as links, the actions perhaps as anchors and the game itself as a browser. The only additional thing the game needs to manage is an inventory and NPCs, which is basically a static class or two with the state of each item and character in the game, has it been taken, was it used/ talked to already, has it been destroyed/ defeated.

If you use html instead of pure xml in a similar way to what Josh described, you could debug in the browser, at least as far as navigation goes.

\$\endgroup\$
  • \$\begingroup\$ josh's answer is more technically thorough and directly relevant, but this analogy is pretty good and may help understand the overall concept \$\endgroup\$ – jhocking Jan 19 '14 at 13:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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