Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling 'units' in an RTS game - c++

Tags:

c++

I'm currently in the process of making a simple RTS style game in c++.

What i'm wondering is how to handle the creation of new units in the game (ie. making marines from the barrack). How would i store these units?

I was thinking of having a class 'unit' which would then be inherited by specific unit types (ie. marines, firebats, etc) but if i create an array for these (ie. Marines myMarines[20]) that will create a hard cap on these units.

How do i create such an array that can be expanded at will? Thank you!

like image 297
SamHLec Avatar asked Dec 06 '22 16:12

SamHLec


2 Answers

The standard library provides them std::vector template for dynamically resizable arrays. A std::vector<Marine> would be the most straightforward alternative to Marines myMarines[20].

However, you probably don't want a separate list for each unit type. It is highly likely that you will want to store all units in the same list, regardless of their type. std::vector<Unit> would sound like the obvious solution but it is not. The problem is that std::vector stores the objects by value. The following would not work right:

std::vector<Unit> v;
v.push_back(Marine("John Doe"));

The problem is that the Marine object will be copied into a Unit object, which is what the vector stores. This kind of copy results in a what is known as slicing: all the Marine specific members will be lost, and only those that exist in Unit will be stored.

One solution to this problem is to store pointers in the vector because copying pointers does not change the objects they point to. But that brings other problems. To store pointers, this means you'll need to allocate the objects dynamically. And that means that now you are responsible for destroying those objects manually. That's a tiresome and error-prone task.

The solution is to store in the vector objects that destroy the dynamically allocated objects automatically, instead of pointers. These objects are known as smart pointers. The simplest one that exists in the standard library is std::unique_ptr.

std::vector<std::unique_ptr<Unit>> v;
v.emplace_back(new Marine("John Doe"));

This is a C++11 feature. If your compiler doesn't support it you can find alternatives in the Boost libraries. Boost even includes a container that acts pretty much like a std::vector of std::unique_ptrs: boost::ptr_vector. That would be another alternative.

like image 149
R. Martinho Fernandes Avatar answered Dec 22 '22 13:12

R. Martinho Fernandes


You will probably benefit from using an std::vector here. This will allow you to add and remove items at will, and handles dynamic memory allocation internally (without concerning you over the nitty-gritty details!).

Say you want to store a list of marines (denoted by an imaginary class CMarine in the following example):

std::vector<CMarine> marinesList;

Now to add a marine simply do this:

marinesList.push_back( CMarine( <whatever-its-constructor-takes> ) );

To access this marine you can do something like this:

CMarine& marine = marinesList.at( 0 );
marine.someVar = 33;
marine.doMethod();

(I use a reference since CMarine could very well be too bulky to pass around by value efficiently)

You can also loop through all the marines with an iterator like so:

for ( std::vector<CMarine>::iterator _it = marinesList.begin();
                                     _it != marinesList.end(); ++_it );
{
    CMarine& marine = *_it;
    // Now you can do something with this marine reference
}

UPDATE:

If CMarine is polymorphic, that is, it inherits from a superclass (maybe something like CUnit in your case), and you have a 'global' vector of all units - Georg Fritzsche rightly noted that object slicing could occur (if we are storing by value). Instead you might be better off with a vector of CUnit (smart) pointers like this:

std::vector<std::unique_ptr<CUnit>> unitsList;
// To add a marine:
unitsList.push_back( new CMarine( <whatever-its-constructor-takes> ) );

Read more about vectors here.

like image 30
Alex Z Avatar answered Dec 22 '22 13:12

Alex Z