G'day....
So the new year is upon us and after taking a few days off to do family things over the holidays I managed to get some time into my Test Adventure Game Project. As mentioned in the last DevDiary I wanted to build a base skeleton for the game so I could work on the meat of the project, which is the Command Interrupter. My goal for this phase was simply to implement classes for Player, Level, Room, Exits and Items. That way I could sit in a test room, with a few items lying about so I can build an test my command processing code by interacting with that room and those items.
That is all up and running now. So the game loop is running, and I get to enter commands and stuff, and there is a room to look at and items to interact with, but at this moment there is no logic to "understand" anything or "do" anything.
To do this though I also had to build my DataReader class, as I have always wanted the meat of the "game design" to be done externally form the coding. The goal here was to build data files for rooms and items that the game reads from. Allowing me to quickly edit descriptions and even set boolean flags without ever having to touch the code. In addition my plan for the command processor will be using dynamically built word lists and the DataReader will be used for this as well to construct those lists from files. (more on the actual command interpreter when I get around it it)
Building the DataReader was a little more fiddly than I thought.
I went through a few iterations of methods and towards the end of the coding phase (a phase is what I am calling a short term project goal) decided that "bracketed" data is probably the best way to do it. Unfortunately I was so deep into using line by line reading that I didn't want to redo everything. I may still redo things, but as I said the testing environment is up, so I will probably just move onto the command interpreter.
Examples of DataFiles
Room DataFile Example @PasteBin
- Name
-
Room_Description
- Default room description that always prints on on any given "Look-Room" command. The idea is for this text to have appended onto it any other "Look-Room" information that may be required by cycling through the objects in the scene.
-
Exit Brackets
-
These are two text lines that can be searched for to find the given index number for the start and end of a individual item information.
-
Exit-Name
- Contains the name for the individual Exit.. like North... or "Road into Forest".
-
Open
- This is a Boolean value that tells me if the exit is closed or not at initialisation.
-
Look-Room-Closed
- text description that is to be appended to the default "Look-Room" result. If the exit is CLOSED.
-
Look-Room-Open
- text description that is to be appended to the default "Look-Room" result. If the exit is OPEN.
-
Look-Exit-Open
- This is the description of the "Look-Exit". So when you actually examine the exit itself. If the exit is currently OPENED.
-
Look-Exit-Closed
- This is the description of the "Look-Exit". So when you actually examine the exit itself. If the exit is currently CLOSED.
-
Use-Open
- Text response if the "Open-Exit" command is successful.
-
Use-Closed
- Text response if the "Open-Exit" command is a failure.
-
Exit-Name
-
These are two text lines that can be searched for to find the given index number for the start and end of a individual item information.
-
Item List Brackets
- List as many items here to fill room. Each item name corresponds to a physical item data file to be read and imported into the room object.
Item DataFile Example @PasteBin
- Name
-
Get-able
- a booleen value to determine if the object is able to have the "Get-Inventory" command run on it.
-
Description_Room
- Text description that is to be appended to the default "Look-Room" result. If the object is in the scene and not picked up.
-
Description_Dropped
- Text description that is to be appended to the default "Look-Room" result. If the object has been placed in the room by the player.
-
Description_Gone
- Text description that is to be appended to the default "Look-Room" result. If the object has been removed from the room.
-
Get-Item-Success
- Text to be printed when "Get-Item" is SUCCESSFUL.
-
Get-Item-Never
- Text to be printed when "Get-Item" is done on an object that is never allowed to be gotten.
ReadData-Room
- At this time I have 2 Data Files in the project. ROOMS and ITEMS.
- Each individual room or item is a separate file in either the room or item folder
- Each DataFile is read into a List<string> using File.ReadLines().
-
I then read those lines looking for keywords at the start of each line using .StartsWith()
- or I read a section of the file into lines between two brackets
- Those found lines are then cleaned and added to the room's object as data.
- Also the room DataFiles contains a names of items, which match the file names item data files. These datafiles are in turn processed to build the items that are then added into the Room.
- This entire process of adding a room to the level map is boiled down to a single command "LevelMap[x, y] = DataReader.ImportRoomData(string name);"
I am reading the DataLine by line, as you can see in the text files each line has its own "keyword" at the start of the line. Even if it is a long string. The entire text file is read into the application, ignoring any empty lines. It then processes each line looking for the keywords at the start of the line. If the keyword is found, it removes that keyword and then uses the rest of the line as data by plugging it into various variables for objects in the game.
This is all working pretty well. Though I came to a issue with adding multiple exits.
I wanted to be able to add as many exits as I liked and I didn't want to have to code each exit keyword to be unique. This lead me to working out that the Line by Line reading is probably not the best. As you can see I now have a EXIT_START and EXIT_END keyword, with the data for that unique exit inside. What the code dose now is look for EXIT STARTs and tally the total exists in the file. At the same time is it tallying and recording the indexVale in the List<string> for those "start and end" bracket lines. I can then feed those into a method and do the keyword search to extract the data on a targeted "section" of the file instead of the entire file. It can even loop by the total found count to automatically add things as I edit the text file.
I think this idea is a far better way to handle line reading when trying to extract data. I will be using "brackets" from now on until I work out something better.
Forward Ho!
Right.... so the test environment is up. I may have to look at adding more or changing the actual data being extracted but I think the extractor is robust enough for my needs as well. So now the fun part starts! Building my Command Interpret.
See Ya Next Time
--A4L
Test Print of a testRoom with Three exits and 4 Items (I have not printed out all the item properties)
G'day, hope it's going well. I'd say your ideas overall are quite good. Consider using a standard format such XML or JSON (or other structured text) however. This will save you the time of designing the format of the 'design language' itself and you can concentrate on the data format (the schema in XML). Plus you get many ready-to-go reader/writers.
I know you've said (in a forum post) that this is a coding exercise, so if that's the case then fair enough and just ignore.
8<> --------------------------------------
Follows the post I was going to put in the forum, auto-merged here with my previous post.
8<> --------------------------------------
I guess you wanted something like below. There's no need for casting/conversion methods.
But back to your requirements.
Do you mean parser? Many books have been written just on this subject. But obviously you'd be wanting to keep it simple to start.
So I can see why you were experimenting with that test code. But I'm not sure this is the right approach. Each object is not going to 'get' itself. But it might be useful perhaps as a 'reaction' to being taken animal.react(take) { say( "it struggles and squirms")}, person.react(take) { say ("I don't think so") }. Your game engine might be the 'thing' that does the 'getting', being passed the object in question.
Not sure what you mean here.
Not sure what you mean here either. With the highlighted part, do mean you need with visual studio's debugging features?
----------------------
PS: Is it ok to post this kind of thing here or is the forum preferred?