new Struct array on free store

Hi, I am working on a bit of gaming code and have run into a small problem ( more of a misunderstanding) I am using allegro/c++ but allegro shouldn't come into play for this concern.

I have a struct for the enemy objects and i want to make lets say 10 enemies. With my struct like this(just an example):
1
2
3
4
5
6
typedef struct ENEMY
{
    int dir, alive;
    int x,y;
    //int etc.........
}ENEMY;


So when I create the array of ENEMY, I can do so like this:

ENEMY *guard[10];

Okay that is fine. Now I want to do the same thing, but this time on the free store so that I can delete them at the end of the level. Now I try this:

ENEMY * guard[10] = new ENEMY;

This does not work. It gives an error of :

error C2440: 'initializing' : cannot convert from 'ENEMY *' to 'ENEMY *[2]'

Is there an easy way to correct this? Am I missing something simple to create this struct array on the free store?

Thank you for all comments/suggestions in advance!! :)


Last edited on
ENEMY* guard = new ENEMY[ 10 ];
This -> ENEMY * guards[10]; is not an array of ENEMYs. It's an array of pointers to ENEMY.

This -> ENEMY guards[10]; is an array of 10 ENEMYs.

If you want to decide the number of enemies during run-time, you have to do it like this:

Declare an ENEMY pointer -> ENEMY * guards;

Then reserve memory for n ENEMYs -> guards=new ENEMY[n];

Then delete it after you're done -> delete[] guards;
Last edited on
wow! thanks so much r0shi, it worked. I can not type how appreciative I am! As usual another problem arose...

I have multiple enemy types and they are not all arrays.

for example in main i have something like:
 
boss = (ENEMY*)malloc(sizeof(ENEMY));

and then what you told me
1
2
ENEMY *zombie;
zombie = new ENEMY[ENEMYCOUNT];


so there is a boss, and ENEMYCOUNT = 10 enemies. When I initialize them for the single boss I have:
1
2
3
4
5
6
void init_enemy(ENEMY * enemy)
{
		enemy->x = 200;
		enemy->y = 300;
		//etc...
}


for the 10 enemies of course I want their positions to be different so I want to overload the init_enemy function to handle this array of 10 guys. This is what I wanted to type:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void init_enemy(ENEMY * enemy[])
{
	for(int n = 0 ; n< ENEMYCOUNT ; n++)
	{
		enemy[n]->curframe=0;
		enemy[n]->framecount=0;
		//etc...
	}
	for(int n = 0 ; n< ENEMYCOUNT ; n++)
	{
		enemy[n]->x = 200*2 + 20*n;
		enemy[n]->y = 300;
	}
}


something like this but it will not work. It actually builds but the first time it tries to access guard[1] there is no set value which means it used the first function and not the 2nd one overloading it. The guard is getting passed the same as boss, pointer to an object of ENEMY, not an array...
This is how I am calling them:
1
2
init_enemy(boss);
init_enemy(guard);

Thanks again for the previous response!
okay so I actually used my head and figured it out after reading what I wrote haha. If any one is having the same problem, this is how i fixed it:

I have a different overloaded function like so:
1
2
3
4
5
6
7
8
init_enemy(ENEMY * enemy , int n)
{
for (n = 0 ; n < ENEMYCOUNT ; n++)
{
enemy[n].x = 200;
etc..
}
}


Again thanks for your responses! :)
I think that here:

1
2
3
4
5
6
7
8
init_enemy(ENEMY * enemy , int n)
{
    for (n = 0 ; n < ENEMYCOUNT ; n++)
    {
        enemy[n].x = 200;
        //etc..
    }
}

you mean:

1
2
3
4
5
6
7
8
init_enemy(ENEMY * enemy , int ENEMYCOUNT)
{
    for (int n = 0 ; n < ENEMYCOUNT ; n++)
    {
        enemy[n].x = 200;
        //etc..
    }
}

But there is another problem... Suppose you want to make 10 zombies and 10 dragons. How are you going to do it? This approach:

1
2
3
4
5
ENEMY * zombies;
ENEMY * dragons;

init_enemy(zombies,10);
init_enemy(dragons,10);

won't work... You'll end up with zombies and dragons being the same thing... There's the easy way to solve this and the hard way. The easy way is having something like an id for your monsters that shows what kind of monsters they are:

1
2
3
4
const int MT_BANDIT=0; //MT stands for Monster Type
const int MT_ZOMBIE=1;
const int MT_DRAGON=2;
//etc... 

or you could use an enumeration, like this:

enum {MT_BANDIT=0, MT_ZOMBIE=1, MT_DRAGON=2 /*etc...*/};

Then, implement your init_enemy function like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
init_enemy(ENEMY * enemy , int count, int type)
{
    int x,y; //stats

    switch (type)
    {
        case MT_BANDIT:
            x=10; y=20; break;
        case MT_ZOMBIE:
            x=20;
            y=15;
            break;
        case MT_DRAGON:
            x=50; y=40;
    }

    for (int i=0; i<count; i++)
    {
        enemy[count].x=x;
        enemy[count].y=y;
        //etc...
    }
}

Info on switch -> http://cplusplus.com/doc/tutorial/control/

The hard (but more efficient in many ways) way involves inheritance, i.e. making every enemy type a separate class derived from ENEMY:

1
2
3
struct BANDIT: public ENEMY {/*...*/};
struct ZOMBIE: public ENEMY {/*...*/};
//etc... 

Maybe it's too early for you to jump to this but if you really want you can take a look here:

http://cplusplus.com/doc/tutorial/inheritance/
http://cplusplus.com/doc/tutorial/polymorphism/
Last edited on
wow this is great info! Yeah, it would be a much better idea to use inheritance. I really need to split all the code into some headers. There is so much right now I was just trying to quick fix which I hate to do because it makes it even worse come clean up time. I plan on doing that soon. Actually I am using the switch statement right now, (without enum makes it even more confusing! hah) using it for the personality of the guard ( type 1 is aggressive runs right at you, 2 strafes , 3 takes cover etc..)

Using that switch case for initialization would be useful though wouldn't I run into the same problem before, where some enemies dont have array elements and it would cause an error when my ENEMY * boss tried to do the part:
1
2
3
4
5
6
for (int i=0; i<count; i++)
    {
        enemy[count].x=x;
        enemy[count].y=y;
        //etc...
    }

?
You have been so helpful , thank you so much!!
If I understand what you mean, no, you'd have no problem with that. If you only have one unit for initialization, you can do it like this without problem:

1
2
3
4
ENEMY * boss;
boss=new ENEMY;

init_enemy(boss,1,MT_BOSS);

The explanation is that array[index] is a synonym for *(array+index). In this case, i only takes the value zero in the for loop, and boss[0] is interpreted as *(boss+0) i.e. *boss, which is exactly what you want :)
Last edited on
oh yeah that is a smart way to do it, your lesson gave me player.programming += 1;
:) thanks so much!
Topic archived. No new replies allowed.