Stuck with vectors

The Partridge Family were neither partridges nor a family. Discuss.
Paul
Posts: 18
Joined: December 31st, 2021, 1:45 am

Stuck with vectors

Post by Paul » January 10th, 2022, 12:55 am

Hi, I'm still working on my space strategy game and I've ran into another problem and I don't know where to begin to fix this one. I've converted almost all of my arrays to vectors (as was suggested by albinopapa, thanks very much btw). But now I'm getting an error "can't decrement vector iterator before begin". The set up goes fine, the problem seems to happen when the game loads the first real turn. When the game enters the load function it goes into a for loop that is supposed to set up all the planets and ships for the first turn. I've set up break points and it reaches line 543 of Game.cpp and doesn't seem to even go into the update_food function in Planet.cpp.

To anyone who's willing to help, you need to hit start turn and it will take you to the start up. From there you need to click on a tile (on the planet) to place the first city (a 'C' should appear on the tile you clicked), and then a farm on one of the tiles next to the city. You then need to select one of the 6 jobs and click person 1, and do the same for person 2 and 3. You then need to select a starting project and then hit end turn in the bottom right. The program will crash after that.

If you need more information or clarification I am more than happy to provide it.
Attachments
Paul's Space Empire Strategy Game.zip
(397.05 KiB) Downloaded 145 times

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Stuck with vectors

Post by albinopapa » January 10th, 2022, 11:37 am

Make sure to use assert() a lot, especially when you are accessing arrays.
I suggest using std::array<T, size> instead of C arrays map[ size ].

They are little safer, usually won't let you access outside the bounds of the array. They also have the added benefit of being able to use them in the STD algorithms, ranged base for loops and they have built in iterators.

If you don't need to traverse the vectors in reverse order, you can use a ranged for loop:

Code: Select all

for( auto& object : objects ){
    object.DoSomething();
}
Instead of:

Code: Select all

for( std::vector<Object>::iterator object_it; object_it != objects.end(); ++object_it ){
    object_it->DoSomething();
}
Also, if you ever get tired of writing std::vector<Object>::reverse_iterator when that's what you really
want, you can use auto.

Code: Select all

for( auto object_it = objects.rbegin(); object_it != objects.end(); ++object_it )
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Stuck with vectors

Post by albinopapa » January 10th, 2022, 11:39 am

Basically, there is a line of code that uses a negative number to access a map when you click on one of the tiles...that's what triggered for me anyway. The forum kicked me out for being idle while writing and when I submitted it all went away and I am too tired to find it again.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Paul
Posts: 18
Joined: December 31st, 2021, 1:45 am

Re: Stuck with vectors

Post by Paul » January 10th, 2022, 8:09 pm

Ok, thanks for the help! That should be enough to point me in the right direction. Sorry about your trouble with submitting. I got your comment about using assert, std::array<T,size>, using ranged for loops, and auto.

I'll try changing some of my vectors to the std::array<T,size> if the don't need to change in size throughout the game. I'll also look for a negative number to access a map using assert.

Paul
Posts: 18
Joined: December 31st, 2021, 1:45 am

Re: Stuck with vectors

Post by Paul » January 10th, 2022, 10:56 pm

Did you ever get to end turn? I got an error sometimes when I clicked on a planet on the galaxy map, but that was an xmemory error. Maybe that's the error that you got. I should probably fix that error too, but I was more talking about the error after you end the turn because that one always occurs at least on my version of visual studio 2022.

Paul
Posts: 18
Joined: December 31st, 2021, 1:45 am

Re: Stuck with vectors

Post by Paul » January 10th, 2022, 11:33 pm

Damn, changing to ranged for loops seems to have fixed the vector issue! Thanks again!

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Stuck with vectors

Post by albinopapa » January 11th, 2022, 8:51 am

Awesome.

Was really trying to think about why you would be using reverse_iterators. The only thing I've come up with is removing elements from a container while looping through them, but there is a different way of doing it that is a little bit less code.

Code: Select all

// First, remove_if moves elements to the end of the vector and returns the first moved object.
auto new_end = std::remove_if( objects.begin(), objects.end(), [&]( Object const& object ){ return object.is_dead(); } );

// The, we remove all the elements from new_end to objects.end()
objects.erase( last_ter, objects.end() );
One of the nice things about the ranged version of erase is you don't have to check if new_end is valid. If it matches objects.end(), the loop inside that function is skipped.

One other suggestion and this one is pretty small, but arrays and vectors are multiples of items, so it makes sense to use a plural form...std::vector<Person> persons. This way when you do a ranged for loop or accessing a single element, you can use the singular form...for( auto& person : persons ). Just a suggestion, one of the hardest parts of programming sometimes is naming things...especially when you've already used a name somewhere else.

A naming convention I have started to settle into, this isn't a suggestion but more of an example, is:
member variables start with m_
function parameters end in _
class names I usually capitalize
function names are lower case
local variables ( variables declared inside functions ) are shortened to no less than 3 characters.
pos -> position
vel -> velocity
clr -> color

Code: Select all

class Hero{
public:
    void update( float delta_time_ ){
        auto new_vel = m_velocity * delta_time_;

        if( m_bullets > 1000 )
            new_vel *= .9f;

        m_position += new_vel;
    }
    Vec2 const& position()const{ return m_position; }
    Vec2 const& velocity()const{ return m_velocity; }
private:
    Vec2 m_position = {};
    Vec2 m_velocity = {};
    float m_health = 100.f;
    std::uint32_t m_num_bullets = 20u;
};
Deciding on a naming convention really helped alleviate some of the headaches I had in the beginning. I was pretty resistant to a few of these like prefacing member data with m_, but I gave in because I wanted to name function names as if they were variables instead of
get_position() and
set_position( Vec2 const& )

it would be

Vec2 const& position()const;
void position( Vec2 const& position_ );


You'll also find that there are times where not using a const& instead of a & will not work. For instance, trying to pass a temporary to a normal & ( reference ), you get an error. Const& ( constant reference ) are a special case that extends the life of the temporary to the function call. Basically, if you aren't going to change the value you are passing, then the function signature should be Object const& ( or const Object& object ). This allows for passing temporaries as well as signifying that the object you're passing won't be altered. You don't need to do this with small types like int/float and such, but it won't affect anything if you do it.

Anyway, as you can see I like to ramble. Glad you got things going again. Assert is definitely your friend when you are starting out. I took the hard way, set a break point and step through the code line by line. If it was more difficult to find, I'd make an if block that would trip given some error condition and set my break point inside there. I have gotten pretty decent at debugging projects though, but it's painfully slow.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Paul
Posts: 18
Joined: December 31st, 2021, 1:45 am

Re: Stuck with vectors

Post by Paul » January 11th, 2022, 9:30 pm

Ya a naming convention isn't a bad idea at all, I'll definitely consider it. Keep rambling lol, your ramblings contain useful information haha.

Unfortunately, I've ran into a bunch more errors. I'm trying to add a List of Buttons that are attached to either a Location or an Action so that when you click on a Button in a List it has an associated Location (which I can use to find a Planet or Ship) or Action that I can then use to perform actions on.

Everything compiled fine when I just had one List class and one Button class, but to make the attachments I mentioned above I made 2 more button classes that inherit from Button called LocationButton and ActionButton and 2 more List classes that contain the new types of Buttons called LocationList and ActionList. Now there's a bunch of errors and it doesn't compile.

The errors I get upon build are:
- error C3646: 'action_list': unknown override specifier
- error C4430: missing type specifier - int assumed
- error C2039: 'action_list': is not a member of 'Ship'
- error C2504: 'Button': base class undefined
- error C2976: 'std::vector': too few template arguments

Maybe there's a better way of doing this that would be less prone to errors? Or maybe I just don't understand something inheritance or circular inclusion?

Paul
Posts: 18
Joined: December 31st, 2021, 1:45 am

Re: Stuck with vectors

Post by Paul » January 11th, 2022, 9:35 pm

Ya a naming convention isn't a bad idea at all, I'll definitely consider it. Keep rambling lol, your ramblings contain useful information haha.

Unfortunately, I've ran into a bunch more errors. I'm trying to add a List of Buttons that are attached to either a Location or an Action so that when you click on a Button in a List it has an associated Location (which I can use to find a Planet or Ship) or Action that I can then use to perform actions on.

Everything compiled fine when I just had one List class and one Button class, but to make the attachments I mentioned above I made 2 more button classes that inherit from Button called LocationButton and ActionButton and 2 more List classes that contain the new types of Buttons called LocationList and ActionList. Now there's a bunch of errors and it doesn't compile.

The errors I get upon build are:
- error C3646: 'action_list': unknown override specifier
- error C4430: missing type specifier - int assumed
- error C2039: 'action_list': is not a member of 'Ship'
- error C2504: 'Button': base class undefined
- error C2976: 'std::vector': too few template arguments

Maybe there's a better way of doing this that would be less prone to errors? Or maybe I just don't understand something inheritance or circular inclusion?
Attachments
Paul's Space Empire Strategy Game.zip
(383.95 KiB) Downloaded 135 times

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Stuck with vectors

Post by albinopapa » January 12th, 2022, 4:30 am

Code: Select all

#include "Action.h"
#include "Colors.h"
#include "Font.h"	    // ->	"Surface.h"			-> "Colors.h"
						//		"Location.h"		
						//		"Graphics.h"		-> "ChiliException.h"
						//							   "ChiliWin.h"
						//							   "Colors.h"
						//							   "Rect.h"
						//							   "Surface.h"			-> "Colors.h"

#include "Graphics.h"   // ->	"ChiliException.h"	   
						//		"ChiliWin.h"
						//		"Colors.h"
						//		"Rect.h"
						//		"Surface.h"			-> "Colors.h"

#include "Mouse.h"
#include "Planet.h"		// ->	"Action.h"
						//		"ActionList.h"		-> "ActionButton.h"		->	"Button.h"
						//		"Font.h"			->	"Surface.h"			->	"Colors.h"
						//								"Location.h"		
						//								"Graphics.h"		->	"ChiliException.h"
						//														"ChiliWin.h"
						//														"Colors.h"
						//														"Rect.h"
						//														"Surface.h"			-> "Colors.h"
						//		
						//		"Graphics.h"		-> "ChiliException.h"
						//							   "ChiliWin.h"
						//							   "Colors.h"
						//							   "Rect.h"
						//							   "Surface.h"			-> "Colors.h"
						//		"Location.h"
						//		"Person.h"
						//		"Project.h"

#include "Rect.h"
#include "Ship.h"		// ->	"Action.h"
						//		"ActionList.h"		-> "ActionButton.h"		-> #include "Button.h"
						//		"Colors.h"
						//		"Location.h"
						//		"Person.h"

#include <string>
Here's a tree I made of just the #include lines in Button.h. If you look at #include "Ship.h" and #include "Planet.h" they both indirectly #include "Button.h" through ActionButton.h.

My suggestion would be then to make Button generic so that it doesn't rely on anything else from the core game and only on the framework ( Rect, Location and Color for example ). In ActionButton, you can include Button.h.

You also have duplicate definitions of ActionList functions. One set in ActionList.cpp and the other in List.cpp.

I made a diagram of your include files: yED Live
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply