List structure for c++ game - c++

I'm making a very very basic game in C++ to gain some experience in the language and I have hit a bit of a brick wall in terms of progress.
My problem is, while I was designing a class for the player's weapons, I realized I required a list, as I will only have a certain number of weapons throughout the game.
So I ask you, if you were designing this, what implementation would you use for storing all of the weapons in a game? Why?
Here is my code so far for the weapons. as you can see I was just about to start defining all of them manually, starting with the "DoubleBlades"... (Edit* I forgot to note that players should be able to have more than one wepaon, and they can pick up more or drop some, so the list can grow and shrink)
#ifndef __WEAPON_H__
#define __WEAPON_H__
#include <string>
class Item
{
public:
Item(const std::string& name)
: name(name){ }
const std::string& getName(void) const { return name; }
int getID(void) const { return this->itemID;}
private:
std::string name;
int itemID;
};
class Weapon
: public Item
{
private:
int damage;
public:
Weapon(const std::string& name)
: Item(name) { }
virtual int getDamage(void) const = 0;
};
class DoubleBlades
: public Weapon
{
public:
DoubleBlades(int ammo)
: Weapon("DoubleBlades") { }
virtual int getDamage(void) const { return 12; }
};
#endif
Also if you spot any bad habits I would really appreciate letting me know.

I would use the standard implementation (std::list<Item*>) because it's easy to use ("out of the box") and, out of the standard containers, it seems to be most suitable:
You probably need support for fast adding/deleting of weapons (so no std::vector or C arrays)
You probably don't need support for fast searching of the list for a specific item (so no std::map)
BTW you need to have a virtual destructor in the Item class (this is a general rule on base classes in c++).
Oh, and another minor problem - i think the Weapon class does not need the damage member variable - the class doesn't use it and it has private access, so the deriving classes cannot use it either.
You might have to use dynamic_cast in your implementation - a virtual environment such as yours will probably require "safe" casting of pointers from Item* to Weapon*.

On a very basic level, you may not necessarily need a data structure. For instance, if you know exactly how many weapons, etc. you need/may possibly have, you can (wastefully) allocate an array of size n and have certain spots in the array as a pointer to a weapon (if you currently have that weapon, else NULL). Then, simply cast appropriately based on weapon index. But this is a naive approach. Otherwise, refer to Mike's comment above on the original post.

If the list is going to vary in size, I'd use either an std::vector or and std::set. With both, you'll get to use all the nice stl functions and what not. If you use set, it will be quicker to sort the "weapon objects". The vector is more useful if you want to know the order in which a particualr object was added.
If they are going to have a fixed number of weapons you can still use a vector or a set, just make sure you pass the exact size you're going to use to the constructors. This will allow for some optimizations like allocating contiguous blocks of memory (which speeds up access times).

You might actually look at std::map, -- consider something like
std::map<std::string, Item*>
This would allow you to access items by name, which can be nice syntactic sugar, and would allow you to quickly check for existence of an item using the count method.

Related

text adventure - how to add items to 'inventory' struct/class without defining each in advance?

So far this is the most awkward thing I've come about. I have it set for integers to mark how many potions, keys, a player has, but I'm not sure exactly how I can get random items, like rocks, CPU (in the case of Dunnet), stick, shovel, etc.
I don't want to have to figure out every item in the game and assign it a variable. There has to be an easier way. I thought of using two arrays, one a string and one an int, to do the job - but this wont work for a variety of reasons one being I can't do string stringname[10], I see problems associating the two, and... the list goes on, I'm sure it just wont work that way.
Everything else is a class btw, I don't like using structs (but this is going to be used throughout the code, and accessed everywhere), so far my code is:
struct Inventory{
int Keys;
int Potions;
int getinventory() const { return Keys, Potions; }
void addkey(int amt){ Keys += amt; }
void addpotion(int amt){ Potions += amt; }
void usepotion(){Potions -= 1;}
void usekey()
{
if (Keys >> 0)
{
Keys -= 1;
}
else if (Keys << 1)
{
cout << "You do not have a key!" << endl;
}
}
};
I'm definitely still working on the getinventory(), because well, I'm not sure what I'm doing with this code, or even if I'm using it. is the only way I'm going to get this to work, to define EACH variable as I create it in the game and add it in?
I was going to handle weapons and monsters this way... but it just sucks not having a dynamic system for an inventory. I'd like to focus on parsing user input and not have to go back into the header where my main classes are consistently... plus I haven't even fully written the story yet, so I don't know whats happening...
The way this is addressed in LPMuds (and similar) is to create a generic object template. The generic template would have things like a short description, long description, define weight, value, etc.
Specific object types then inherit this class. For example, a potion is an object with all of those attributes but it also has additional actions (functions) that can be taken and possibly different attributes... Taste and color, for example.
Weapons can inherit from that general class, defining things like damage and hit percentage as a generalized notion. A sword can then inherit this weapon (that inherits the generic object) and can be further refined.
In this way, you simply need your inventory to be able to handle a generic object. The objects themselves may define additional attributes and actions. This also means that you don't need to predefine every single object as its own unique variable.
What about creating a structure like this:
struct InventoryItem
{
enum { Key, Potion, Rock, Stick, Shovel } type_;
unsigned int num_;
}
and then have Inventory contain something like a std::vector of InventoryItem.

A better design pattern than factory?

In the code I am now creating, I have an object that can belong to two discrete types, differentiated by serial number. Something like this:
class Chips {
public:
Chips(int shelf) {m_nShelf = shelf;}
Chips(string sSerial) {m_sSerial = sSerial;}
virtual string GetFlavour() = 0;
virtual int GetShelf() {return m_nShelf;}
protected:
string m_sSerial;
int m_nShelf;
}
class Lays : Chips {
string GetFlavour()
{
if (m_sSerial[0] == '0') return "Cool ranch";
else return "";
}
}
class Pringles : Chips {
string GetFlavour()
{
if (m_sSerial.find("cool") != -1) return "Cool ranch";
else return "";
}
}
Now, the obvious choice to implement this would be using a factory design pattern. Checking manually which serial belongs to which class type wouldn't be too difficult.
However, this requires having a class that knows all the other classes and refers to them by name, which is hardly truly generic, especially if I end up having to add a whole bunch of subclasses.
To complicate things further, I may have to keep around an object for a while before I know its actual serial number, which means I may have to write the base class full of dummy functions rather than keeping it abstract and somehow replace it with an instance of one of the child classes when I do get the serial. This is also less than ideal.
Is factory design pattern truly the best way to deal with this, or does anyone have a better idea?
You can create a factory which knows only the Base class, like this:
add pure virtual method to base class: virtual Chips* clone() const=0; and implement it for all derives, just like operator= but to return pointer to a new derived. (if you have destructor, it should be virtual too)
now you can define a factory class:
Class ChipsFactory{
std::map<std::string,Chips*> m_chipsTypes;
public:
~ChipsFactory(){
//delete all pointers... I'm assuming all are dynamically allocated.
for( std::map<std::string,Chips*>::iterator it = m_chipsTypes.begin();
it!=m_chipsTypes.end(); it++) {
delete it->second;
}
}
//use this method to init every type you have
void AddChipsType(const std::string& serial, Chips* c){
m_chipsTypes[serial] = c;
}
//use this to generate object
Chips* CreateObject(const std::string& serial){
std::map<std::string,Chips*>::iterator it = m_chipsTypes.find(serial);
if(it == m_chipsTypes.end()){
return NULL;
}else{
return it->clone();
}
}
};
Initialize the factory with all types, and you can get pointers for the initialized objects types from it.
From the comments, I think you're after something like this:
class ISerialNumber
{
public:
static ISerialNumber* Create( const string& number )
{
// instantiate and return a concrete class that
// derives from ISerialNumber, or NULL
}
virtual void DoSerialNumberTypeStuff() = 0;
};
class SerialNumberedObject
{
public:
bool Initialise( const string& serialNum )
{
m_pNumber = ISerialNumber::Create( serialNum );
return m_pNumber != NULL;
}
void DoThings()
{
m_pNumber->DoSerialNumberTypeStuff();
}
private:
ISerialNumber* m_pNumber;
};
(As this was a question on more advanced concepts, protecting from null/invalid pointer issues is left as an exercise for the reader.)
Why bother with inheritance here? As far as I can see the behaviour is the same for all Chips instances. That behaviour is that the flavour is defined by the serial number.
If the serial number only changes a couple of things then you can inject or lookup the behaviours (std::function) at runtime based on the serial number using a simple map (why complicate things!). This way common behaviours are shared among different chips via their serial number mappings.
If the serial number changes a LOT of things, then I think you have the design a bit backwards. In that case what you really have is the serial number defining a configuration of the Chips, and your design should reflect that. Like this:
class SerialNumber {
public:
// Maybe use a builder along with default values
SerialNumber( .... );
// All getters, no setters.
string getFlavour() const;
private:
string flavour;
// others (package colour, price, promotion, target country etc...)
}
class Chips {
public:
// Do not own the serial number... 'tis shared.
Chips(std::shared_ptr<SerialNumber> poSerial):m_poSerial{poSerial}{}
Chips(int shelf, SerialNumber oSerial):m_poSerial{oSerial}, m_nShelf{shelf}{}
string GetFlavour() {return m_poSerial->getFlavour()};
int GetShelf() {return m_nShelf;}
protected:
std::shared_ptr<SerialNumber> m_poSerial;
int m_nShelf;
}
// stores std::shared_ptr but you could also use one of the shared containers from boost.
Chips pringles{ chipMap.at("standard pringles - sour cream") };
This way once you have a set of SerialNumbers for your products then the product behaviour does not change. The only change is the "configuration" which is encapsulated in the SerialNumber. Means that the Chips class doesn't need to change.
Anyway, somewhere someone needs to know how to build the class. Of course you could you template based injection as well but your code would need to inject the correct type.
One last idea. If SerialNumber ctor took a string (XML or JSON for example) then you could have your program read the configurations at runtime, after they have been defined by a manager type person. This would decouple the business needs from your code, and that would be a robust way to future-proof.
Oh... and I would recommend NOT using Hungarian notation. If you change the type of an object or parameter you also have to change the name. Worse you could forget to change them and other will make incorrect assumptions. Unless you are using vim/notepad to program with then the IDE will give you that info in a clearer manner.
#user1158692 - The party instantiating Chips only needs to know about SerialNumber in one of my proposed designs, and that proposed design stipulates that the SerialNumber class acts to configure the Chips class. In that case the person using Chips SHOULD know about SerialNumber because of their intimate relationship. The intimiate relationship between the classes is exactly the reason why it should be injected via constructor. Of course it is very very simple to change this to use a setter instead if necessary, but this is something I would discourage, due to the represented relationship.
I really doubt that it is absolutely necessary to create the instances of chips without knowing the serial number. I would imagine that this is an application issue rather than one that is required by the design of the class. Also, the class is not very usable without SerialNumber and if you did allow construction of the class without SerialNumber you would either need to use a default version (requiring Chips to know how to construct one of these or using a global reference!) or you would end up polluting the class with a lot of checking.
As for you complaint regarding the shared_ptr... how on earth to you propose that the ownership semantics and responsibilities are clarified? Perhaps raw pointers would be your solution but that is dangerous and unclear. The shared_ptr clearly lets designers know that they do not own the pointer and are not responsible for it.

Sort function which takes a vector of pointers to an interface class

I've recently begun learning c++ (no prior programming knowledge). I've used the book "Jumping into c++" By Alex Allain and i've found it most useful! However i've reached the chapters of classes, inheritence and polymorphism, and while i do understand most of it I just cannot wrap my head around this one problem.
In the book I am asked to solve the following problem:
Implement a sort function that takes a vector of pointers to an interface class, Comparable,
that defines a method, compare(Comparable& other), and returns 0 if the objects are the
same, 1 if the object is greater than other, and -1 if the object is less than other. Create a class
that implements this interface, create several instances, and sort them. If you're looking for
some inspiration for what to create—try a HighScoreElement class that has a name and a
score, and sorts so that the top scores are first, but if two scores are the same, they are sorted
next by name.
I've created the classes Comparable and HighScores:
class Comparable {
public:
virtual int compare(Comparable& other)=0;
};
class HighScore : public Comparable {
public:
HighScore(int, std::string);
virtual int compare(Comparable& other);
private:
int highscore;
std::string name;
};
If i try to overwrite the inherited function in HighScore, i am not able to compare, for instance the int highscore, with the int highscore of (Comparable& other), since i cannot access the other.highscore. Example below:
int HighScore::compare(Comparable& other){
if (highscore == other.highscore) {
return 0;
}
//...
}
I thought i could maybe change the virtual method to something like:
int HighScore::compare(HighScore& other){
if (highscore == other.highscore) {
return 0;
}
//...
}
Since that would allow me to access other.highscore (and i had hoped that i would work since HighScore also can be considered a Comparable. But alas no such luck. What should I do, i litterally have no clue on how to continue and i would appreciate any help i can get. Thanks :)
Indeed, trying to choose behaviour based on the run-time type of two or more objects is a bit fiddly in a single-dispatch language like C++.
The simplest solution is to use RTTI to determine whether the other object has a type comparable with ours:
int HighScore::compare(Comparable& other){
int other_highscore = dynamic_cast<HighScore&>(other).highscore;
if (highscore == other_highscore) {
return 0;
}
//...
}
This will throw an exception if the types aren't comparable, which is probably the best you can do.
Alternatively, you could implement a double-dispatch mechanism (such as the "Visitor Pattern"), involving two virtual functions. I'll let you research it yourself, since an example would be long-winded and not particularly inspiring.
Hopefully, you will soon learn how to do this using compile-time generics rather than run-time abstract interfaces, which is much more idiomatic in C++. If the book doesn't teach you that, throw it away and get one of these instead.
You can write a pulic getter function to get the score
class Comparable {
public:
int get_score() const = 0;
//
}
class HighScore : public Comparable {
public:
int get_score() const { return highscore; }
and then use that for comparison.
int HighScore::compare(Comparable& other){
if (highscore == other.get_score()) {
^^^^^^^^^^^
return 0;
}
//...
}
But since only the derived class has highscore member you should probably change what you pass to compare.
int HighScore::compare(HighScore& other)
OR move highscore member to the base class. Whichever males sense to you.
I'd suggest picking another book on the subject. Since this exercise seemed to be vague and doesn't give good understanding on polymorphism. The tricky part is that when you get Comparable in your compare method you have no clue, if it is HighScore or some other derived class. And in case if the class you are attempting to compare is not an instance of HighScore such terms as equal less and greater doesn't have any meaning. Thus there is no way to solve this correctly. You can of course use dynamic_cast to check if it is HighScore, but still if it doesn't there is no good answer if it greater, lesser or equal to something that isn't a HighScore.
Just imagine that there is something like class Color : public Comparable { exists. What should you return in case if you get Color to be compared with HighScore? Is blue bigger than 10, or Yellow less than 15, what red is equal to?

How to apply DOP and keep a nice user interface?

Currently I want to optimize my 3d engine for consoles a bit. More precisely I want to be more cache friendly and align my structures more data oriented, but also want to keep my nice user interface.
For example:
bool Init()
{
// Create a node
ISceneNode* pNode = GetSystem()->GetSceneManager()->AddNode("viewerNode");
// Create a transform component
ITransform* pTrans = m_pNode->CreateTransform("trans");
pTrans->SetTranslation(0,1.0f,-4.0f);
pTrans->SetRotation(0,0,0);
// Create a camera component
ICamera* pCam = m_pNode->CreateCamera("cam", pTrans);
pCam->LookAt(Math::Vec3d(0,0,0));
// And so on...
}
So the user can work with interface pointers in his code.
BUT
In my engine I currently store pointers to scene nodes.
boost::ptr_vector<SceneNode> m_nodes
So in data oriented design it's good practice to have structs of arrays and not arrays of structs. So my node gets from...
class SceneNode
{
private:
Math::Vec3d m_pos;
};
std::vector<SceneNode> m_nodes;
to this...
class SceneNodes
{
std::vector<std::string> m_names;
std::vector<Math::Vec3d> m_positions;
// and so on...
};
So I see two problems here if I want to apply DOP.
Firstly how could I keep my nice user interface without having the user to work with IDs, indexes and so on?
Secondly how do I handle relocations of properties when some vectors resize without letting users interface pointers point to nirvana?
Currently my idea is to implement a kind of handle_vector from which you get a handle for persistent "pointers":
typedef handle<ISceneNodeData> SceneNodeHandle;
SceneNodeHandle nodeHandle = nodeHandleVector.get_handle(idx);
So when the intern std::vector resizes, it updates its handles.
A "handle" stores a pointer to the actual object and the "->" operator is overloaded to achive a nice wrapping. But this approach sounds a bis complicated to me?!
What do you think? How to keep a nice interface, but keep thinks contiguous in memory for better cache usage?
Thanks for any help!
You will need to use smarter handles than raw pointers. There is no way around it with DOP.
This means:
class SceneNode
{
public:
std::string const& getName() const { mManager->getSceneName(mId); }
void setName(std::string const& name) { mManager->setSceneName(mId, name); }
// similar with other data
private:
ISceneManager* mManager;
size_t mId;
};
One very good point though: the user cannot accidently call delete on one of the pointer you returned now. That's why smart handles are always better.
On the other hand: how are you going to deal with the lifetime of the pointee of mManager is another issue :-)
For those interested in a practical example of DOP, have a look at this fantastic presentation from Niklas Frykholm => http://bitsquid.blogspot.com/2010/05/practical-examples-in-data-oriented.html
This helped me to implement my scene graph in a data oriented manner.

Good practice for choosing an algorithm randomly with c++

Setting:
A pseudo-random pattern has to be generated. There are several ways / or algorithms availible to create different content. All algorithms will generate a list of chars (but could be anything else)... the important part is, that all of them return the same type of values, and need the same type of input arguments.
It has to be possible to call a method GetRandomPattern(), which will use a random one of the algorithms everytime it is called.
My first aproach was to put each algorithm in it's own function and select a random one of them each time GetRandompattern() is called. But I didn't come up with another way of choosing between them, than with a switch case statement which is unhandy, ugly and inflexible.
class PatternGenerator{
public:
list<char> GetRandomPattern();
private:
list<char>GeneratePatternA(foo bar);
list<char>GeneratePatternB(foo bar);
........
list<char>GeneratePatternX(foo bar);
}
What would be a good way to select a random GeneratePattern function every time the GetRandomPattern() method is called ?
Or should the whole class be designed differently ?
Thanks a lot
Create a single class for each algorithm, each one subclassing a generator class. Put instances of those objects into a list. Pick one randomly and use it!
More generically, if you start creating several alternative methods with the same signature, something's screaming "put us into sibling classes" at you :)
Update
Can't resist arguing a bit more for an object-oriented solution after the pointer-suggestion came
Imagine at some point you want to print which method created which random thing. With objects, it's easy, just add a "name" method or something. How do you want to achieve this if all you got is a pointer? (yea, create a dictionary from pointers to strings, hm...)
Imagine you find out that you got ten methods, five of which only differ by a parameter. So you write five functions "just to keep the code clean from OOP garbage"? Or won't you rather have a function which happens to be able to store some state with it (also known as an object?)
What I'm trying to say is that this is a textbook application for some OOP design. The above points are just trying to flesh that out a bit and argue that even if it works with pointers now, it's not the future-proof solution. And you shouldn't be afraid to produce code that talks to the reader (ie your future you, in four weeks or so) telling that person what it's doing
You can make an array of function pointers. This avoids having to create a whole bunch of different classes, although you still have to assign the function pointers to the elements of the array. Any way you do this, there are going to be a lot of repetitive-looking lines. In your example, it's in the GetRandomPattern method. In mine, it's in the PatternGenerator constructor.
#define FUNCTION_COUNT 24
typedef list<char>(*generatorFunc)(foo);
class PatternGenerator{
public:
PatternGenerator() {
functions[0] = &GeneratePatternA;
functions[1] = &GeneratePatternB;
...
functions[24] = &GeneratePatternX;
}
list<char> GetRandomPattern() {
foo bar = value;
int funcToUse = rand()%FUNCTION_COUNT;
functions[funcToUse](bar);
}
private:
generatorFunc functions[FUNCTION_COUNT];
}
One way to avoid switch-like coding is using Strategy design pattern. As example:
class IRandomPatternGenerator
{
public:
virtual list<int> makePattern(foo bar);
};
class ARandomPatternGenerator : public IRandomPatternGenerator
{
public:
virtual list<int> makePattern(foo bar)
{
...
}
};
class BRandomPatternGenerator : public IRandomPatternGenerator
{
public:
virtual list<int> makePattern(foo bar)
{
...
}
};
Then you can choose particular algorithm depending on runtime type of your RandomPatternGenerator instance. (As example creating list like nicolas78 suggested)
Thank you for all your great input.
I decided to go with function pointers, mainly because I didn't know them before and they seem to be very powerfull and it was a good chance to get to know them, but also because it saves me lot of lines of code.
If I'd be using Ruby / Java / C# I'd have decided for the suggested Strategy Design pattern ;-)
class PatternGenerator{
typedef list<char>(PatternGenerator::*createPatternFunctionPtr);
public:
PatternGenerator(){
Initialize();
}
GetRandomPattern(){
int randomMethod = (rand()%functionPointerVector.size());
createPatternFunctionPtr randomFunction = functionPointerVector.at( randomMethod );
list<char> pattern = (this->*randomFunction)();
return pattern;
}
private:
void Initialize(){
createPatternFunctionPtr methodA = &PatternGenerator::GeneratePatternA;
createPatternFunctionPtr methodB = &PatternGenerator::GeneratePatternB;
...
functionPointerVector.push_back( methodA );
functionPointerVector.push_back( methodB );
}
list<char>GeneratePatternA(){
...}
list<char>GeneratePatternB(){
...}
vector< createPattern > functionPointerVector;
The readability is not much worse as it would have been with the Design Pattern Solution, it's easy to add new algorithms, the pointer arithmetics are capsuled within a class, it prevents memory leaks and it's very fast and effective...