C++ Workshop - Project 2

Started by
94 comments, last by Warlord_Shaun 15 years, 11 months ago
Heh, I'm still working on Project 1! (My journal has a to-do list and a few comments)
Advertisement
Quote:Original post by jwalsh
Oh, and as we'll be working on streams and file I/O next week, it may not be a bad idea to implement your room achitecture in such a way that they can be read from disk.

Perhaps have a Rooms.dat file, or 1 file for each room, ie. bank.room, hallway1, room, grassyfield.room, etc.... Perhaps even a .map, .level, or .maze file which contains all the connections between you rooms. In this way you can create new rooms, and new connections between rooms, without having to recompile your application.

Just a thought. =)



Hrm, looks like I should read before throwing any code out there. Ive no clue about how to do that. This makes my 6th or 7th week in toto of programing since comodore basic in the early 80's /shame
Quote:Original post by jwalsh
Well, one way would be to implement your own Pseudo-RTTI, where the base class has a function called "GetItemType()" or some-such, which returns an enum, identifying the type. If the object is of type WEAPON, then it's safe to cast the Item into a Weapon. Like I said, this is one way...however not the only way, and not necessarily the best way.

C++ actually supports RTTI implicitly, and can usually be enabled in the compiler if it's not enabled by default. With RTTI enabled you can use the nifty "dynamic_cast" operator.


For completeness, other common ways of approaching this kind of situation are:

1) Just don't put a Weapon* into a container of Item*s if you are going to care about its Weapon-ness later. Have a separate container just for Weapons instead. Of course, this can get messy quickly, especially considering that almost all types are just as likely to need that kind of "special treatment". Yes, you get the ability to just pull a Sword out of the Room's Weapon-vector, and put it in the Player's Weapon-vector and not worry about the types... but the classes quickly get very complicated. On the gripping hand, note that if Weapon is a most-derived class, you could store Weapons directly rather than Weapon*'s - but that's unlikely to help you (will probably increase your memory management headaches rather than decreasing them) if you're already using pointers in most of the rest of the system.

2) Instead of a direct type-query like GetItemType(), create capability queries, like isWieldable() which might return true for Weapons and false for all other Items. This gives you extra flexibility, because you could e.g. make Potions, Wands and Scrolls - but not Armor or Weapons - be isHoldable(). Sometimes, this points to a need to add a level to the inheritance hierarchy (i.e. HoldableItem), but sometimes it's not that clear-cut. But if you can avoid this approach (in favour of a better-designed inheritance scheme and/or the build-in RTTI with dynamic_cast), then you probably should avoid it. It often quickly degenerates into implementing your own RTTI instead of letting the language do it for you, and anyway you usually want member functions to do stuff(TM) when possible.

There are always trade-offs to be made. Getting a good design will require you to Think(TM). Happy hacking (cheers Olu).
Thanks Zahl. I knew I forgot some options. =) Both of your suggestions are good possible alternatives.

[OPINION]
When trying to figure out the best design guys, just remember good engineering philosophies. You want it encapsulated, modular, and easily maintainable. This often amounts to doing it whichever way requires the least amount of user code, as this frequently means less work on your behalf, less to encapsulate, less to modularize, and less to maintain.

If the language or compiler does something for you...let it. =)
[/OPINION]
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
Wow, this project is even better than I had expected. I have been on a training in Belgium the last week so I didn't have time to read this earlier.

I'm gonna start on it immidiately. Good job Jeromy!
I thought the other characters in the game (not you) would be created randomly, and destroyed when exiting a room. Then other random characters will or wont be created should you re-enter the same room. but then theres this:

Quote:Original post by jwalsh
...All coins are taken by the character that defeated you (and can later be regained by defeating them)...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.


oh, so characters are static, or, at least the one who engaged me. should all other characters also be static? and only re-created randomly after player defeats a character? seems abit weird though, what if a hostile character decides to go home? but no, he cant, he must stay around until player engages him again because he is flagged as hostile, or because he's holding my coins...somewhat weird
Quote:Original post by kingIZZZY
I thought the other characters in the game (not you) would be created randomly, and destroyed when exiting a room. Then other random characters will or wont be created should you re-enter the same room.


I don't see where you get that from. I would say that the set of characters in the game is generated randomly at the start (possibly with more added at time and/or turn intervals), and when you leave a room, everything that was there just stays there until you come back.



Anyway, I got the go-ahead to show you guys this thing I was working on recently. (To understand the name, you will need some background.) This may be a useful way of handling those Items: it's a way (actually a combination of general-purpose C++ techniques) of handling the memory management and getting objects (rather than pointers) to show polymorphic behaviour (it simply works by making an object that's a wrapper for the pointer; it does the memory management on the pointer, and uses the pointed-at object in order to behave like an object of that derived type). Please try to understand everything if you want to use this :)

In that setup, you should be able to handle dynamic_casts with code along the lines of (integration is left as an exercise):

// Return a reference so that we can keep on using the object syntax.// (Polymorphism works upon references the same as on pointers.)// Notice that dynamic_cast can cast references too, but because there is // really no such thing as a "null reference", it doesn't have an effective// return value to indicate an error. Therefore, a failed cast throws an// exception - std::bad_cast, IIRC. If this is unacceptable, to you, you might// want to bite the bullet and return a pointer (implementation left as // exercise).template<typename Impl>Impl& Animal::as() {  return dynamic_cast<Impl&>(*impl);}// Used like...#include "Animal.h"#include "Chicken.h"Animal x = someCodeCreatingOrFindingAnAnimal();// I "know" x is a Chicken...x.as<Chicken>().scratchInDirt();

Does the std library have a linked list? I have been looking for a good implementation but I can't find one.

I thought a linked list would be the best way of storing my Room's, seeing that I have to iterate over them a lot.
Of course it does. It's in header '<list>', and it's called 'std::list'.
Quote:Original post by Deyja
Of course it does. It's in header '<list>', and it's called 'std::list'.


Great, thanks.

This topic is closed to new replies.

Advertisement