C++ Workshop - Project 2

Started by
94 comments, last by Warlord_Shaun 15 years, 11 months ago
Project 2 – Overview Welcome all to the second project of the C++ Workshop. Continuing with the theme of the first project, we will move along in our journey towards making an RPG similar in style to Dungeons & Dragons. In the first project you created characters, gave them ability scores, and had them fight 1 on 1 in an arena environment. However, RPG’s are much more than combat. They’re also about exploration and discovery, and there’s not much to discover in an arena. So in this project we will be breaking out of the arena. Project 2 – Introduction In graphical video games, as in life, what you can see is only limited by your range of vision and your field of view. Although you may not realize it, your eyes take in vast amounts of information in a microsecond, allowing your brain to identify objects, determine the presence of danger, and to become aware of the weather, atmosphere, and mood – for as far as the eye can see. In pen & paper RPG’s, as in text RPG’s, your awareness is much more restricted. If I (or the Dungeon Master) were to try and describe to you everything the eye could see in one sitting, we’d be reading paragraph after paragraph for days, and you’d never get an opportunity to actually DO something. To make the transition from visual to text environments easier, the world is often broken up into smaller, more manageable chunks called rooms. “Imagine you’re standing on a small hill in an open, circular field of dark green grass. The field stretches in all directions and extends almost as far as you can see. At the edge of the field is a forest, which surrounds you on all sides. You notice that to the north the forest has a small opening, and to the south you hear the sound of flowing water. The wind is cool, the air is dry, and the sky is blue and bright above you.” The above is an example of a description which might be read in a “room.” You’ll notice that in the example, its not really a room at all. In fact, it’s not even inside, but outside in an open field. The reason its referred to as a “room” has more to do with the subdivision of the world and the existence of exits, than with the fact that it emulates an actual physical room. When I say the room has “exits,” I mean that there are paths to follow, directions to head, ways in which you can get from this “room” to the next “room.” In the description above, there are two logical exists, north, and south. If the user were to exit either north or south, they would leave the current room and enter one of the adjoining rooms. So if the example “room” above was an entire field, how big is a room normally? Well, a room is as small as possible, in order to contain all relevant information. You notice in the room above that there was very little content. An open field, trees, and a bit of weather. There were no buildings, obstacles, people, objects, or even distinguishable landscape, other than the hill you were on. So it was quite feasible to absorb all of that information in a single paragraph. Now, imagine trying to describe the entire city of New York. It would be impossible to do in a single paragraph and be able to effectively communicate to the user the weather, the people, dangers, and all the shops and stores that would be possible to explore. It goes without saying that you’d more likely divide the city up into city blocks, with each block being described in a single “room.” Or better yet, imagine you’re inside of a medieval castle. The castle itself is smaller than a New York city block, and definitely smaller than a field as large as the eye can see, but yet, you’d still likely subdivide the castle into dozens of rooms representing the actual rooms and hallways of the castle, because that’s all the eye can see. As well, the zoomed in level of detail necessary to see the books on the shelves, the paintings on the walls, and the furniture in the room requires a much smaller subdivision. Which leads me to the next topic. As you’re exploring a medieval castle or dungeon, you’ll often see things lying around. Things such as furniture, armor, weapons, treasure chests, and even piles or coffers of money. Sometimes these things are merely part of the description – such as the furniture. Other times, however, you need to be able to pick up and interact with the object – such as the weapons, armor, or coffers. These require physical objects which you can take, examine, and put in your inventory. Once in your inventory, you want to be able to open it, equip it, or drop it. This implies that you have an inventory, perhaps a backpack, which, much like the room you’re standing in, is a container for other objects. And finally, different types of rooms allow you to do different things. For example, a room in your house might perhaps just have a bed which allows you to “sleep.” While a room in a bank might allow you to “check” your balance, “deposit” some money, or even “withdraw” some money. Another example might be a shop, which allows you to “List” the inventory, “Purchase”, an item, or even “Sell” something from your inventory. Project 2 – Conceptualization This program is a continuation of the program created in project 1. It will again consist of various menus and submenus, however the menus and submenus will now be different depending upon which room you’re in. The primary functionality will be the ability to move in an out and explore different rooms. Each room will have its own description, exits, and contents – which includes objects and other characters. While in a room you will be able to interact with objects, pick up equipment and put it in your inventory, and fight against the other characters which are in the rooms, much as you did in the arena. If you defeat a character, you may then loot his body in order to take any equipment or coins he may have had on him. Some characters will be non-hostile, meaning that they do not attack you when you enter the same room with them, however some of them WILL BE hostile, and will engage you as soon as you enter, so be prepared. As with before, you may create a character, view your stats, and gain experience and level as before. You no longer automatically gain coins for defeating a character (but you can loot their corpses), and you no longer purchase armor and weapons via the main menu. Now, your character begins with a basic, level 1 set of gear and you must enter weapon, armor, and potion shops in order to purchase new equipment. If you should die while fighting in combat, your body is left on the ground where you fell, and you return to the starting room where you began with a new body. All coins are taken by the character that defeated you (and can later be regained by defeating them), but your equipment is left on your body. To prevent losing all of your coins when defeated in combat, it would be wise to store some of it in a bank while exploring. You can reclaim the items by returning to your body and entering your corpse. Project 2 – General Analysis Use Cases 1. Entering The Game When the user first executes the program they will be shown a main menu similar to that displayed below. When the user makes a choice the screen will be cleared and the user will be shown a new menu or screen depending upon which choice was made. It is important to note that “Enter World” will only be shown if a character has been created. If not, “Create Character” is the only option available. ============================== Main Menu ============================== Menu Options: a. Create Character b. Enter World Q. Quit ============================== Choice: 2. Creating a Character When the user selects the option to create a character they will be shown a menu similar to that shown below. If the user selects “Name Character” they will receive a prompt allowing them to enter a name for the character. If the user selects roll for stats, then he will enter a loop where he can continue to “roll for stats” until he finds a suitable distribution. Returning to the previous menu clears the screen and then once again shows the main menu. 2a. If the user has already created a character by previously entering this submenu then entering the “Create Character” menu additional times should first prompt the user that they have already created a character, and that continuing will result in the removal of the old character to make room for the new. If the user opts to continue to “Create a Character” then the menu below is shown. If they decide NOT to create a new character, they will simply be returned to the main menu and their previously created character will remain. ============================== Create Character ============================== Menu Options: a. Name Character b. Roll for Stats R. Return to previous menu ============================== Choice: 3. Entering the World After the user selects “Enter World” they should be taken to a starting room. This can be any room you like, however it should always be consistent, and should be safe from opposing characters or monsters. Typical choices are a Church/Cathedral, a Town Hall, or an upstairs bedroom in an Inn. When the character is transferred to the starting room is should be treated as entering any room. See Below. 4. Entering a Room When a player enters a room they should be shown a screen similar to that listed below. It should show the title of the room, the long description, the exits, and any objects or characters in the room. After all of those have been shown, a menu will appear which lists the available choices. The menu should be dynamically, with directions for exits, “Examine objects” if there are any objects in the room, “Attack” if there are any other characters in the room, and any shopping or banking options as will be discussed later. Additionally, the “Character” option should be available in all rooms. ============================== The Grassy Hill ============================== You’re standing on a small hill in an open, circular field of dark green grass. The field stretches in all directions and extends almost as far as you can see. At the edge of the field is a forest, which surrounds you on all sides. You notice that to the north the forest has a small opening, and to the south you hear the sound of flowing water. The wind is cool, the air is dry, and the sky is blue and bright above you. Obvious Exits: North, South A small tombstone A broadsword ============================== Menu Options: n. North s. South x. Examine Objects c. Character q. Quit ============================== Choice: 5. Using Exits Using an exit simply transports the user from one room to the appropriate connected room. The screen is cleared and they are shown a new screen appropriate for entering the new room. 6. The Character Screen Whenever the user selects the “Character” screen are they choosing to view the information about their character. The screen should be cleared and they should be shown the View Stats menu from project 1. Additionally, the screen should contain 3 new options – V. View Inventory, E. Equip Items, and R. Return. Selecting either of the first 2 will show them a submenu, select R will return them to the view of the room. 6a. Viewing inventory simply gives the user a numbered list of all items their character is currently holding in their bag. From the Inventory screen the user may select any of the items by number which then prompts the user if they’d like to drop the item. Selecting yes drops the item, selecting no returns the user to the Inventory Menu. Additionally, the user may select ‘r’ for return to character screen. 6b. When the user opts to Equip Items, they should be shown what’s currently equipped (armor & weapons) and they should be shown a numbered list of all items in their inventory which can be equipped. Selecting one of those numbers swaps the item currently equipped with the item they selected. The last 2 numbers should be reserved for “remove weapon” and “remove armor,” just in case they want to remove it without first equipping something else. 7. Examining Objects When the user views a room they are shown a list of items in the room and are also given a menu option to “Examine Objects.” If the user selects that option they are taken to a sub-menu which again lists the items in the room, this time numbered. Selecting a number prints the description of the corresponding object, and also gives the user the option to view contents if the item is a container. Additionally, while viewing the object’s description the user may opt to “take” objects which are equip-able, such as weapons and armor, or small enough to carry such as potions or coins. If the object is a container and the user selects to view its contents, they are shown a sub-menu identical to that shown to “examine objects” with all items within the container numbered, etc…This system of objects within objects, and a menu with numbers to examine and then take objects is recursive, and works until all objects within objects have been examined. 8. Attacking Mobs If the room the user is currently in has other characters (non-hostile) they are shown a menu option called “Attack.” Selecting that item will list the characters in the room so the user may decide which character/monster they would like to attack. Once that has been done, combat begins similar to the way in which it was done in project 1, with one small change. 8a. After each round of combat (after both characters have attacked/defended), the user will be shown their hit points and a menu. The menu will contain three options – Attack, Use Item, and Run! Selecting Attack will cause combat to progress for another round. Selecting “Use Item” will show the user a list of items in his inventory which are “Consumable,” such as potions. Selecting one of those items will cause the user to drink the potion, and then continue with the current round of combat. Drinking a potion counts as the user’s turn for that round, so they will not get an opportunity to attack, but they WILL be attacked. Selecting “Run” will usher the character out of the room, in a random direction. (hope they don’t run into a room with a hostile mob). 8b. Attacking a mob and then running flags that mob as hostile. The next time you enter the room, the enemy will continue their attack, however you automatically gain the initiative and get the first swing. 9. Hostile Mobs Whenever you enter a room with 1 or more hostile characters, you are shown the description, the obvious exits, and the objects in the room just as before, however combat immediately begins just as though the player had chosen a character to attack, however without clearing the screen, If there are more than one hostile characters, use initiative or a random chance to determine which attacks first. The first time you enter a new room which contains hostiles they automatically gain the initiative. Every time after that, however, the player gains the initiative. 10. Dying If the player is killed in combat they “die.” Their body is left in the room as an object and their spirit is moved back to the starting room. While a “ghost” the player may only move between rooms and examine objects. They cannot view their stats, open objects, or engage other characters, either hostile or non-hostile. Additionally they cannot shop or bank. Upon returning to the room where they were killed they are given an additional menu option to “Enter Body.” Doing this brings them back to life, with 10% of their full health. If they were killed by a character which was originally “non-hostile” then the character does not attack. If the character was flagged as “hostile” then they will immediately attack once again. As the player has obviously been in this room before, they get the initiative automatically. (Take this as an opportunity to flee.) 10a. When an enemy kills you, they take all of your coins. You may regain those coins upon defeating them, and then examining and opening the corpse. 11. Banks Banks are special rooms which follow all of the rules above, with the addition of a few new menu choices. In a bank you gain the ability to “Check Balance”, “Deposit”, and “Withdraw.” Selecting “Check balance” prints the amount of money you have in the bank, and then reprints the menu “choice” prompt, without clearing the screen. Selecting either Deposit or Withdraw takes you to a suitable sub-menu, where you are shown the amount you can deposit or withdraw, and then a prompt asking you for how much you’d like to deposit or withdraw, respectively. From any of these menus you may “return” to the bank by using the “Return” menu option. 12. Shops Shops are special rooms which follow all of the rules above, with the addition of a few new menu choices. In a shop you may “List” the items for sale, or you may “Sell” something of your own. Selecting “List” displays a numbered list of items for sale, with the amount and attributes of the items identical to the system used in Project 1. Selecting “Sell” will show you all the items in your inventory, along with the prices being offered by the shop. By default, sell prices are 1 / 4 the purchase price. Project 2 – Conclusion By the time this project is over you should be able to create a character, move around in the world, and either collect objects or engage other characters in combat. This is no small project and I very much look forward to seeing what the members of this workshop can come up with. I’ve made every effort to make the analysis thorough enough that you should be able to come up with a pretty accurate design. However, its always difficult to describe a task to someone when you already have the design and implementation in mind. If there’s anything I was overly vague on, or left too much to doubt, please feel free to ask in this thread. Additionally, please feel free to post any design or implementation questions you have. You may notice that in some places, such as the costs of items, what items there are, and what potions exist that I have not specified anything. This was intentional. Use your imagination. As well, this project description should be viewed as a guideline for testing your skills. It should be treated as a minimum specification. If there’s other things you’d like to add, ideas you have of making the project more enjoyable or interesting, please feel free to post those ideas here on the forum and implement unique features as you see fit. Cheers and good luck!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
Advertisement
I had already started doing some of these upgrades to the orginal project for fun.
So. We're making a single playing MUD.

AWESOME!!
Quote:Original post by linkofazeroth
So. We're making a single playing MUD.

AWESOME!!


You do know that MUD stands for Multi-User Dungeon, right? [smile]

The project goes in a very interesting direction. Be aware that you'll have to work a lot on what you already learnt. This is not an easy task, so don't give up!

Good night, and good luck!
Yes, I do... but how else would you describe it? I play a MUD called Achaea that's very very similar to this. Now, that might make it easier on me since I know how a MUD works.. basically.. but I'm not sure how I'd set up monster entities, how to 'generate' rooms, etc.

Oi. This is going to be hard.

BUT FUN!
Can anyone give some possibilities for map/room traversal? My first inclination would be to create a vector of room classes. Each element is a class "Room" where the element # is the room ID and that contains the map description, exits, the room ID #'s of the exits, drops, examinables, and npc's. The player's position gives a room ID that loads that particular room and when he exits he goes to the room ID of the exit.

ie
Class Room{	string Description;	vector<Object> Objects;		bool NorthExit,SouthExit,WestExit,EastExit;	int NorthExitID,SouthExitID,WestExitID,EastExit,ID;}vector<Room> Map;Map[1].Description="hi there";Map[1].NorthExit=true;Map[1].NorthExitID=25;//if player goes to the northLoadMap(Map[25]);


Is there a better way?

p.s. Thanks' JWalsh for coming up with these fun projects. This one is definitely going to take a while, but be a fun challenge. When it's over we'll have a great RPG system in place that can easily be upgraded to a 2d adventure.
Quote:Original post by ChurchSkiz
Can anyone give some possibilities for map/room traversal? My first inclination would be to create a vector of room classes. Each element is a class "Room" where the element # is the room ID and that contains the map description, exits, the room ID #'s of the exits, drops, examinables, and npc's. The player's position gives a room ID that loads that particular room and when he exits he goes to the room ID of the exit.

ie
*** Source Snippet Removed ***

Is there a better way?


That's a pefectly valid method. However, there's no need to store the bool about whether the direction exists or not, just initialize the room ID to -1 for that direction. That indicates "no exit," since you cant have a negative index.

Also, you could potentially store pointers within the objects to the adjacent rooms, similar to the way tree structures often contain pointers to their child nodes; Creating a "web" of rooms. ie..
class Room{public:  ....protected:    Room* m_pNorth;    Room* m_pSouth;    Room* m_pEast;    Room* m_pWest;};


Then when the user follows a path, you just update a global "location" pointer with the address of the new room, then call "DisplayRoom()" or somesuch on the pointer with the new location.

Also, suppose you want to have exits other than just north, south, east, and west? What if you want up and down? Would you go back and add 2 more variables for every room in your world (int or ptr), even if they dont use that direction?

Which brings up a good point, if you've got rooms with variables (integers ID's or pointers) which are frequently null or -1, it seems like a potential waste of memory.

Perhaps there's a more dynamic way to do this. Perhaps you could tell the rooms which directions they support on construction? maybe add:
class Exit {   ...protected:   int m_RoomID;         // ex. 5   char m_MenuChoice;    // ex. 'n'   string m_Direction;   // ex. "North"}vector<Exit> m_Exits;

or some-such. [smile]

Then you can GetExits() when you display the room and use that to show the menu. Then when they enter a menu option, check it against the menu choices stored in each Exit...ie.
for( int i = 0; i < m_Exits.length; i++ ){    if( choice == m_Exits.GetChoice() )       ....}

Anyways...just some ideas and food for thought.

Cheers!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
Quote:Original post by ChurchSkiz
p.s. Thanks' JWalsh for coming up with these fun projects. This one is definitely going to take a while, but be a fun challenge. When it's over we'll have a great RPG system in place that can easily be upgraded to a 2d adventure.


Indeed. You're quite welcome. I look forward to seeing what everyone comes up with. And you think this project is complex...wait until Project 3. [wow]
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
Quote:Original post by jwalsh
Then when the user follows a path, you just update a global "location" pointer with the address of the new room, then call "DisplayRoom()" or somesuch on the pointer with the new location.

Or perhaps it shouldn't be a global...after all, maybe other entities will be able to move through rooms...perhaps such data could be stored with the entity...including the player?[wink]
Quote:
Perhaps there's a more dynamic way to do this. Perhaps you could tell the rooms which directions they support on construction? maybe add:
class Exit {   ...protected:   int m_RoomID;         // ex. 5   char m_MenuChoice;    // ex. 'n'   string m_Direction;   // ex. "North"}vector<Exit> m_Exits;

or some-such. [smile]

Which then also gives you the added flexibility of "unlocking" doors and opening secret chambers, amongst other interesting possibilities [grin].

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

This topic is closed to new replies.

Advertisement