Make constant available command

Pages: 12
So to learn C++ im making a basic text based game. I can make dision trees and stuff but how would i make a command that can always be axesd like an inventory so if you pressed I it would open up your inventory.
How is your game system set up? How do you get events/read input from the player?
ITs not that good but i use this cin >> aclass; then check it wiht a if(it will take forever) not sure how to do it a better way but i know there is. If you want its its realy small i could post it.

Edit: im using string for everything not integers so its kinda stupid but... Also any pointers its annoying because i would have to make a huge decision tree with a ton of ifs any way to clean it up?
Last edited on
ANyone?
It's certainly possible (might want to look at ncurses), but the console isn't designed for such things - the console and games don't mix.
?? Not sure what you mean, but i just would want to make a constantly available command so if you typeed in so any time you typed in "I" it would do something

Edit: ohh i know its not really designed for it but wanted to try.
Last edited on
Text based games are actually quite difficult to program efficiently because they are so heavily event-driven.

You will either need to spend a good deal of time designing a storage mechanism for your events, or you will need to have one or more tremendously long "else if" chains.

As Athar says, I don't really recommend a text based game, especially not in the console. A simple Galaga-style shooter with a graphics lib would actually be much easier and would do a better job of introducing you to how program flows in a video game.

If you want to start with a graphic lib, there are many available. SFML and SDL are both very popular (google them). SFML is generally better, faster, and easier to use once it's installed, but is more difficult to install, whereas SDL is easier to install, but a little more difficult to use and not as fast.

Or... if you want to stick with a text adventure game... sit down and buckle up...


Beginners like to hardcode things. You probably have something like a function for every room which prints a description and whatnot. And in that function you watch user input and move to another room or trigger some kind of action depending on what the user inputs.

That is a poor design. One reason it's a poor design is because of what you are trying to do now. You want to have a universal 'I' command that checks your inventory, but you don't want to put that command in every single room in your code. The problem is your underlying design is flawed so there's no way around it unless you redesign.

What you want to do is have some kind of data structure which represents the room. You then write code that works for ALL rooms, and simply use different data for each room. This way all your code is in one spot.


For a basic example...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct RoomData
{
  string name;
  string description;
  string exits[4];  // N,E,S,W
};

RoomData room1 = {
 "Room 1",
 "You are in a dark, cold room. There is an exit to the south.",
 "","","Room 2",""
};

RoomData room2 = {
 "Room 2",
 "This room is blazing hot!  There is an exit to the north.",
 "Room 1","","",""
};


As you can see, the south exit in the room1 data leads you to room2, and the north exit in room2 data leads you to room1. Now in your code, you would simply print the description of whatever the current room is, rather than printing static text.

Once you get this foundation set up, adding new rooms requires 0 code changes. All you have to do is add/modify the existing room data.


The reason why text adventure games are so difficult is because room and event data tend to be significantly more complciated to store in a generic structure like this, since a specific item will often only work in a specific room.


Also -- in the above example I put the room data in code as an illustration, but in practice that isn't wise. You're better off storing that kind of information in an external file (like a text file) and reading it during game execution. That way adding new rooms doesn't even require you to rebuild.
Last edited on
C++ doesn't know the fact that you pressed an "i" until you press ENTER. C++ understands input (stream of characters usually coming from keyboard) and output (stream of characters usually going to you monitor). Without extra libraries (like ncurses) it's not designed to interact with a user in an interactive, "game-like" way.

That's why many here will tell you to just move on to a graphics library which can handle events, pixels, sounds, music, etc., etc... Because if you're going to learn to eventually make real games, why waste time forcing the console to do something it was never intended to?

I suggest you just keep this text game REALLY simple and use it to learn C++ basics until you get comfortable with OOP and creating classes. Then move on to bigger projects that need external packages when you're ready...

Oh yeah, to answer your question: A command that can be defined once and then used again and again inside a program is called a function. To call it in console code you'll still have to press "i" and then hit ENTER of course. You can read about it in the tutorial here on this site.

A better choice would be to turn that function into a method (that's a function owned by a class). Keep reading the tutorial to learn about those...
Ok thank you 2 things. FirstDisch is that code you used what are those arrays? ANd is there any tutorial on them because they look really efficiently. And how would i do it with a text file if i did? ANd to cnoeval would i do if button is pressed or what to detect it? Thanks All!
Last edited on
Yes I am using arrays and structs in that example. An array is just a group of a single kind of variable (here, 'exits' is an array of 4 strings), and a struct is just a bunch of different kinds of variables grouped together for convenience.

What I would recommend for a beginner project is that you store all your data in simple text files, where each line in the text file represents a different field.

So with a very basic struct:
1
2
3
4
5
struct RoomData
{
  string description;
  string exits[4];
};


Here we have 5 fields. So your text files would need to have 5 lines.

room1.txt
1
2
3
4
5
This room is dark and cold.  There is an exit to the south


room2


room2.txt
1
2
3
4
5
This room is hot.  There is an exit to the north.
room1




Your simple game can just keep track of which room it's in, then load that room's text file and print the appropriate display message.


That's how I would start. Once you have that working, and you can move around to various rooms, then start adding other, more complicated stuff. You should be able to do that much with just a basic understanding of arrays, and file i/o.
Last edited on
Ok looks great thanks. Do you now any tutorials on how to read a text file?

Edit: But as i said before you would have to gather data in some way to press I but that would have to be somewere in my script and would be executed once...would i have to make an if every single time for if i was pressed.
Last edited on
Do you now any tutorials on how to read a text file?



Look up ifstream on this site. It's very simple, you just get lines of text with getline:

1
2
3
4
5
6
7
string firstline;
string secondline;

ifstream file("myfilename.txt");

getline(file, firstline);
getline(file, secondline);


But as i said before you would have to gather data in some way to press I but that would have to be somewere in my script and would be executed once...would i have to make an if every single time for if i was pressed.


Do you know about loops?

Your primary game loop will look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// this is greatly simplified, but you should get the overall idea
int main()
{
  bool gameRunning = true;
  RoomData currentRoom;
  currentRoom.LoadFromFile("room1");

  while( gameRunning )
  {
    currentRoom.PrintRoomDescription();

    // get user input here, process 'i' command or whatever
    //   if the user wants to move to another room, refill 'currentRoom' with the data
    //   of the room they're moving to
  }
}


The printing of the room description and user input processing will keep looping until you set 'gameRunning' to false, at which point the loop exits. This way you only need to write the input handling code once -- it stays in one part of the program because all rooms share the same code.
Ok. I have tried this for the file.
ifstream file("StartingRoom.txt");
but it give me errors. Not sure were or how it gets it but if you could help.

I tried this just to see if id get errors.

#include<iostream>
using namespace std;

int main(void)
{
string firstline;
string secondline;

ifstream file("TESTER.txt");

getline(file, firstline);
getline(file, secondline);


system("pause");
return 0;

}
Last edited on
1
2
#include <string>  // if you're using string
#include <fstream>  // if you're using ifstream 
Ok thank you. One mroe thing im finding a file within the folder the program is in. Could i make it something like C:/folder/folder/tester.txt ? Also how could i make it a variable the file name?
Last edited on
Yes to both questions. (edit: I just noticed your second question is "how" not "can I"... so "yes" was not a sensible answer. But the below example should illustrate how to do it anyway)

Just remember that ifstream takes a char*, so if you are using strings, you will need to use the c_str function:

1
2
string filename = "C:/mypath/myfile.txt";
ifstream myfile( filename.c_str() );
Last edited on


THANK YOU FOR HELPING ME




EDIT::
I got this to work but it does not show the text from the file. It does put the new lines there but no text.... I also tried this

string filename = "C:/mypath/myfile.txt";
ifstream myfile( filename.c_str() );
and it did not work

#include<iostream>
#include <string> // if you're using string
#include <fstream> // if you're using ifstream
using namespace std;

int main(void)
{
string firstline;
string secondline;
string curroom = "StartingRoom";
string command;
ifstream file("StartingRoom");
getline(file, firstline);
getline(file, secondline);

cout << firstline << " \n" << endl;
cout << secondline << " \n" << endl;




cin >> command;

if (command[0] == 'a'){//Help
cout<< "hi"<< endl;
}


system("pause");
return 0;

}
Last edited on
?
Compiles and runs just fine here. Maybe it's not finding your "StartingRoom" file. Note the name of it is "StartingRoom" and not "StartingRoom.txt" so maybe that's the problem? Your file has to match the name with extension.
Pages: 12