Newbie help - array of pointers to objects as a parameter

Started by
11 comments, last by Zahlman 15 years, 10 months ago
Im very new to programming, and am writing a simple (albiet ambitious first project) game. I have an array of pointers to objects. the objects being the bad guys. initialised as such:
Monster* beastlist[16];

	for (int i = 0; i < gamemap.mapx; i++)
	{
		for (int j = 0; j < gamemap.mapy; j++)
		{
			if (gamemap.map[j] == '*')
			{
				beastlist[beastcounter] = new Monster(i, j);
                                beastcounter++;
				totalbeasts++;
			};
		}
	}
now, for collision detection, i have made a function:
int Coldet::checkpos(int y, int x, Monster *monsterarray[16], char mappos, int totalmonsters)
{
	if (mappos == 'o')
	{
		return -1;
	}
	else if (mappos == 'T')
	{
		return -1;
	}
	else
	{
		if ((Player::getposition('i') == y) && (Player::getposition('j') == x))
			return -3;
		else
		{
			for (objectID = 0; objectID < totalmonsters; objectID++)
			{
				if ((monsterarray[objectID] == 0))
				{
					return 0;
				}
				else if ((monsterarray[objectID]->getposition('i') == y) && (monsterarray[objectID]->getposition('j') == x))
				{
					return objectID;
				}
				else
				{
					return 0;
				}
			}
		}
	}
}
Heres an example of a parameter list:
coldetect.checkpos(Bundy.getposition('i')-1, Bundy.getposition('j'), beastlist, gamemap.map[Bundy.getposition('i')-1][Bundy.getposition('j')], totalbeasts);
This works for detecting all collisions except those with the monsters, where it simply returns a 0. I believe the problem is in how ive passed the array.
Advertisement
First, to answer your question:
the problem is the last return 0 in the loop. If it doesn't collide with the first monster, it returns 0. Put that return outside the loop.


Now, some suggestions:

Having a static array size of 16 isn't very nice. Try using std::vector to store a list of Monster*.

What's up with the getposition('i')? I'd hate to see the current implementation of that function. What's wrong with, e.g., getposition_i(), or even better, have getposition() return a structure/class with x/y or i/j members:
getposition().i and getposition().j. For good measure, overload the == operator so you can directly compare getposition() to the position passed to the function.

beastcounter and totalbeasts seem to do the same thing. Why need both?

My suggestion:
struct position{    int x, y;    bool operator==(const position& rhs) const    {        return x == rhs.x && y == rhs.y;    }    position(int _x, int _y) : x(_x), y(_y) {}    position() {}};vector<Monster*> beastlist;for (int x = 0; x < gamemap.mapx; x++)for (int y = 0; y < gamemap.mapy; y++){    if (gamemap.map[x][y] == '*')    {        // This is done this way for exception safety        beastlist.push_back(NULL);        beastlist.back() = new Monster(x,y);    }}int Coldet::checkpos(position& pos, const vector<Monster*> monsters, char mappos){    if (mappos == 'o' || mappos == 'T')    {        return -2;    }    if ((Player::getposition() == pos)    {        return -3;    }    for (size_t i = 0; i < monsters.size(); ++i)    {        if (monsters->getposition() == pos)        {	    return i;	}    }    return -1;}

Note that I've changed -1 to -2 and 0 to -1, because otherwise there'd be no way to distinguish between "no collisions" and "collided with first monster".


And use it like this:
position pos = Bundy.getposition();pos.y--;coldetect.checkpos(pos, mosters, gamemap.map[pos.x][pos.y]);


Now, isn't that slightly more readable?
Million-to-one chances occur nine times out of ten!
Always use the debugger instead of assuming things. But even without a debugger, can your function ever return anything greater than zero? It cannot.
alright got the collision detection working properly now, thanks :D.
I havn't used a vector before, i'll look into it, if it means the number of elements in the array is defined at runtime, ill love it, and have a fair few other places i could use it in this program.
i don't see anything wrong with the getposition function to be honest, you just tell it the coordinate you want the position in (i, or j) and it outputs the coordinate, i did originally try to have it return the position array, but couldn't get that working (that was ages ago, on the other side of some recently finished exams, can't remember the full details). But it's a member function of the beast class, i don't see how having it as a seperate struct would work (note: as i said, very new to programming, never used a struct, and not really sure about what they are.)

beastcounter is used multiple times in loops. total beasts isn't changed after all of the beasts have been initialised, it remains the total number of beasts. (probably redundant if i used vector).

About using the debugger - for some reason if i try using a debug build, i get access violation errors, and i don't with release builds, im not sure why.

By the way, if you want to see the game im working on you can download it here. (The last couple of versions have had 6 downloads, the latest one had 3, and i could name them all... im not above shameless plugs). Any suggestions are welcome.

Thanks for the help, and the quick reply, i can now start trying to figure out other holes introduced by multiple enemies :D.
Quote:Original post by Hernan13
I havn't used a vector before, i'll look into it, if it means the number of elements in the array is defined at runtime, ill love it, and have a fair few other places i could use it in this program.

Yes it does. Use it :)

Quote:Original post by Hernan13
i don't see anything wrong with the getposition function to be honest, you just tell it the coordinate you want the position in (i, or j) and it outputs the coordinate, i did originally try to have it return the position array, but couldn't get that working (that was ages ago, on the other side of some recently finished exams, can't remember the full details).

The problem is that you pass what you want as a character. My guess is the code looks somewhat like:
int getposition(char what) {    if (what == 'i') return i;    if (what == 'j') return j;    return -1;}

Which is very ugly.

Quote:Original post by Hernan13
But it's a member function of the beast class, i don't see how having it as a seperate struct would work (note: as i said, very new to programming, never used a struct, and not really sure about what they are.)

A struct is, basically, a type that defines a grouping of variables. Instead of moving all seperate variable about, you just have to work with one variable, a structure. In C++ they are identical to classes, but the difference is mostly conceptual. Think of structures as groups of variables and as classes as 'black boxes' that do stuff.

In my example, I defined a structure holding the x and y value of a 'position'. Then, you can just define and work with positions as one variable. So, you can have a member variable of type 'position' and return that by getposition():
struct position{    int x, y;};class Monster{    position m_position;public:    const position& getposition() const {        return m_position;    }    Monster(int x, int y)    {        m_position.x = x;        m_position.y = y;    }};


Use it, for instance, as:
// Create a monster at position 5,10Monster monster(5,10);// Get (a reference to) the monster's positionconst position& pos = monster.getposition();// Print the monster's positioncout << "The monster is at: " << pos.x << "," << pos.y << endl;

It's very useful and trust me, structures are a no-brainer once you know what they do. Everyone uses them.

Quote:Original post by Hernan13
beastcounter is used multiple times in loops. total beasts isn't changed after all of the beasts have been initialised, it remains the total number of beasts. (probably redundant if i used vector).

Yes, the vector has the size() function.
Million-to-one chances occur nine times out of ten!
ah, sweet, that looks pretty useful, thanks.
i just have a couple of questions about where you've defined the == operator for the position struct.
1. What does the const at the end of it do?
2. what does all this do?
Quote:position(int _x, int _y) : x(_x), y(_y) {}
position() {}
Quote:Original post by Hernan13
i just have a couple of questions about where you've defined the == operator for the position struct.
1. What does the const at the end of it do?
2. what does all this do?
Quote:position(int _x, int _y) : x(_x), y(_y) {}
position() {}


1.

A member function marked as const means that the function is not allowed modify the object it is called on. It also means that you can now call the member function on const values or references of this type. It is considered good practise to be const correct and mark all member functions not intending to modify the calling object as const.

2.

The first constructor uses an initialisation list to initialise the members. This is the preferred way to do initialisation - and on occasion the only way. Here are some links: one two.

The second is an inline empty default constructor. It means you can create position objects without specifying an x or y position. I would have used an initialisation list here to explicitly set x and y to 0 or some other sane value.
Quote:Original post by Hernan13

About using the debugger - for some reason if i try using a debug build, i get access violation errors, and i don't with release builds, im not sure why.



In this case you have something very wrong, you may be accesing something you shouldn't. You are probably writing or reading out of array bounds. Reason why you get this in debug build only is that in debug such things are checked, in release they are not and you are just being lucky. They will sure come up later and they will be much harder to find. I strongly suggest running debug build and correct all errors. It may be huge pain in the ass at the beginning but will have to do it sooner or later. And sooner is much much better :)

hmm, now it's not giving access violations for debugging, but i think i know what the problem is. it works fine when run from the debug executable, but not when running a new instance from within VS. The problems its having seem to be because it can't find the files it needs (this game uses a lot of text files for things, the idea is for it to be very customisable.) Do files need to be somewhere else for executing from within VS?

This topic is closed to new replies.

Advertisement